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

/TangooBaby/libs/CCGameSWF/gameswf/gameswf/gameswf_disasm.cpp

https://github.com/qinxiaog/cocos2dx-swf
C++ | 865 lines | 713 code | 93 blank | 59 comment | 100 complexity | fc355efe85e872b0e907a991200000a7 MD5 | raw file
  1. // gameswf_disasm.cpp -- Thatcher Ulrich <tu@tulrich.com> 2003
  2. // This source code has been donated to the Public Domain. Do
  3. // whatever you want with it.
  4. //
  5. // Disassembler
  6. //
  7. #include "gameswf_disasm.h"
  8. #include "gameswf_log.h"
  9. #include <stdarg.h>
  10. namespace gameswf
  11. {
  12. #define COMPILE_DISASM 1
  13. #ifndef COMPILE_DISASM
  14. void log_disasm(const unsigned char* instruction_data)
  15. // No disassembler in this version...
  16. {
  17. log_msg("<no disasm>\n");
  18. }
  19. #else // COMPILE_DISASM
  20. //
  21. // Action Script 3.0
  22. //
  23. enum arg_format_avm2
  24. {
  25. ARG_END=0,
  26. ARG_MULTINAME,
  27. ARG_NAMESPACE,
  28. ARG_BYTE,
  29. ARG_SHORT,
  30. ARG_INT,
  31. ARG_UINT,
  32. ARG_DOUBLE,
  33. ARG_STRING,
  34. ARG_COUNT,
  35. ARG_CLASSINFO,
  36. ARG_FUNCTION,
  37. ARG_EXCEPTION,
  38. ARG_REGISTER,
  39. ARG_SLOTINDEX,
  40. ARG_OFFSET,
  41. ARG_OFFSETLIST,
  42. };
  43. int read_vu30( int& result, const uint8 *args )
  44. {
  45. result = args[0];
  46. if ((result & 0x00000080) == 0)
  47. {
  48. return 1;
  49. }
  50. result = (result & 0x0000007F) | args[1] << 7;
  51. if ((result & 0x00004000) == 0)
  52. {
  53. return 2;
  54. }
  55. result = (result & 0x00003FFF) | args[2] << 14;
  56. if ((result & 0x00200000) == 0)
  57. {
  58. return 3;
  59. }
  60. result = (result & 0x001FFFFF) | args[3] << 21;
  61. if ((result & 0x10000000) == 0)
  62. {
  63. return 4;
  64. }
  65. result = (result & 0x0FFFFFFF) | args[4] << 28;
  66. return 5;
  67. }
  68. struct inst_info_avm2
  69. {
  70. const char* m_instruction;
  71. array<arg_format_avm2> m_arg_formats;
  72. inst_info_avm2(const char* opname) :
  73. m_instruction(opname)
  74. {
  75. }
  76. inst_info_avm2(const char* opname, const arg_format_avm2 arg_format_0, ...) :
  77. m_instruction(opname)
  78. {
  79. va_list arg;
  80. m_arg_formats.push_back( arg_format_0 );
  81. va_start( arg, arg_format_0 );
  82. arg_format_avm2 current_format;
  83. while( ( current_format = (arg_format_avm2)va_arg( arg, int ) ) != ARG_END )
  84. {
  85. m_arg_formats.push_back( current_format );
  86. }
  87. }
  88. int process(const abc_def* def, const uint8 *args)
  89. {
  90. int byte_count = 1;
  91. for( int i=0; i<m_arg_formats.size();++i)
  92. {
  93. int value;
  94. switch( m_arg_formats[i] )
  95. {
  96. case ARG_MULTINAME:
  97. byte_count += read_vu30(value, &args[byte_count]);
  98. if( value >= def->m_multiname.size() )
  99. {
  100. log_msg( "\t\tmultiname: runtime %i\n", value);
  101. }
  102. else
  103. {
  104. switch( def->m_multiname[value].m_kind )
  105. {
  106. case multiname::CONSTANT_Multiname:
  107. case multiname::CONSTANT_QName:
  108. log_msg( "\t\tmultiname: %s\n", def->m_string[def->m_multiname[value].m_name].c_str());
  109. break;
  110. default:
  111. log_msg( "\t\tmultiname ( todo kind: %i )\n", def->m_multiname[value].m_kind );
  112. };
  113. }
  114. break;
  115. case ARG_NAMESPACE:
  116. byte_count += read_vu30(value, &args[byte_count]);
  117. log_msg( "\t\tnamespace: %s\n", def->m_string[ def->m_namespace[value].m_name ].c_str());
  118. break;
  119. case ARG_BYTE:
  120. value = args[byte_count];
  121. log_msg("\t\tvalue: %i\n", value);
  122. byte_count++;
  123. break;
  124. case ARG_SHORT:
  125. byte_count += read_vu30(value, &args[byte_count]);
  126. log_msg("\t\tvalue: %i\n", value);
  127. break;
  128. case ARG_INT:
  129. byte_count += read_vu30(value, &args[byte_count]);
  130. log_msg("\t\tvalue: %i\n", def->m_integer[value]);
  131. break;
  132. case ARG_UINT:
  133. byte_count += read_vu30(value, &args[byte_count]);
  134. log_msg("\t\tvalue: %ui\n", def->m_uinteger[value]);
  135. break;
  136. case ARG_DOUBLE:
  137. byte_count += read_vu30(value, &args[byte_count]);
  138. log_msg("\t\tvalue: %f\n", def->m_double[value]);
  139. break;
  140. case ARG_STRING:
  141. byte_count += read_vu30(value, &args[byte_count]);
  142. log_msg( "\t\tstring: %s\n", def->m_string[value].c_str());
  143. break;
  144. case ARG_COUNT:
  145. byte_count += read_vu30(value, &args[byte_count]);
  146. log_msg( "\t\tcount: %i\n", value);
  147. break;
  148. case ARG_CLASSINFO:
  149. byte_count += read_vu30(value, &args[byte_count]);
  150. log_msg( "\t\tclass: %i\n", value);
  151. break;
  152. case ARG_FUNCTION:
  153. byte_count += read_vu30( value, &args[byte_count] );
  154. //TODO: print signature
  155. log_msg( "\t\tfunction: %s\n", def->m_string[def->m_method[value]->m_name].c_str());
  156. break;
  157. case ARG_EXCEPTION:
  158. byte_count += read_vu30( value, &args[byte_count] );
  159. //TODO: print exception info
  160. log_msg( "\t\texception: %i\n", value);
  161. break;
  162. case ARG_REGISTER:
  163. byte_count += read_vu30( value, &args[byte_count] );
  164. log_msg( "\t\tregister: %i\n", value);
  165. break;
  166. case ARG_SLOTINDEX:
  167. byte_count += read_vu30( value, &args[byte_count] );
  168. log_msg( "\t\tslot index: %i\n", value);
  169. break;
  170. case ARG_OFFSET:
  171. value = args[byte_count] | args[byte_count+1]<<8 | args[byte_count+2]<<16;
  172. byte_count += 3;
  173. log_msg( "\t\toffset: %i\n", value);
  174. break;
  175. case ARG_OFFSETLIST:
  176. value = args[byte_count] | args[byte_count+1]<<8 | (*(int8*)&args[byte_count+2])<<16; //sign extend the high byte
  177. log_msg( "\t\tdefault offset: %i\n", value);
  178. byte_count += 3;
  179. int offset_count;
  180. byte_count += read_vu30( offset_count, &args[byte_count] );
  181. for(int i=0;i<offset_count+1;i++)
  182. {
  183. value = args[byte_count] | args[byte_count+1]<<8 | (*(int8*)&args[byte_count+2])<<16;
  184. log_msg("\t\toffset %i: %i\n", i, value);
  185. byte_count +=3;
  186. }
  187. break;
  188. case ARG_END:
  189. assert(0 && "forbidden");
  190. break;
  191. }
  192. }
  193. return byte_count;
  194. }
  195. bool has_argument() const { return m_arg_formats.size() != 0;}
  196. };
  197. static hash<int, inst_info_avm2> s_instr;
  198. // it's called on exit from player
  199. void clear_disasm()
  200. {
  201. s_instr.clear();
  202. }
  203. void log_disasm_avm2(const membuf& data, const abc_def* def)
  204. // Disassemble one instruction to the log, AVM2
  205. {
  206. if (s_instr.size() == 0)
  207. {
  208. s_instr.add(0x03, inst_info_avm2("throw"));
  209. s_instr.add(0x04, inst_info_avm2("getsuper", ARG_MULTINAME, ARG_END ));
  210. s_instr.add(0x05, inst_info_avm2("setsuper" ));
  211. s_instr.add(0x06, inst_info_avm2("dxns"));
  212. s_instr.add(0x07, inst_info_avm2("dxnslate"));
  213. s_instr.add(0x08, inst_info_avm2("kill", ARG_REGISTER, ARG_END));
  214. s_instr.add(0x09, inst_info_avm2("label"));
  215. // no inst for 0x0A, 0x0B
  216. s_instr.add(0x0C, inst_info_avm2("ifnlt", ARG_OFFSET, ARG_END));
  217. s_instr.add(0x0D, inst_info_avm2("ifnle", ARG_OFFSET, ARG_END));
  218. s_instr.add(0x0E, inst_info_avm2("ifngt", ARG_OFFSET, ARG_END));
  219. s_instr.add(0x0F, inst_info_avm2("ifnge", ARG_OFFSET, ARG_END));
  220. s_instr.add(0x10, inst_info_avm2("jump", ARG_OFFSET, ARG_END));
  221. s_instr.add(0x11, inst_info_avm2("iftrue", ARG_OFFSET, ARG_END));
  222. s_instr.add(0x12, inst_info_avm2("iffalse", ARG_OFFSET, ARG_END));
  223. s_instr.add(0x13, inst_info_avm2("ifeq", ARG_OFFSET, ARG_END));
  224. s_instr.add(0x14, inst_info_avm2("ifne", ARG_OFFSET, ARG_END));
  225. s_instr.add(0x15, inst_info_avm2("iflt", ARG_OFFSET, ARG_END));
  226. s_instr.add(0x16, inst_info_avm2("ifle", ARG_OFFSET, ARG_END));
  227. s_instr.add(0x17, inst_info_avm2("ifgt", ARG_OFFSET, ARG_END));
  228. s_instr.add(0x18, inst_info_avm2("ifge", ARG_OFFSET, ARG_END));
  229. s_instr.add(0x19, inst_info_avm2("ifstricteq", ARG_OFFSET, ARG_END));
  230. s_instr.add(0x1A, inst_info_avm2("ifstrictne", ARG_OFFSET, ARG_END));
  231. s_instr.add(0x1B, inst_info_avm2("lookupswitch", ARG_OFFSETLIST, ARG_END));
  232. s_instr.add(0x1C, inst_info_avm2("pushwith"));
  233. s_instr.add(0x1D, inst_info_avm2("popscope"));
  234. s_instr.add(0x1E, inst_info_avm2("nextname"));
  235. s_instr.add(0x1F, inst_info_avm2("hasnext"));
  236. s_instr.add(0x20, inst_info_avm2("pushnull"));
  237. s_instr.add(0x21, inst_info_avm2("pushundefined"));
  238. // no inst for 0x22
  239. s_instr.add(0x23, inst_info_avm2("nextvalue"));
  240. s_instr.add(0x24, inst_info_avm2("pushbyte", ARG_BYTE, ARG_END));
  241. s_instr.add(0x25, inst_info_avm2("pushshort", ARG_SHORT, ARG_END));
  242. s_instr.add(0x26, inst_info_avm2("pushtrue"));
  243. s_instr.add(0x27, inst_info_avm2("pushfalse"));
  244. s_instr.add(0x28, inst_info_avm2("pushnan"));
  245. s_instr.add(0x29, inst_info_avm2("pop"));
  246. s_instr.add(0x2A, inst_info_avm2("dup"));
  247. s_instr.add(0x2B, inst_info_avm2("swap"));
  248. s_instr.add(0x2C, inst_info_avm2("pushstring", ARG_STRING, ARG_END));
  249. s_instr.add(0x2D, inst_info_avm2("pushint", ARG_INT, ARG_END));
  250. s_instr.add(0x2E, inst_info_avm2("pushuint", ARG_UINT, ARG_END));
  251. s_instr.add(0x2F, inst_info_avm2("pushdouble", ARG_DOUBLE, ARG_END));
  252. s_instr.add(0x30, inst_info_avm2("pushscope"));
  253. s_instr.add(0x31, inst_info_avm2("pushnamespace", ARG_NAMESPACE, ARG_END));
  254. s_instr.add(0x32, inst_info_avm2("hasnext2", ARG_REGISTER, ARG_REGISTER, ARG_END));
  255. // no inst for 0x33 -> 0X3F
  256. s_instr.add(0x40, inst_info_avm2("newfunction", ARG_FUNCTION, ARG_END));
  257. s_instr.add(0x41, inst_info_avm2("call", ARG_COUNT, ARG_END));
  258. s_instr.add(0x42, inst_info_avm2("construct", ARG_COUNT, ARG_END));
  259. s_instr.add(0x43, inst_info_avm2("callmethod", ARG_SHORT, ARG_COUNT, ARG_END));
  260. s_instr.add(0x44, inst_info_avm2("callstatic", ARG_FUNCTION, ARG_COUNT, ARG_END));
  261. s_instr.add(0x45, inst_info_avm2("callsuper", ARG_MULTINAME, ARG_COUNT, ARG_END));
  262. s_instr.add(0x46, inst_info_avm2("callproperty", ARG_MULTINAME, ARG_COUNT, ARG_END));
  263. s_instr.add(0x47, inst_info_avm2("returnvoid"));
  264. s_instr.add(0x48, inst_info_avm2("returnvalue"));
  265. s_instr.add(0x49, inst_info_avm2("constructsuper", ARG_COUNT, ARG_END));
  266. s_instr.add(0x4A, inst_info_avm2("constructprop", ARG_MULTINAME, ARG_COUNT, ARG_END));
  267. // no inst for 0x4B
  268. s_instr.add(0x4C, inst_info_avm2("callproplex", ARG_MULTINAME, ARG_COUNT, ARG_END));
  269. // no inst for 0x4E
  270. s_instr.add(0x4E, inst_info_avm2("callsupervoid", ARG_MULTINAME, ARG_COUNT, ARG_END));
  271. s_instr.add(0x4F, inst_info_avm2("callpropvoid", ARG_MULTINAME, ARG_COUNT, ARG_END));
  272. // no inst for 0x50 -> 0x54
  273. s_instr.add(0x55, inst_info_avm2("newobject", ARG_COUNT, ARG_END));
  274. s_instr.add(0x56, inst_info_avm2("newarray", ARG_COUNT, ARG_END));
  275. s_instr.add(0x57, inst_info_avm2("newactivation"));
  276. s_instr.add(0x58, inst_info_avm2("newclass", ARG_CLASSINFO, ARG_END));
  277. s_instr.add(0x59, inst_info_avm2("getdescendants", ARG_MULTINAME, ARG_END));
  278. s_instr.add(0x5A, inst_info_avm2("newcatch", ARG_EXCEPTION, ARG_END));
  279. // no inst for 0x5B -> 0x5C
  280. s_instr.add(0x5D, inst_info_avm2("findpropstrict", ARG_MULTINAME, ARG_END));
  281. s_instr.add(0x5E, inst_info_avm2("findproperty", ARG_MULTINAME, ARG_END));
  282. // no inst for 0x5F
  283. s_instr.add(0x60, inst_info_avm2("getlex", ARG_MULTINAME, ARG_END));
  284. s_instr.add(0x61, inst_info_avm2("setproperty", ARG_MULTINAME, ARG_END));
  285. s_instr.add(0x62, inst_info_avm2("getlocal", ARG_REGISTER, ARG_END));
  286. s_instr.add(0x63, inst_info_avm2("setlocal", ARG_REGISTER, ARG_END));
  287. s_instr.add(0x64, inst_info_avm2("getglobalscope"));
  288. s_instr.add(0x65, inst_info_avm2("getscopeobject", ARG_BYTE, ARG_END));
  289. s_instr.add(0x66, inst_info_avm2("getproperty", ARG_MULTINAME, ARG_END));
  290. // no inst for 0x67
  291. s_instr.add(0x68, inst_info_avm2("initproperty", ARG_MULTINAME, ARG_END));
  292. // no inst for 0x69
  293. s_instr.add(0x6A, inst_info_avm2("deleteproperty", ARG_MULTINAME, ARG_END));
  294. // no inst for 0x6B
  295. s_instr.add(0x6C, inst_info_avm2("getslot", ARG_SLOTINDEX, ARG_END));
  296. s_instr.add(0x6D, inst_info_avm2("setslot", ARG_SLOTINDEX, ARG_END));
  297. s_instr.add(0x6E, inst_info_avm2("getglobalslot", ARG_SLOTINDEX, ARG_END));
  298. s_instr.add(0x6F, inst_info_avm2("setglobalslot", ARG_SLOTINDEX, ARG_END));
  299. s_instr.add(0x70, inst_info_avm2("convert_s"));
  300. s_instr.add(0x71, inst_info_avm2("esc_xelem"));
  301. s_instr.add(0x72, inst_info_avm2("esc_xattr"));
  302. s_instr.add(0x73, inst_info_avm2("convert_i"));
  303. s_instr.add(0x74, inst_info_avm2("convert_u"));
  304. s_instr.add(0x75, inst_info_avm2("convert_d"));
  305. s_instr.add(0x76, inst_info_avm2("convert_b"));
  306. s_instr.add(0x77, inst_info_avm2("convert_o"));
  307. s_instr.add(0x78, inst_info_avm2("checkfilter"));
  308. // no inst for 0x79 - 0x7F
  309. s_instr.add(0x80, inst_info_avm2("coerce", ARG_MULTINAME, ARG_END));
  310. // no inst for 0x81
  311. s_instr.add(0x82, inst_info_avm2("coerce_a"));
  312. // no inst for 0x83, 0x84
  313. s_instr.add(0x85, inst_info_avm2("coerce_s"));
  314. s_instr.add(0x86, inst_info_avm2("astype", ARG_MULTINAME, ARG_END));
  315. s_instr.add(0x87, inst_info_avm2("astypelate", ARG_MULTINAME, ARG_END));
  316. // no inst for 0x88->0x8F
  317. s_instr.add(0x90, inst_info_avm2("negate"));
  318. s_instr.add(0x91, inst_info_avm2("increment"));
  319. s_instr.add(0x92, inst_info_avm2("inclocal", ARG_REGISTER, ARG_END));
  320. s_instr.add(0x93, inst_info_avm2("decrement"));
  321. s_instr.add(0x94, inst_info_avm2("declocal", ARG_REGISTER, ARG_END));
  322. s_instr.add(0x95, inst_info_avm2("typeof"));
  323. s_instr.add(0x96, inst_info_avm2("not"));
  324. s_instr.add(0x97, inst_info_avm2("bitnot"));
  325. // no inst for 0x99->0x0x9F
  326. s_instr.add(0xA0, inst_info_avm2("add"));
  327. s_instr.add(0xA1, inst_info_avm2("subtract"));
  328. s_instr.add(0xA2, inst_info_avm2("multiply"));
  329. s_instr.add(0xA3, inst_info_avm2("divide"));
  330. s_instr.add(0xA4, inst_info_avm2("modulo"));
  331. s_instr.add(0xA5, inst_info_avm2("lshift"));
  332. s_instr.add(0xA6, inst_info_avm2("rshift"));
  333. s_instr.add(0xA7, inst_info_avm2("urshift"));
  334. s_instr.add(0xA8, inst_info_avm2("bitand"));
  335. s_instr.add(0xA9, inst_info_avm2("bitor"));
  336. s_instr.add(0xAA, inst_info_avm2("bitxor"));
  337. s_instr.add(0xAB, inst_info_avm2("equals"));
  338. s_instr.add(0xAC, inst_info_avm2("strictequals"));
  339. s_instr.add(0xAD, inst_info_avm2("lessthan"));
  340. s_instr.add(0xAE, inst_info_avm2("lessequals"));
  341. s_instr.add(0xAF, inst_info_avm2("greaterequals"));
  342. // no inst for 0xB0
  343. s_instr.add(0xB1, inst_info_avm2("instanceof"));
  344. s_instr.add(0xB2, inst_info_avm2("istype", ARG_MULTINAME, ARG_END));
  345. s_instr.add(0xB3, inst_info_avm2("istypelate"));
  346. s_instr.add(0xB4, inst_info_avm2("in"));
  347. // no inst for 0xB5
  348. s_instr.add(0xC0, inst_info_avm2("increment_i"));
  349. s_instr.add(0xC1, inst_info_avm2("decrement_i"));
  350. s_instr.add(0xC2, inst_info_avm2("inclocal_i", ARG_REGISTER, ARG_END));
  351. s_instr.add(0xC3, inst_info_avm2("declocal_i", ARG_REGISTER, ARG_END));
  352. s_instr.add(0xC4, inst_info_avm2("negate_i"));
  353. s_instr.add(0xC5, inst_info_avm2("add_i"));
  354. s_instr.add(0xC6, inst_info_avm2("subtract_i"));
  355. s_instr.add(0xC7, inst_info_avm2("multiply_i"));
  356. // no inst for 0xC8 - > 0xCF
  357. s_instr.add(0xD0, inst_info_avm2("getlocal_0"));
  358. s_instr.add(0xD1, inst_info_avm2("getlocal_1"));
  359. s_instr.add(0xD2, inst_info_avm2("getlocal_2"));
  360. s_instr.add(0xD3, inst_info_avm2("getlocal_3"));
  361. s_instr.add(0xD4, inst_info_avm2("setlocal_0"));
  362. s_instr.add(0xD5, inst_info_avm2("setlocal_1"));
  363. s_instr.add(0xD6, inst_info_avm2("setlocal_2"));
  364. s_instr.add(0xD7, inst_info_avm2("setlocal_3"));
  365. // no inst for 0xD8 - > 0xEE
  366. s_instr.add(0xEF, inst_info_avm2("debug", ARG_BYTE, ARG_STRING, ARG_BYTE, ARG_SHORT));
  367. s_instr.add(0xF0, inst_info_avm2("debugline", ARG_SHORT, ARG_END));
  368. s_instr.add(0xF1, inst_info_avm2("debugfile", ARG_STRING, ARG_END));
  369. }
  370. assert(data.size() > 0);
  371. int ip = 0;
  372. do
  373. {
  374. int opcode = data[ip];
  375. inst_info_avm2 ii(0);
  376. if (s_instr.get(opcode, &ii))
  377. {
  378. printf(": %s\n", ii.m_instruction);
  379. if( ii.has_argument() )
  380. {
  381. ip += ii.process( def, &data[ip] );
  382. }
  383. else
  384. {
  385. ip++;
  386. }
  387. }
  388. else
  389. {
  390. log_msg(": unknown opcode 0x%02X\n", opcode);
  391. ip++;
  392. }
  393. }
  394. while (ip < data.size());
  395. }
  396. //
  397. // Action Script 2.0
  398. //
  399. enum arg_format
  400. {
  401. ARG_NONE = 0,
  402. ARG_STR,
  403. ARG_HEX, // default hex dump, in case the format is unknown or unsupported
  404. ARG_U8,
  405. ARG_U16,
  406. ARG_S16,
  407. ARG_PUSH_DATA,
  408. ARG_DECL_DICT,
  409. ARG_FUNCTION2
  410. };
  411. struct inst_info
  412. {
  413. int m_action_id;
  414. const char* m_instruction;
  415. arg_format m_arg_format;
  416. };
  417. void log_disasm(const unsigned char* instruction_data)
  418. // Disassemble one instruction to the log.
  419. {
  420. static inst_info s_instruction_table[] = {
  421. { 0x04, "next_frame", ARG_NONE },
  422. { 0x05, "prev_frame", ARG_NONE },
  423. { 0x06, "play", ARG_NONE },
  424. { 0x07, "stop", ARG_NONE },
  425. { 0x08, "toggle_qlty", ARG_NONE },
  426. { 0x09, "stop_sounds", ARG_NONE },
  427. { 0x0A, "add", ARG_NONE },
  428. { 0x0B, "sub", ARG_NONE },
  429. { 0x0C, "mul", ARG_NONE },
  430. { 0x0D, "div", ARG_NONE },
  431. { 0x0E, "equ", ARG_NONE },
  432. { 0x0F, "lt", ARG_NONE },
  433. { 0x10, "and", ARG_NONE },
  434. { 0x11, "or", ARG_NONE },
  435. { 0x12, "not", ARG_NONE },
  436. { 0x13, "str_eq", ARG_NONE },
  437. { 0x14, "str_len", ARG_NONE },
  438. { 0x15, "substr", ARG_NONE },
  439. { 0x17, "pop", ARG_NONE },
  440. { 0x18, "floor", ARG_NONE },
  441. { 0x1C, "get_var", ARG_NONE },
  442. { 0x1D, "set_var", ARG_NONE },
  443. { 0x20, "set_target_exp", ARG_NONE },
  444. { 0x21, "str_cat", ARG_NONE },
  445. { 0x22, "get_prop", ARG_NONE },
  446. { 0x23, "set_prop", ARG_NONE },
  447. { 0x24, "dup_sprite", ARG_NONE },
  448. { 0x25, "rem_sprite", ARG_NONE },
  449. { 0x26, "trace", ARG_NONE },
  450. { 0x27, "start_drag", ARG_NONE },
  451. { 0x28, "stop_drag", ARG_NONE },
  452. { 0x29, "str_lt", ARG_NONE },
  453. { 0x2B, "cast_object", ARG_NONE },
  454. { 0x30, "random", ARG_NONE },
  455. { 0x31, "mb_length", ARG_NONE },
  456. { 0x32, "ord", ARG_NONE },
  457. { 0x33, "chr", ARG_NONE },
  458. { 0x34, "get_timer", ARG_NONE },
  459. { 0x35, "substr_mb", ARG_NONE },
  460. { 0x36, "ord_mb", ARG_NONE },
  461. { 0x37, "chr_mb", ARG_NONE },
  462. { 0x3A, "delete", ARG_NONE },
  463. { 0x3B, "delete_all", ARG_NONE },
  464. { 0x3C, "set_local", ARG_NONE },
  465. { 0x3D, "call_func", ARG_NONE },
  466. { 0x3E, "return", ARG_NONE },
  467. { 0x3F, "mod", ARG_NONE },
  468. { 0x40, "new", ARG_NONE },
  469. { 0x41, "decl_local", ARG_NONE },
  470. { 0x42, "decl_array", ARG_NONE },
  471. { 0x43, "decl_obj", ARG_NONE },
  472. { 0x44, "type_of", ARG_NONE },
  473. { 0x45, "get_target", ARG_NONE },
  474. { 0x46, "enumerate", ARG_NONE },
  475. { 0x47, "add_t", ARG_NONE },
  476. { 0x48, "lt_t", ARG_NONE },
  477. { 0x49, "eq_t", ARG_NONE },
  478. { 0x4A, "number", ARG_NONE },
  479. { 0x4B, "string", ARG_NONE },
  480. { 0x4C, "dup", ARG_NONE },
  481. { 0x4D, "swap", ARG_NONE },
  482. { 0x4E, "get_member", ARG_NONE },
  483. { 0x4F, "set_member", ARG_NONE },
  484. { 0x50, "inc", ARG_NONE },
  485. { 0x51, "dec", ARG_NONE },
  486. { 0x52, "call_method", ARG_NONE },
  487. { 0x53, "new_method", ARG_NONE },
  488. { 0x54, "is_inst_of", ARG_NONE },
  489. { 0x55, "enum_object", ARG_NONE },
  490. { 0x60, "bit_and", ARG_NONE },
  491. { 0x61, "bit_or", ARG_NONE },
  492. { 0x62, "bit_xor", ARG_NONE },
  493. { 0x63, "shl", ARG_NONE },
  494. { 0x64, "asr", ARG_NONE },
  495. { 0x65, "lsr", ARG_NONE },
  496. { 0x66, "eq_strict", ARG_NONE },
  497. { 0x67, "gt_t", ARG_NONE },
  498. { 0x68, "gt_str", ARG_NONE },
  499. { 0x69, "extends", ARG_NONE },
  500. { 0x81, "goto_frame", ARG_U16 },
  501. { 0x83, "get_url", ARG_STR },
  502. { 0x87, "store_register", ARG_U8 },
  503. { 0x88, "decl_dict", ARG_DECL_DICT },
  504. { 0x8A, "wait_for_frame", ARG_HEX },
  505. { 0x8B, "set_target", ARG_STR },
  506. { 0x8C, "goto_frame_lbl", ARG_STR },
  507. { 0x8D, "wait_for_fr_exp", ARG_HEX },
  508. { 0x8E, "function2", ARG_FUNCTION2 },
  509. { 0x94, "with", ARG_U16 },
  510. { 0x96, "push_data", ARG_PUSH_DATA },
  511. { 0x99, "goto", ARG_S16 },
  512. { 0x9A, "get_url2", ARG_HEX },
  513. // { 0x8E, "function2", ARG_HEX },
  514. { 0x9B, "func", ARG_HEX },
  515. { 0x9D, "branch_if_true", ARG_S16 },
  516. { 0x9E, "call_frame", ARG_HEX },
  517. { 0x9F, "goto_frame_exp", ARG_HEX },
  518. { 0x00, "<end>", ARG_NONE }
  519. };
  520. int action_id = instruction_data[0];
  521. inst_info* info = NULL;
  522. for (int i = 0; ; i++)
  523. {
  524. if (s_instruction_table[i].m_action_id == action_id)
  525. {
  526. info = &s_instruction_table[i];
  527. }
  528. if (s_instruction_table[i].m_action_id == 0)
  529. {
  530. // Stop at the end of the table and give up.
  531. break;
  532. }
  533. }
  534. arg_format fmt = ARG_HEX;
  535. // Show instruction.
  536. if (info == NULL)
  537. {
  538. log_msg("<unknown>[0x%02X]", action_id);
  539. }
  540. else
  541. {
  542. log_msg("%-15s", info->m_instruction);
  543. fmt = info->m_arg_format;
  544. }
  545. // Show instruction argument(s).
  546. if (action_id & 0x80)
  547. {
  548. assert(fmt != ARG_NONE);
  549. int length = instruction_data[1] | (instruction_data[2] << 8);
  550. // log_msg(" [%d]", length);
  551. if (fmt == ARG_HEX)
  552. {
  553. for (int i = 0; i < length; i++)
  554. {
  555. log_msg(" 0x%02X", instruction_data[3 + i]);
  556. }
  557. log_msg("\n");
  558. }
  559. else if (fmt == ARG_STR)
  560. {
  561. log_msg(" \"");
  562. for (int i = 0; i < length; i++)
  563. {
  564. log_msg("%c", instruction_data[3 + i]);
  565. }
  566. log_msg("\"\n");
  567. }
  568. else if (fmt == ARG_U8)
  569. {
  570. int val = instruction_data[3];
  571. log_msg(" %d\n", val);
  572. }
  573. else if (fmt == ARG_U16)
  574. {
  575. int val = instruction_data[3] | (instruction_data[4] << 8);
  576. log_msg(" %d\n", val);
  577. }
  578. else if (fmt == ARG_S16)
  579. {
  580. int val = instruction_data[3] | (instruction_data[4] << 8);
  581. if (val & 0x8000) val |= ~0x7FFF; // sign-extend
  582. log_msg(" %d\n", val);
  583. }
  584. else if (fmt == ARG_PUSH_DATA)
  585. {
  586. log_msg("\n");
  587. int i = 0;
  588. while (i < length)
  589. {
  590. int type = instruction_data[3 + i];
  591. i++;
  592. log_msg("\t\t"); // indent
  593. if (type == 0)
  594. {
  595. // string
  596. log_msg("\"");
  597. while (instruction_data[3 + i])
  598. {
  599. log_msg("%c", instruction_data[3 + i]);
  600. i++;
  601. }
  602. i++;
  603. log_msg("\"\n");
  604. }
  605. else if (type == 1)
  606. {
  607. // float (little-endian)
  608. union {
  609. float f;
  610. Uint32 i;
  611. } u;
  612. compiler_assert(sizeof(u) == sizeof(u.i));
  613. memcpy(&u.i, instruction_data + 3 + i, 4);
  614. u.i = swap_le32(u.i);
  615. i += 4;
  616. log_msg("(float) %f\n", u.f);
  617. }
  618. else if (type == 2)
  619. {
  620. log_msg("NULL\n");
  621. }
  622. else if (type == 3)
  623. {
  624. log_msg("undef\n");
  625. }
  626. else if (type == 4)
  627. {
  628. // contents of register
  629. int reg = instruction_data[3 + i];
  630. i++;
  631. log_msg("reg[%d]\n", reg);
  632. }
  633. else if (type == 5)
  634. {
  635. int bool_val = instruction_data[3 + i];
  636. i++;
  637. log_msg("bool(%d)\n", bool_val);
  638. }
  639. else if (type == 6)
  640. {
  641. // double
  642. // wacky format: 45670123
  643. union {
  644. double d;
  645. Uint64 i;
  646. struct {
  647. Uint32 lo;
  648. Uint32 hi;
  649. } sub;
  650. } u;
  651. compiler_assert(sizeof(u) == sizeof(u.i));
  652. memcpy(&u.sub.hi, instruction_data + 3 + i, 4);
  653. memcpy(&u.sub.lo, instruction_data + 3 + i + 4, 4);
  654. u.i = swap_le64(u.i);
  655. i += 8;
  656. log_msg("(double) %f\n", u.d);
  657. }
  658. else if (type == 7)
  659. {
  660. // int32
  661. Sint32 val = instruction_data[3 + i]
  662. | (instruction_data[3 + i + 1] << 8)
  663. | (instruction_data[3 + i + 2] << 16)
  664. | (instruction_data[3 + i + 3] << 24);
  665. i += 4;
  666. log_msg("(int) %d\n", val);
  667. }
  668. else if (type == 8)
  669. {
  670. int id = instruction_data[3 + i];
  671. i++;
  672. log_msg("dict_lookup[%d]\n", id);
  673. }
  674. else if (type == 9)
  675. {
  676. int id = instruction_data[3 + i] | (instruction_data[3 + i + 1] << 8);
  677. i += 2;
  678. log_msg("dict_lookup_lg[%d]\n", id);
  679. }
  680. }
  681. }
  682. else if (fmt == ARG_DECL_DICT)
  683. {
  684. int i = 0;
  685. int count = instruction_data[3 + i] | (instruction_data[3 + i + 1] << 8);
  686. i += 2;
  687. log_msg(" [%d]\n", count);
  688. // Print strings.
  689. for (int ct = 0; ct < count; ct++)
  690. {
  691. log_msg("\t\t"); // indent
  692. log_msg("\"");
  693. while (instruction_data[3 + i])
  694. {
  695. // safety check.
  696. if (i >= length)
  697. {
  698. log_msg("<disasm error -- length exceeded>\n");
  699. break;
  700. }
  701. log_msg("%c", instruction_data[3 + i]);
  702. i++;
  703. }
  704. log_msg("\"\n");
  705. i++;
  706. }
  707. }
  708. else if (fmt == ARG_FUNCTION2)
  709. {
  710. // Signature info for a function2 opcode.
  711. int i = 0;
  712. const char* function_name = (const char*) &instruction_data[3 + i];
  713. i += (int) strlen(function_name) + 1;
  714. int arg_count = instruction_data[3 + i] | (instruction_data[3 + i + 1] << 8);
  715. i += 2;
  716. int reg_count = instruction_data[3 + i];
  717. i++;
  718. log_msg("\n\t\tname = '%s', arg_count = %d, reg_count = %d\n",
  719. function_name, arg_count, reg_count);
  720. uint16 flags = (instruction_data[3 + i]) | (instruction_data[3 + i + 1] << 8);
  721. i += 2;
  722. // @@ What is the difference between "super" and "_parent"?
  723. bool preload_global = (flags & 0x100) != 0;
  724. bool preload_parent = (flags & 0x80) != 0;
  725. bool preload_root = (flags & 0x40) != 0;
  726. bool suppress_super = (flags & 0x20) != 0;
  727. bool preload_super = (flags & 0x10) != 0;
  728. bool suppress_args = (flags & 0x08) != 0;
  729. bool preload_args = (flags & 0x04) != 0;
  730. bool suppress_this = (flags & 0x02) != 0;
  731. bool preload_this = (flags & 0x01) != 0;
  732. log_msg("\t\t pg = %d\n"
  733. "\t\t pp = %d\n"
  734. "\t\t pr = %d\n"
  735. "\t\tss = %d, ps = %d\n"
  736. "\t\tsa = %d, pa = %d\n"
  737. "\t\tst = %d, pt = %d\n",
  738. int(preload_global),
  739. int(preload_parent),
  740. int(preload_root),
  741. int(suppress_super),
  742. int(preload_super),
  743. int(suppress_args),
  744. int(preload_args),
  745. int(suppress_this),
  746. int(preload_this));
  747. for (int argi = 0; argi < arg_count; argi++)
  748. {
  749. int arg_register = instruction_data[3 + i];
  750. i++;
  751. const char* arg_name = (const char*) &instruction_data[3 + i];
  752. i += (int) strlen(arg_name) + 1;
  753. log_msg("\t\targ[%d] - reg[%d] - '%s'\n", argi, arg_register, arg_name);
  754. }
  755. int function_length = instruction_data[3 + i] | (instruction_data[3 + i + 1] << 8);
  756. i += 2;
  757. log_msg("\t\tfunction length = %d\n", function_length);
  758. }
  759. }
  760. else
  761. {
  762. log_msg("\n");
  763. }
  764. }
  765. #endif // COMPILE_DISASM
  766. };
  767. // Local Variables:
  768. // mode: C++
  769. // c-basic-offset: 8
  770. // tab-width: 8
  771. // indent-tabs-mode: t
  772. // End: