PageRenderTime 53ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/LSO.cs

http://lsotool.googlecode.com/
C# | 369 lines | 354 code | 15 blank | 0 comment | 100 complexity | f9493ff4065f75b93ca54346218a450a MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. namespace LSO
  5. {
  6. static class LSO
  7. {
  8. public class InstructionInfo
  9. {
  10. public string Official;
  11. public string Mnemonic;
  12. public byte Opcode;
  13. public ArgType[] ArgTypes = new ArgType[0];
  14. public InstructionInfo(byte opcode, ArgType[] argtypes)
  15. {
  16. Opcode = opcode;
  17. ArgTypes = argtypes;
  18. }
  19. public InstructionInfo()
  20. {
  21. }
  22. public InstructionInfo(string official, string mnemonic, int opcode, ArgType[] argtypes)
  23. {
  24. Official = official;
  25. Mnemonic = mnemonic;
  26. Opcode = (byte)opcode;
  27. ArgTypes = argtypes;
  28. }
  29. public int NumberOfArgs
  30. {
  31. get
  32. {
  33. return ArgTypes.Length;
  34. }
  35. }
  36. }
  37. public class Instruction
  38. {
  39. public InstructionInfo Info = new InstructionInfo();
  40. public List<Object> Arguments = new List<Object>();
  41. public int Size
  42. {
  43. get
  44. {
  45. int size = 1;
  46. int argcount = Info.ArgTypes.Length;
  47. ArgType type = new ArgType();
  48. for(int i = 0; i < argcount; i++)
  49. {
  50. type = Info.ArgTypes[i];
  51. if (type == ArgType.CodeOffset || type == ArgType.Float
  52. || type == ArgType.Integer || type == ArgType.LocalFrameOffset
  53. || type == ArgType.StateIndex || type == ArgType.StaticFrameOffset
  54. || type == ArgType.UserFunctionIndex)
  55. {
  56. size += 4;
  57. }
  58. else if (type == ArgType.LibFunctionIndexTwoByte)
  59. size += 2;
  60. else if (type == ArgType.LibFunctionIndexByte || type == ArgType.RType
  61. || type == ArgType.Type)
  62. {
  63. size += 1;
  64. }
  65. else if (type == ArgType.String)
  66. {
  67. size += Arguments[i].ToString().Length + 1;
  68. }
  69. }
  70. return size;
  71. }
  72. }
  73. public void FromBytes(byte[] b, int offset)
  74. {
  75. Info = LSO.InstructionByOpcode(b[offset]);
  76. if (Info == null)
  77. throw new Exception("Invalid instruction");
  78. offset++;
  79. Arguments = new List<object>();
  80. int intvalue;
  81. float floatvalue;
  82. short shortvalue;
  83. string stringvalue;
  84. byte[] buffer;
  85. foreach (ArgType type in Info.ArgTypes)
  86. {
  87. if (type == ArgType.CodeOffset
  88. || type == ArgType.Integer || type == ArgType.LocalFrameOffset
  89. || type == ArgType.StateIndex || type == ArgType.StaticFrameOffset
  90. || type == ArgType.UserFunctionIndex)
  91. {
  92. buffer = new byte[4];
  93. Buffer.BlockCopy(b, offset, buffer, 0, 4);
  94. if (BitConverter.IsLittleEndian) Array.Reverse(buffer);
  95. intvalue = BitConverter.ToInt32(buffer, 0);
  96. Arguments.Add(intvalue);
  97. offset += 4;
  98. }
  99. else if (type == ArgType.Float)
  100. {
  101. buffer = new byte[4];
  102. Buffer.BlockCopy(b, offset, buffer, 0, 4);
  103. if (BitConverter.IsLittleEndian) Array.Reverse(buffer);
  104. floatvalue = BitConverter.ToSingle(buffer, 0);
  105. Arguments.Add(floatvalue);
  106. offset += 4;
  107. }
  108. else if (type == ArgType.LibFunctionIndexByte)
  109. {
  110. Arguments.Add(b[offset]);
  111. offset += 2;
  112. }
  113. else if (type == ArgType.LibFunctionIndexTwoByte)
  114. {
  115. buffer = new byte[2];
  116. Buffer.BlockCopy(b, offset, buffer, 0, 2);
  117. if (BitConverter.IsLittleEndian) Array.Reverse(buffer);
  118. shortvalue = BitConverter.ToInt16(buffer, 0);
  119. Arguments.Add(shortvalue);
  120. offset += 2;
  121. }
  122. else if (type == ArgType.LType)
  123. {
  124. Arguments.Add((VariableType)((b[offset] >> 4) & 0x0F));
  125. }
  126. else if (type == ArgType.RType)
  127. {
  128. Arguments.Add((VariableType)(b[offset] & 0x0F));
  129. offset++;
  130. }
  131. else if (type == ArgType.Type)
  132. {
  133. Arguments.Add((VariableType)b[offset]);
  134. offset++;
  135. }
  136. else if (type == ArgType.String)
  137. {
  138. stringvalue = "";
  139. while (b[offset] != 0)
  140. {
  141. stringvalue += Encoding.ASCII.GetString(b, offset, 1);
  142. offset++;
  143. }
  144. offset++;
  145. Arguments.Add(stringvalue);
  146. }
  147. }
  148. }
  149. public byte[] ToBytes()
  150. {
  151. byte[] b = new byte[Size];
  152. b[0] = Info.Opcode;
  153. int offset = 1;
  154. int argcount = Info.NumberOfArgs;
  155. ArgType type = new ArgType();
  156. byte[] buffer;
  157. byte ltype = 0;
  158. for (int i = 0; i < argcount; i++)
  159. {
  160. type = Info.ArgTypes[i];
  161. if (type == ArgType.LType)
  162. {
  163. ltype = Convert.ToByte(Arguments[i]);
  164. ltype = (byte)(ltype << 4);
  165. ltype = (byte)(ltype & 0xF0);
  166. }
  167. else if (type == ArgType.RType)
  168. {
  169. b[offset] = (byte)(ltype | (Convert.ToByte(Arguments[i]) & 0x0F));
  170. offset++;
  171. }
  172. else if (type == ArgType.Type || type == ArgType.LibFunctionIndexByte)
  173. {
  174. b[offset] = Convert.ToByte(Arguments[i]);
  175. offset++;
  176. }
  177. else if (type == ArgType.LibFunctionIndexTwoByte)
  178. {
  179. buffer = BitConverter.GetBytes(Convert.ToInt16(Arguments[i]));
  180. if (BitConverter.IsLittleEndian) Array.Reverse(buffer);
  181. Buffer.BlockCopy(buffer, 0, b, offset, buffer.Length);
  182. offset += buffer.Length;
  183. }
  184. else if (type == ArgType.String)
  185. {
  186. string str = Convert.ToString(Arguments[i]);
  187. buffer = new byte[str.Length + 1];
  188. Buffer.BlockCopy(Encoding.ASCII.GetBytes(str), 0, b, offset, str.Length);
  189. offset += buffer.Length;
  190. }
  191. else if (type == ArgType.Float)
  192. {
  193. buffer = BitConverter.GetBytes(Convert.ToSingle(Arguments[i]));
  194. if (BitConverter.IsLittleEndian) Array.Reverse(buffer);
  195. Buffer.BlockCopy(buffer, 0, b, offset, buffer.Length);
  196. offset += buffer.Length;
  197. }
  198. else
  199. {
  200. buffer = BitConverter.GetBytes(Convert.ToInt32(Arguments[i]));
  201. if (BitConverter.IsLittleEndian) Array.Reverse(buffer);
  202. Buffer.BlockCopy(buffer, 0, b, offset, buffer.Length);
  203. offset += buffer.Length;
  204. }
  205. }
  206. return b;
  207. }
  208. public override string ToString()
  209. {
  210. string s = Info.Official;
  211. if (Arguments.Count > 0)
  212. {
  213. s += " ";
  214. int argcount = Info.ArgTypes.Length;
  215. ArgType type = new ArgType();
  216. for (int i = 0; i < argcount; i++)
  217. {
  218. if (i > 0) s += ", ";
  219. type = Info.ArgTypes[i];
  220. if (type == ArgType.String)
  221. {
  222. s += "\"" + Arguments[i] + "\"";
  223. }
  224. else
  225. {
  226. s += Arguments[i].ToString();
  227. }
  228. }
  229. }
  230. return s;
  231. }
  232. }
  233. public static List<InstructionInfo> InstructionInfos = new List<InstructionInfo>();
  234. public static InstructionInfo InstructionByName(string name)
  235. {
  236. name = name.ToUpper();
  237. foreach (InstructionInfo info in InstructionInfos)
  238. {
  239. if (info.Official == name)
  240. return info;
  241. }
  242. return null;
  243. }
  244. public static InstructionInfo InstructionByOpcode(byte opcode)
  245. {
  246. foreach (InstructionInfo info in InstructionInfos)
  247. {
  248. if (info.Opcode == opcode)
  249. return info;
  250. }
  251. return null;
  252. }
  253. static void AddInstruction(string official, string mnemonic, int opcode, ArgType[] argtypes)
  254. {
  255. InstructionInfo info = new InstructionInfo(official, mnemonic, opcode, argtypes);
  256. InstructionInfos.Add(info);
  257. }
  258. static LSO()
  259. {
  260. AddInstruction("NOOP", "NOP", 0x00, new ArgType[0]);
  261. AddInstruction("POP", "DROP_NUM", 0x01, new ArgType[0]);
  262. AddInstruction("POPS", "DROP_STRING", 0x02, new ArgType[0]);
  263. AddInstruction("POPL", "DROP_LIST", 0x03, new ArgType[0]);
  264. AddInstruction("POPV", "DROP_VECTOR", 0x04, new ArgType[0]);
  265. AddInstruction("POPQ", "DROP_ROTATION", 0x05, new ArgType[0]);
  266. AddInstruction("POPARG", "", 0x06, new ArgType[] { ArgType.Integer });
  267. AddInstruction("POPIP", "", 0x07, new ArgType[0]);
  268. AddInstruction("POPBP", "BUILD_CALL_FRAME", 0x08, new ArgType[0]);
  269. AddInstruction("POPSP", "", 0x09, new ArgType[0]);
  270. AddInstruction("POPSLR", "", 0x0A, new ArgType[0]);
  271. AddInstruction("DUP", "", 0x20, new ArgType[0]);
  272. AddInstruction("DUPS", "", 0x21, new ArgType[0]);
  273. AddInstruction("DUPL", "", 0x22, new ArgType[0]);
  274. AddInstruction("DUPV", "", 0x23, new ArgType[0]);
  275. AddInstruction("DUPQ", "", 0x24, new ArgType[0]);
  276. AddInstruction("STORE", "STORE_L_NUMBER", 0x30, new ArgType[] { ArgType.LocalFrameOffset });
  277. AddInstruction("STORES", "STORE_L_STRING", 0x31, new ArgType[] { ArgType.LocalFrameOffset });
  278. AddInstruction("STOREL", "STORE_L_LIST", 0x32, new ArgType[] { ArgType.LocalFrameOffset });
  279. AddInstruction("STOREV", "STORE_L_VECTOR", 0x33, new ArgType[] { ArgType.LocalFrameOffset });
  280. AddInstruction("STOREQ", "STORE_L_ROTATION", 0x34, new ArgType[] { ArgType.LocalFrameOffset });
  281. AddInstruction("STOREG", "STORE_G_NUMBER", 0x35, new ArgType[] { ArgType.StaticFrameOffset });
  282. AddInstruction("STOREGS", "STORE_G_STRING", 0x36, new ArgType[] { ArgType.StaticFrameOffset });
  283. AddInstruction("STOREGL", "STORE_G_LIST", 0x37, new ArgType[] { ArgType.StaticFrameOffset });
  284. AddInstruction("STOREGV", "STORE_G_VECTOR", 0x38, new ArgType[] { ArgType.StaticFrameOffset });
  285. AddInstruction("STOREGQ", "STORE_G_ROTATION", 0x39, new ArgType[] { ArgType.StaticFrameOffset });
  286. AddInstruction("LOADP", "POP_L_NUMBER", 0x3A, new ArgType[] { ArgType.LocalFrameOffset });
  287. AddInstruction("LOADSP", "POP_L_STRING", 0x3B, new ArgType[] { ArgType.LocalFrameOffset });
  288. AddInstruction("LOADLP", "POP_L_LIST", 0x3C, new ArgType[] { ArgType.LocalFrameOffset });
  289. AddInstruction("LOADVP", "POP_L_VECTOR", 0x3D, new ArgType[] { ArgType.LocalFrameOffset });
  290. AddInstruction("LOADQP", "POP_L_ROTATION", 0x3E, new ArgType[] { ArgType.LocalFrameOffset });
  291. AddInstruction("LOADGP", "POP_G_NUMBER", 0x3F, new ArgType[] { ArgType.StaticFrameOffset });
  292. AddInstruction("LOADGSP", "POP_G_STRING", 0x40, new ArgType[] { ArgType.StaticFrameOffset });
  293. AddInstruction("LOADGLP", "POP_G_LIST", 0x41, new ArgType[] { ArgType.StaticFrameOffset });
  294. AddInstruction("LOADGVP", "POP_G_VECTOR", 0x42, new ArgType[] { ArgType.StaticFrameOffset });
  295. AddInstruction("LOADGQP", "POP_G_ROTATION", 0x43, new ArgType[] { ArgType.StaticFrameOffset });
  296. AddInstruction("PUSH", "PUSH_L_NUMBER", 0x50, new ArgType[] { ArgType.LocalFrameOffset });
  297. AddInstruction("PUSHS", "PUSH_L_STRING", 0x51, new ArgType[] { ArgType.LocalFrameOffset });
  298. AddInstruction("PUSHL", "PUSH_L_LIST", 0x52, new ArgType[] { ArgType.LocalFrameOffset });
  299. AddInstruction("PUSHV", "PUSH_L_VECTOR", 0x53, new ArgType[] { ArgType.LocalFrameOffset });
  300. AddInstruction("PUSHQ", "PUSH_L_ROTATION", 0x54, new ArgType[] { ArgType.LocalFrameOffset });
  301. AddInstruction("PUSHG", "PUSH_G_NUMBER", 0x55, new ArgType[] { ArgType.StaticFrameOffset });
  302. AddInstruction("PUSHGS", "PUSH_G_STRING", 0x56, new ArgType[] { ArgType.StaticFrameOffset });
  303. AddInstruction("PUSHGL", "PUSH_G_LIST", 0x57, new ArgType[] { ArgType.StaticFrameOffset });
  304. AddInstruction("PUSHGV", "PUSH_G_VECTOR", 0x58, new ArgType[] { ArgType.StaticFrameOffset });
  305. AddInstruction("PUSHGQ", "PUSH_G_ROTATION", 0x59, new ArgType[] { ArgType.StaticFrameOffset });
  306. AddInstruction("PUSHIP", "", 0x5A, new ArgType[0]);
  307. AddInstruction("PUSHBP", "PUSH_ARGS_START", 0x5B, new ArgType[0]);
  308. AddInstruction("PUSHSP", "PUSH_ARGS_END", 0x5C, new ArgType[0]);
  309. AddInstruction("PUSHARGB", "LIST_BUILD", 0x5D, new ArgType[] { ArgType.Type });
  310. AddInstruction("PUSHARGI", "PUSH_INTEGER", 0x5E, new ArgType[] { ArgType.Integer });
  311. AddInstruction("PUSHARGF", "PUSH_FLOAT", 0x5F, new ArgType[] { ArgType.Float });
  312. AddInstruction("PUSHARGS", "PUSH_STRING", 0x60, new ArgType[] { ArgType.String });
  313. AddInstruction("PUSHARGV", "PUSH_VECTOR", 0x61, new ArgType[] { ArgType.Float, ArgType.Float, ArgType.Float });
  314. AddInstruction("PUSHARGQ", "PUSH_ROTATION", 0x62, new ArgType[] { ArgType.Float, ArgType.Float, ArgType.Float, ArgType.Float });
  315. AddInstruction("PUSHE", "PUSH_VOID4", 0x63, new ArgType[0]);
  316. AddInstruction("PUSHEV", "PUSH_VOID12", 0x64, new ArgType[0]);
  317. AddInstruction("PUSHEQ", "PUSH_VOID16", 0x65, new ArgType[0]);
  318. AddInstruction("PUSHARGE", "PUSH_LOCAL_ALLOC", 0x66, new ArgType[] { ArgType.Integer });
  319. AddInstruction("ADD", "MATH_ADD", 0x70, new ArgType[] { ArgType.LType, ArgType.RType });
  320. AddInstruction("SUB", "MATH_SUBTRACT", 0x71, new ArgType[] { ArgType.LType, ArgType.RType });
  321. AddInstruction("MUL", "MATH_MULTIPLY", 0x72, new ArgType[] { ArgType.LType, ArgType.RType });
  322. AddInstruction("DIV", "MATH_DIVIDE", 0x73, new ArgType[] { ArgType.LType, ArgType.RType });
  323. AddInstruction("MOD", "MATH_MODULO", 0x74, new ArgType[] { ArgType.LType, ArgType.RType });
  324. AddInstruction("EQ", "COMPARE_EQ", 0x75, new ArgType[] { ArgType.LType, ArgType.RType });
  325. AddInstruction("NEQ", "COMPARE_NE", 0x76, new ArgType[] { ArgType.LType, ArgType.RType });
  326. AddInstruction("LEQ", "COMPARE_LTE", 0x77, new ArgType[] { ArgType.LType, ArgType.RType });
  327. AddInstruction("GEQ", "COMPARE_GTE", 0x78, new ArgType[] { ArgType.LType, ArgType.RType });
  328. AddInstruction("LESS", "COMPARE_LT", 0x79, new ArgType[] { ArgType.LType, ArgType.RType });
  329. AddInstruction("GREATER", "COMPARE_GT", 0x7A, new ArgType[] { ArgType.LType, ArgType.RType });
  330. AddInstruction("BITAND", "BINARY_AND", 0x7B, new ArgType[0]);
  331. AddInstruction("BITOR", "BINARY_OR", 0x7C, new ArgType[0]);
  332. AddInstruction("BITXOR", "BINARY_XOR", 0x7D, new ArgType[0]);
  333. AddInstruction("BOOLAND", "LOGICAL_AND", 0x7E, new ArgType[0]);
  334. AddInstruction("BOOLOR", "LOGICAL_OR", 0x7F, new ArgType[0]);
  335. AddInstruction("NEG", "MATH_NEGATIVE", 0x80, new ArgType[] { ArgType.Type });
  336. AddInstruction("BITNOT", "COMPLEMENT", 0x81, new ArgType[0]);
  337. AddInstruction("BOOLNOT", "LOGICAL_NOT", 0x82, new ArgType[0]);
  338. AddInstruction("JUMP", "BRANCH", 0x90, new ArgType[] { ArgType.CodeOffset });
  339. AddInstruction("JUMPIF", "BRANCH_TRUE", 0x91, new ArgType[] { ArgType.Type, ArgType.CodeOffset });
  340. AddInstruction("JUMPNIF", "BRANCH_FALSE", 0x92, new ArgType[] { ArgType.Type, ArgType.CodeOffset });
  341. AddInstruction("STATE", "", 0x93, new ArgType[] { ArgType.StateIndex });
  342. AddInstruction("CALL", "CALL_FUNCTION", 0x94, new ArgType[] { ArgType.UserFunctionIndex });
  343. AddInstruction("RETURN", "", 0x95, new ArgType[0]);
  344. AddInstruction("CAST", "CAST_TYPE", 0xA0, new ArgType[] { ArgType.LType, ArgType.RType });
  345. AddInstruction("STACKTOS", "", 0xB0, new ArgType[] { ArgType.Integer });
  346. AddInstruction("STACKTOL", "MERGE_LIST", 0xB1, new ArgType[] { ArgType.Integer });
  347. AddInstruction("PRINT", "", 0xC0, new ArgType[] { ArgType.Type });
  348. AddInstruction("CALLLIB", "", 0xD0, new ArgType[] { ArgType.LibFunctionIndexByte });
  349. AddInstruction("CALLLIB_TWO_BYTE", "CALL_BUILTIN", 0xD1, new ArgType[] { ArgType.LibFunctionIndexTwoByte });
  350. AddInstruction("SHL", "BINARY_SHL", 0xE0, new ArgType[0]);
  351. AddInstruction("SHR", "BINARY_SHR", 0xE1, new ArgType[0]);
  352. }
  353. }
  354. }