FieldDisassembler.cpp 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245
  1. /*
  2. * Copyright (C) 2022 The V-Gears Team
  3. *
  4. * This file is part of V-Gears
  5. *
  6. * V-Gears is free software: you can redistribute it and/or modify it under
  7. * terms of the GNU General Public License as published by the Free Software
  8. * Foundation, version 3.0 (GPLv3) of the License.
  9. *
  10. * V-Gears is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include <vector>
  16. #include <boost/format.hpp>
  17. #include <boost/algorithm/string/split.hpp>
  18. #include <boost/algorithm/string.hpp>
  19. #include "decompiler/field/FieldCodeGenerator.h"
  20. #include "decompiler/field/FieldDisassembler.h"
  21. #include "decompiler/Engine.h"
  22. #include "decompiler/field/FieldEngine.h"
  23. #include "decompiler/field/instruction/FieldBackgroundInstruction.h"
  24. #include "decompiler/field/instruction/FieldCameraInstruction.h"
  25. #include "decompiler/field/instruction/FieldCondJumpInstruction.h"
  26. #include "decompiler/field/instruction/FieldControlFlowInstruction.h"
  27. #include "decompiler/field/instruction/FieldMathInstruction.h"
  28. #include "decompiler/field/instruction/FieldMediaInstruction.h"
  29. #include "decompiler/field/instruction/FieldModelInstruction.h"
  30. #include "decompiler/field/instruction/FieldModuleInstruction.h"
  31. #include "decompiler/field/instruction/FieldNoOperationInstruction.h"
  32. #include "decompiler/field/instruction/FieldPartyInstruction.h"
  33. #include "decompiler/field/instruction/FieldUncategorizedInstruction.h"
  34. #include "decompiler/field/instruction/FieldUncondJumpInstruction.h"
  35. #include "decompiler/field/instruction/FieldWalkmeshInstruction.h"
  36. #include "decompiler/field/instruction/FieldWindowInstruction.h"
  37. #include "common/Lzs.h"
  38. const int FieldDisassembler::MAGIC(0x0502);
  39. const int FieldDisassembler::NUM_SECTIONS(7);
  40. FieldDisassembler::FieldDisassembler(
  41. FieldScriptFormatter& formatter, FieldEngine* engine,
  42. InstVec& insts, const std::vector<unsigned char>& raw_script_data
  43. ): Disassembler(insts), engine_(engine), formatter_(formatter){
  44. loaded_from_raw_data_ = true;
  45. // If loading a raw section then skip the header section.
  46. section_pointers_size_ = 0;
  47. auto data_copy = raw_script_data;
  48. stream_ = std::make_unique<BinaryReader>(std::move(data_copy));
  49. ReadHeader();
  50. }
  51. FieldDisassembler::FieldDisassembler(
  52. FieldScriptFormatter& formatter, FieldEngine *engine, InstVec &insts
  53. ): Disassembler(insts), engine_(engine), formatter_(formatter){
  54. section_pointers_size_ = (sizeof(uint32) * NUM_SECTIONS);
  55. }
  56. float FieldDisassembler::GetScaleFactor() const{return scale_factor_;}
  57. FieldDisassembler::~FieldDisassembler(){}
  58. void FieldDisassembler::ReadHeader(){
  59. if (!loaded_from_raw_data_){
  60. // First read the file section pointers.
  61. for (int i = 0; i < NUM_SECTIONS; i ++) sections_[i] = stream_->ReadU32();
  62. // Now fix up from PSX RAM pointers to simple file offsets.
  63. const uint32 basePtr = sections_[0];
  64. for (int i = 0; i < NUM_SECTIONS; i++)
  65. sections_[i] = (sections_[i] - basePtr) + section_pointers_size_;
  66. // Now seek to the script section.
  67. stream_->Seek(sections_[SCRIPT]);
  68. }
  69. // Read the script header
  70. header_.Read(*stream_);
  71. scale_factor_ = static_cast<float>(header_.scale) / 512.0f;
  72. }
  73. void FieldDisassembler::Open(const char *filename){
  74. // Read all of the file, decompress it, then stuff it into a stream.
  75. stream_ = std::make_unique<BinaryReader>(Lzs::Decompress(BinaryReader::ReadAll(filename)));
  76. ReadHeader();
  77. }
  78. uint32 FieldDisassembler::GetEndOfScriptOffset(
  79. uint16 cur_entry_point, size_t entity_index, size_t script_index
  80. ){
  81. uint16 next_entry_point = cur_entry_point;
  82. do{
  83. if (script_index + 1 >= 32){
  84. // If this is the very last script, so use the end of its
  85. // data which is the offset to strings.
  86. if (entity_index + 1 >= header_.entity_scripts.size()) return header_.offset_to_strings;
  87. else{
  88. // Wrap around to the next entity
  89. entity_index ++;
  90. script_index = 0;
  91. }
  92. }
  93. // Get the next script in the same entity.
  94. else script_index ++;
  95. next_entry_point = header_.entity_scripts[entity_index][script_index];
  96. } while (next_entry_point == cur_entry_point);
  97. return next_entry_point;
  98. }
  99. std::unique_ptr<Function> FieldDisassembler::StartFunction(size_t script_index){
  100. auto func = std::make_unique<Function>();
  101. func->ret_val = false;
  102. func->num_args = 0;
  103. func->name = "script_" + std::to_string(script_index);
  104. func->start_addr = address_;
  105. return func;
  106. }
  107. void FieldDisassembler::DoDisassemble(){
  108. // Loop through the scripts for each entity.
  109. for (size_t entity_number = 0; entity_number < header_.entity_scripts.size(); entity_number ++){
  110. std::string original_name = header_.field_entity_names[entity_number].data();
  111. // If the entity name was blank in the file then use a consistent generated name
  112. if (original_name.empty()) original_name = "entity_" + std::to_string(entity_number);
  113. const std::string entity_name = formatter_.GetFriendlyEntityName(original_name);
  114. // Only parse each script one.
  115. std::set<uint16> parsed_scripts;
  116. std::vector<ScriptInfo> script_info;
  117. // Collect the scripts to parse
  118. for (
  119. size_t script_index = 0;
  120. script_index < header_.entity_scripts[entity_number].size();
  121. script_index ++
  122. ){
  123. uint16 script_entry_point = header_.entity_scripts[entity_number][script_index];
  124. // If this scripts entry point is already parsed, don't do it again as it means
  125. // two scripts have the same entry, which only seems to be true for "empty" scripts.
  126. if (parsed_scripts.find(script_entry_point) != std::end(parsed_scripts)) continue;
  127. parsed_scripts.insert(script_entry_point);
  128. const uint32 next_script_entry_point = GetEndOfScriptOffset(
  129. script_entry_point, entity_number, script_index
  130. );
  131. const uint32 script_size = next_script_entry_point - script_entry_point;
  132. if (script_size > 0){
  133. ScriptInfo info = {script_entry_point, next_script_entry_point, script_index};
  134. script_info.push_back(info);
  135. }
  136. }
  137. for (auto it = script_info.begin(); it != script_info.end(); it ++){
  138. const bool is_start = it == script_info.begin();
  139. const bool is_end = it == (-- script_info.end());
  140. DisassembleIndivdualScript(
  141. entity_name, entity_number, it->index, it->entry_point,
  142. it->next_entry_point, is_start, is_end
  143. );
  144. }
  145. }
  146. }
  147. int FieldDisassembler::FindId(uint32 start_addr, uint32 end_addr, const InstVec& insts){
  148. for (const InstPtr& instruction : insts){
  149. if (instruction->GetAddress() >= start_addr && instruction->GetAddress() <= end_addr){
  150. if (instruction->GetOpcode() == OPCODES::opCodeCHAR)
  151. return instruction->GetParam(0)->GetSigned();
  152. }
  153. }
  154. return -1;
  155. }
  156. void FieldDisassembler::AddFunc(
  157. std::string entity_name, size_t entity_index, size_t script_index, uint32 next_script_entry_point,
  158. const bool is_start, bool is_end, bool to_return_only, std::string func_name
  159. ){
  160. bool is_line = false;
  161. std::vector<float> point_a = {0, 0, 0};
  162. std::vector<float> point_b = {0, 0, 0};
  163. const auto SCRIPT_ENTRY_POINT = stream_->GetPosition();
  164. // Read each block of opcodes up to a return.
  165. const size_t old_num_instructions = insts_.size();
  166. // Initialize the function.
  167. std::unique_ptr<Function> func = StartFunction(script_index);
  168. // Read.
  169. if (to_return_only){
  170. // Read opcodes to the end or bail at the first return.
  171. is_line = ReadOpCodesToPositionOrReturn(
  172. next_script_entry_point + section_pointers_size_, point_a, point_b
  173. );
  174. auto stream_pos = stream_->GetPosition();
  175. const size_t endPos = next_script_entry_point + section_pointers_size_;
  176. // Can't be the end if there is more data:
  177. if (stream_pos != endPos) is_end = false;
  178. }
  179. else{
  180. // Keep going until all of the scriptis fectched, i.e if bailed at a
  181. // return, then call again until everything is parsed.
  182. while (stream_->GetPosition() != next_script_entry_point + section_pointers_size_){
  183. is_line = ReadOpCodesToPositionOrReturn(
  184. next_script_entry_point + section_pointers_size_, point_a, point_b
  185. );
  186. }
  187. }
  188. // Read metadata, mark start and/or end.
  189. std::string meta_data;
  190. if (is_start && is_end) meta_data = "start_end_";
  191. else if (is_start) meta_data = "start_";
  192. else if (is_end) meta_data = "end_";
  193. const size_t new_num_instructions = insts_.size();
  194. func->num_instructions = new_num_instructions - old_num_instructions;
  195. func->end_addr = insts_.back()->GetAddress();
  196. if (!func_name.empty()) func->name = func_name;
  197. if (engine_->EntityIsLine(entity_index)){
  198. switch (script_index){
  199. // main - on_update
  200. case 0: break;
  201. // [OK] - on_interact
  202. case 1: break;
  203. // Move - on_enter_line
  204. case 2: func->name = "on_enter_line"; break;
  205. // Move - on_move_to_line
  206. case 3: func->name = "on_move_to_line"; break;
  207. // Go - on_cross_line
  208. case 4: func->name = "on_cross_line"; break;
  209. // Go1x - on_cross_line
  210. case 5: func->name = "on_cross_line_once"; break;
  211. // GoAway - on_leave_line
  212. case 6: func->name = "on_leave_line"; break;
  213. }
  214. }
  215. int id = FindId(func->start_addr, func->end_addr, insts_);
  216. // If there is no ID check if there was an ID for this entity in any of
  217. // its other functions and use that instead.
  218. if (id == -1){
  219. for (auto& func : engine_->functions){
  220. FunctionMetaData func_meta_data(func.second.metadata);
  221. if (func_meta_data.GetEntityName() == entity_name && func_meta_data.GetCharacterId() != -1){
  222. id = func_meta_data.GetCharacterId();
  223. break;
  224. }
  225. }
  226. }
  227. meta_data += std::to_string(id) + "_" + entity_name;
  228. func->metadata = meta_data;
  229. engine_->functions[SCRIPT_ENTRY_POINT] = *func;
  230. engine_->AddEntityFunction(entity_name, entity_index, func->name, script_index);
  231. // If the entity is a line, mark it as so.
  232. if (is_line) engine_->MarkEntityAsLine(entity_index, true, point_a, point_b);
  233. }
  234. void FieldDisassembler::DisassembleIndivdualScript(
  235. std::string entity_name, size_t entity_index, size_t script_index,
  236. size_t script_entry_point, uint32 next_script_entry_point, bool is_start, bool is_end)
  237. {
  238. script_entry_point += section_pointers_size_;
  239. stream_->Seek(script_entry_point);
  240. address_base_ = stream_->GetPosition();
  241. address_ = address_base_;
  242. // "Normal" script
  243. if (script_index > 0){
  244. if (script_index == 1){
  245. AddFunc(
  246. entity_name, entity_index, script_index, next_script_entry_point,
  247. is_start, is_end, false, "on_interact"
  248. );
  249. }
  250. else{
  251. AddFunc(
  252. entity_name, entity_index, script_index, next_script_entry_point,
  253. is_start, is_end, false, ""
  254. );
  255. }
  256. }
  257. else{
  258. const size_t end_pos = next_script_entry_point + section_pointers_size_;
  259. // Read the init script, which means stop at the first return.
  260. AddFunc(
  261. entity_name, entity_index, script_index, next_script_entry_point,
  262. is_start, is_end, true, "on_start"
  263. );
  264. // Not at the end of this script? Then the remaining data is the "main" script
  265. auto stream_pos = stream_->GetPosition();
  266. if (stream_pos != end_pos){
  267. // The "main" script can have more than one return statement...
  268. AddFunc(
  269. entity_name, entity_index, script_index, next_script_entry_point,
  270. false, is_end, false, "on_update"
  271. );
  272. stream_pos = stream_->GetPosition();
  273. // ... but should end exactly on the end pos
  274. if (stream_pos != end_pos) throw DecompilerException();
  275. }
  276. }
  277. }
  278. FieldDisassembler::InstructionRecord FieldDisassembler::FLOW_OPCODES[] ={
  279. {1, OPCODES::RET, "RET", "", FieldControlFlowInstruction::Create},
  280. {1, OPCODES::REQ, "REQ", "BU", FieldControlFlowInstruction::Create},
  281. {1, OPCODES::REQSW, "REQSW", "BU", FieldControlFlowInstruction::Create},
  282. {1, OPCODES::REQEW, "REQEW", "BU", FieldControlFlowInstruction::Create},
  283. {1, OPCODES::NOP, "NOP", "", FieldNoOperationInstruction::Create},
  284. {1, OPCODES::IFUB, "IFUB", "NNBBBL", FieldNoOperationInstruction::Create}
  285. };
  286. std::map<std::string, const FieldDisassembler::InstructionRecord*>
  287. FieldDisassembler::FieldInstructions(){
  288. // Convert the array to a map that we can query on by opcode name.
  289. std::map<std::string, const InstructionRecord*> name_to_instruction_records;
  290. for (size_t i = 0; i < boost::size(FLOW_OPCODES); i ++)
  291. name_to_instruction_records[FLOW_OPCODES[i].opcode_name] = &FLOW_OPCODES[i];
  292. return name_to_instruction_records;
  293. }
  294. bool FieldDisassembler::ReadOpCodesToPositionOrReturn(
  295. size_t end_pos, std::vector<float>& point_a, std::vector<float>& point_b
  296. ){
  297. bool is_line = false;
  298. std::vector<unsigned int> exitAddrs;
  299. while (stream_->GetPosition() < end_pos){
  300. uint8 opcode = stream_->ReadU8();
  301. uint32 full_opcode = 0;
  302. full_opcode = (full_opcode << 8) + opcode;
  303. switch (opcode){
  304. // Flow
  305. case OPCODES::IFUB:
  306. ParseOpcode(full_opcode, "IFUB", new FieldCondJumpInstruction(), 0, "NBBBB");
  307. break;
  308. case OPCODES::RET:
  309. ParseOpcode(full_opcode, "RET", new FieldControlFlowInstruction(), 0, "");
  310. break;
  311. case OPCODES::REQ:
  312. ParseOpcode(full_opcode, "REQ", new FieldControlFlowInstruction(), 0, "BU");
  313. break;
  314. case OPCODES::REQSW:
  315. ParseOpcode(full_opcode, "REQSW", new FieldControlFlowInstruction(), 0, "BU");
  316. break;
  317. case OPCODES::REQEW:
  318. ParseOpcode(full_opcode, "REQEW", new FieldControlFlowInstruction(), 0, "BU");
  319. break;
  320. case OPCODES::PREQ:
  321. ParseOpcode(full_opcode, "PREQ", new FieldControlFlowInstruction(), 0, "BU");
  322. break;
  323. case OPCODES::PRQSW:
  324. ParseOpcode(full_opcode, "PRQSW", new FieldControlFlowInstruction(), 0, "BU");
  325. break;
  326. case OPCODES::PRQEW:
  327. ParseOpcode(full_opcode, "PRQEW", new FieldControlFlowInstruction(), 0, "BU");
  328. break;
  329. case OPCODES::RETTO:
  330. ParseOpcode(full_opcode, "RETTO", new FieldControlFlowInstruction(), 0, "U");
  331. break;
  332. case OPCODES::JMPF:
  333. ParseOpcode(full_opcode, "JMPF", new FieldUncondJumpInstruction(), 0, "B");
  334. break;
  335. case OPCODES::JMPFL:
  336. ParseOpcode(full_opcode, "JMPFL", new FieldUncondJumpInstruction(), 0, "w");
  337. break;
  338. case OPCODES::JMPB:
  339. ParseOpcode(full_opcode, "JMPB", new FieldUncondJumpInstruction(), 0, "B");
  340. break;
  341. case OPCODES::JMPBL:
  342. ParseOpcode(full_opcode, "JMPBL", new FieldUncondJumpInstruction(), 0, "w");
  343. break;
  344. case OPCODES::IFUBL:
  345. ParseOpcode(full_opcode, "IFUBL", new FieldCondJumpInstruction(), 0, "NBBBw");
  346. break;
  347. case OPCODES::IFSW:
  348. ParseOpcode(full_opcode, "IFSW", new FieldCondJumpInstruction(), 0, "NwwBB");
  349. break;
  350. case OPCODES::IFSWL:
  351. ParseOpcode(full_opcode, "IFSWL", new FieldCondJumpInstruction(), 0, "NwwBw");
  352. break;
  353. case OPCODES::IFUW:
  354. ParseOpcode(full_opcode, "IFUW", new FieldCondJumpInstruction(), 0, "NwwBB");
  355. break;
  356. case OPCODES::IFUWL:
  357. ParseOpcode(full_opcode, "IFUWL", new FieldCondJumpInstruction(), 0, "NwwBw");
  358. break;
  359. case OPCODES::WAIT:
  360. ParseOpcode(full_opcode, "WAIT", new FieldControlFlowInstruction(), 0, "w");
  361. break;
  362. case OPCODES::IFKEY:
  363. ParseOpcode(full_opcode, "IFKEY", new FieldCondJumpInstruction(), 0, "wB");
  364. break;
  365. case OPCODES::IFKEYON:
  366. ParseOpcode(full_opcode, "IFKEYON", new FieldCondJumpInstruction(), 0, "wB");
  367. break;
  368. case OPCODES::IFKEYOFF:
  369. ParseOpcode(full_opcode, "IFKEYOFF", new FieldCondJumpInstruction(), 0, "wB");
  370. break;
  371. case OPCODES::NOP:
  372. ParseOpcode(full_opcode, "NOP", new FieldNoOperationInstruction(), 0, "");
  373. break;
  374. case OPCODES::IFPRTYQ:
  375. ParseOpcode(full_opcode, "IFPRTYQ", new FieldCondJumpInstruction(), 0, "BB");
  376. break;
  377. case OPCODES::IFMEMBQ:
  378. ParseOpcode(full_opcode, "IFMEMBQ", new FieldCondJumpInstruction(), 0, "BB");
  379. break;
  380. // Module
  381. case OPCODES::DSKCG:
  382. ParseOpcode(full_opcode, "DSKCG", new FieldModuleInstruction(), 0, "B");
  383. break;
  384. case OPCODES::SPECIAL:
  385. full_opcode = 0;
  386. full_opcode = (full_opcode << 8) + OPCODES::SPECIAL;
  387. opcode = this->stream_->ReadU8();
  388. switch (opcode){
  389. case OPCODES_SPECIAL::ARROW:
  390. ParseOpcode(full_opcode, "ARROW", new FieldModuleInstruction(), 0, "B");
  391. break;
  392. case OPCODES_SPECIAL::PNAME:
  393. ParseOpcode(full_opcode, "PNAME", new FieldModuleInstruction(), 0, "B");
  394. break;
  395. case OPCODES_SPECIAL::GMSPD:
  396. ParseOpcode(full_opcode, "GMSPD", new FieldModuleInstruction(), 0, "B");
  397. break;
  398. case OPCODES_SPECIAL::SMSPD:
  399. ParseOpcode(full_opcode, "SMSPD", new FieldModuleInstruction(), 0, "BB");
  400. break;
  401. case OPCODES_SPECIAL::FLMAT:
  402. ParseOpcode(full_opcode, "FLMAT", new FieldModuleInstruction(), 0, "");
  403. break;
  404. case OPCODES_SPECIAL::FLITM:
  405. ParseOpcode(full_opcode, "FLITM", new FieldModuleInstruction(), 0, "");
  406. break;
  407. case OPCODES_SPECIAL::BTLCK:
  408. ParseOpcode(full_opcode, "BTLCK", new FieldModuleInstruction(), 0, "B");
  409. break;
  410. case OPCODES_SPECIAL::MVLCK:
  411. ParseOpcode(full_opcode, "MVLCK", new FieldModuleInstruction(), 0, "B");
  412. break;
  413. case OPCODES_SPECIAL::SPCNM:
  414. ParseOpcode(full_opcode, "SPCNM", new FieldModuleInstruction(), 0, "BB");
  415. break;
  416. case OPCODES_SPECIAL::RSGLB:
  417. ParseOpcode(full_opcode, "RSGLB", new FieldModuleInstruction(), 0, "");
  418. break;
  419. case OPCODES_SPECIAL::CLITM:
  420. ParseOpcode(full_opcode, "CLITM", new FieldModuleInstruction(), 0, "");
  421. break;
  422. default:
  423. throw UnknownSubOpcodeException(this->address_, opcode);\
  424. }
  425. this->address_++ ;
  426. break;
  427. case OPCODES::MINIGAME:
  428. ParseOpcode(full_opcode, "MINIGAME", new FieldModuleInstruction(), 0, "wsswBB");
  429. break;
  430. case OPCODES::BTMD2:
  431. ParseOpcode(full_opcode, "BTMD2", new FieldModuleInstruction(), 0, "d");
  432. break;
  433. case OPCODES::BTRLD:
  434. ParseOpcode(full_opcode, "BTRLD", new FieldModuleInstruction(), 0, "NB");
  435. break;
  436. case OPCODES::BTLTB:
  437. ParseOpcode(full_opcode, "BTLTB", new FieldModuleInstruction(), 0, "B");
  438. break;
  439. case OPCODES::MAPJUMP:
  440. ParseOpcode(full_opcode, "MAPJUMP", new FieldModuleInstruction(), 0, "wsswB");
  441. break;
  442. case OPCODES::LSTMP:
  443. ParseOpcode(full_opcode, "LSTMP", new FieldModuleInstruction(), 0, "NB");
  444. break;
  445. case OPCODES::BATTLE:
  446. ParseOpcode(full_opcode, "BATTLE", new FieldModuleInstruction(), 0, "Nw");
  447. break;
  448. case OPCODES::BTLON:
  449. ParseOpcode(full_opcode, "BTLON", new FieldModuleInstruction(), 0, "B");
  450. break;
  451. case OPCODES::BTLMD:
  452. ParseOpcode(full_opcode, "BTLMD", new FieldModuleInstruction(), 0, "w");
  453. break;
  454. case OPCODES::MPJPO:
  455. ParseOpcode(full_opcode, "MPJPO", new FieldModuleInstruction(), 0, "B");
  456. break;
  457. case OPCODES::PMJMP:
  458. ParseOpcode(full_opcode, "PMJMP", new FieldModuleInstruction(), 0, "w");
  459. break;
  460. case OPCODES::PMJMP2:
  461. ParseOpcode(full_opcode, "PMJMP2", new FieldModuleInstruction(), 0, "");
  462. break;
  463. case OPCODES::GAMEOVER:
  464. ParseOpcode(full_opcode, "GAMEOVER", new FieldModuleInstruction(), 0, "");
  465. break;
  466. // Math
  467. case OPCODES::PLUS_:
  468. ParseOpcode(full_opcode, "PLUS!", new FieldMathInstruction(), 0, "NBB");
  469. break;
  470. case OPCODES::PLUS2_:
  471. ParseOpcode(full_opcode, "PLUS2!", new FieldMathInstruction(), 0, "NBw");
  472. break;
  473. case OPCODES::MINUS_:
  474. ParseOpcode(full_opcode, "MINUS!", new FieldMathInstruction(), 0, "NBB");
  475. break;
  476. case OPCODES::MINUS2_:
  477. ParseOpcode(full_opcode, "MINUS2!", new FieldMathInstruction(), 0, "NBw");
  478. break;
  479. case OPCODES::INC_:
  480. ParseOpcode(full_opcode, "INC!", new FieldMathInstruction(), 0, "BB");
  481. break;
  482. case OPCODES::INC2_:
  483. ParseOpcode(full_opcode, "INC2!", new FieldMathInstruction(), 0, "BB");
  484. break;
  485. case OPCODES::DEC_:
  486. ParseOpcode(full_opcode, "DEC!", new FieldMathInstruction(), 0, "BB");
  487. break;
  488. case OPCODES::DEC2_:
  489. ParseOpcode(full_opcode, "DEC2!", new FieldMathInstruction(), 0, "BB");
  490. break;
  491. case OPCODES::RDMSD:
  492. ParseOpcode(full_opcode, "RDMSD", new FieldMathInstruction(), 0, "NB");
  493. break;
  494. case OPCODES::SETBYTE:
  495. ParseOpcode(full_opcode, "SETBYTE", new FieldMathInstruction(), 0, "NBB");
  496. break;
  497. case OPCODES::SETWORD:
  498. ParseOpcode(full_opcode, "SETWORD", new FieldMathInstruction(), 0, "NBw");
  499. break;
  500. case OPCODES::BITON:
  501. ParseOpcode(full_opcode, "BITON", new FieldMathInstruction(), 0, "NBB");
  502. break;
  503. case OPCODES::BITOFF:
  504. ParseOpcode(full_opcode, "BITOFF", new FieldMathInstruction(), 0, "NBB");
  505. break;
  506. case OPCODES::BITXOR:
  507. ParseOpcode(full_opcode, "BITXOR", new FieldMathInstruction(), 0, "NBB");
  508. break;
  509. case OPCODES::PLUS:
  510. ParseOpcode(full_opcode, "PLUS", new FieldMathInstruction(), 0, "NBB");
  511. break;
  512. case OPCODES::PLUS2:
  513. ParseOpcode(full_opcode, "PLUS2", new FieldMathInstruction(), 0, "NBw");
  514. break;
  515. case OPCODES::MINUS:
  516. ParseOpcode(full_opcode, "MINUS", new FieldMathInstruction(), 0, "NBB");
  517. break;
  518. case OPCODES::MINUS2:
  519. ParseOpcode(full_opcode, "MINUS2", new FieldMathInstruction(), 0, "NBw");
  520. break;
  521. case OPCODES::MUL:
  522. ParseOpcode(full_opcode, "MUL", new FieldMathInstruction(), 0, "NBB");
  523. break;
  524. case OPCODES::MUL2:
  525. ParseOpcode(full_opcode, "MUL2", new FieldMathInstruction(), 0, "NBw");
  526. break;
  527. case OPCODES::DIV:
  528. ParseOpcode(full_opcode, "DIV", new FieldMathInstruction(), 0, "NBB");
  529. break;
  530. case OPCODES::DIV2:
  531. ParseOpcode(full_opcode, "DIV2", new FieldMathInstruction(), 0, "NBw");
  532. break;
  533. case OPCODES::MOD:
  534. ParseOpcode(full_opcode, "MOD", new FieldMathInstruction(), 0, "NBB");
  535. break;
  536. case OPCODES::MOD2:
  537. ParseOpcode(full_opcode, "MOD2", new FieldMathInstruction(), 0, "NBw");
  538. break;
  539. case OPCODES::AND:
  540. ParseOpcode(full_opcode, "AND", new FieldMathInstruction(), 0, "NBB");
  541. break;
  542. case OPCODES::AND2:
  543. ParseOpcode(full_opcode, "AND2", new FieldMathInstruction(), 0, "NBw");
  544. break;
  545. case OPCODES::OR:
  546. ParseOpcode(full_opcode, "OR", new FieldMathInstruction(), 0, "NBB");
  547. break;
  548. case OPCODES::OR2:
  549. ParseOpcode(full_opcode, "OR2", new FieldMathInstruction(), 0, "NBw");
  550. break;
  551. case OPCODES::XOR:
  552. ParseOpcode(full_opcode, "XOR", new FieldMathInstruction(), 0, "NBB");
  553. break;
  554. case OPCODES::XOR2:
  555. ParseOpcode(full_opcode, "XOR2", new FieldMathInstruction(), 0, "NBw");
  556. break;
  557. case OPCODES::INC:
  558. ParseOpcode(full_opcode, "INC", new FieldMathInstruction(), 0, "BB");
  559. break;
  560. case OPCODES::INC2:
  561. ParseOpcode(full_opcode, "INC2", new FieldMathInstruction(), 0, "BB");
  562. break;
  563. case OPCODES::DEC:
  564. ParseOpcode(full_opcode, "DEC", new FieldMathInstruction(), 0, "BB");
  565. break;
  566. case OPCODES::DEC2:
  567. ParseOpcode(full_opcode, "DEC2", new FieldMathInstruction(), 0, "BB");
  568. break;
  569. case OPCODES::RANDOM:
  570. ParseOpcode(full_opcode, "RANDOM", new FieldMathInstruction(), 0, "BB");
  571. break;
  572. case OPCODES::LBYTE:
  573. ParseOpcode(full_opcode, "LBYTE", new FieldMathInstruction(), 0, "NBB");
  574. break;
  575. case OPCODES::HBYTE:
  576. ParseOpcode(full_opcode, "HBYTE", new FieldMathInstruction(), 0, "NBw");
  577. break;
  578. case OPCODES::TWOBYTE:
  579. ParseOpcode(full_opcode, "2BYTE", new FieldMathInstruction(), 0, "NNBBB");
  580. break;
  581. case OPCODES::SIN:
  582. ParseOpcode(full_opcode, "SIN", new FieldMathInstruction(), 0, "NNwwwB");
  583. break;
  584. case OPCODES::COS:
  585. ParseOpcode(full_opcode, "COS", new FieldMathInstruction(), 0, "NNwwwB");
  586. break;
  587. // Window
  588. case OPCODES::TUTOR:
  589. ParseOpcode(full_opcode, "TUTOR", new FieldWindowInstruction(), 0, "B");
  590. break;
  591. case OPCODES::WCLS:
  592. ParseOpcode(full_opcode, "WCLS", new FieldWindowInstruction(), 0, "B");
  593. break;
  594. case OPCODES::WSIZW:
  595. ParseOpcode(full_opcode, "WSIZW", new FieldWindowInstruction(), 0, "Bwwww");
  596. break;
  597. case OPCODES::WSPCL:
  598. ParseOpcode(full_opcode, "WSPCL", new FieldWindowInstruction(), 0, "BBBB");
  599. break;
  600. case OPCODES::WNUMB:
  601. ParseOpcode(full_opcode, "WNUMB", new FieldWindowInstruction(), 0, "NBwwB");
  602. break;
  603. case OPCODES::STTIM:
  604. ParseOpcode(full_opcode, "STTIM", new FieldWindowInstruction(), 0, "NNBBB");
  605. break;
  606. case OPCODES::MESSAGE:
  607. ParseOpcode(full_opcode, "MESSAGE", new FieldWindowInstruction(), 0, "BB");
  608. break;
  609. case OPCODES::MPARA:
  610. ParseOpcode(full_opcode, "MPARA", new FieldWindowInstruction(), 0, "NBBB");
  611. break;
  612. case OPCODES::MPRA2:
  613. ParseOpcode(full_opcode, "MPRA2", new FieldWindowInstruction(), 0, "NBBw");
  614. break;
  615. case OPCODES::MPNAM:
  616. ParseOpcode(full_opcode, "MPNAM", new FieldWindowInstruction(), 0, "B");
  617. break;
  618. case OPCODES::ASK:
  619. ParseOpcode(full_opcode, "ASK", new FieldWindowInstruction(), 0, "NBBBBB");
  620. break;
  621. case OPCODES::MENU:
  622. ParseOpcode(full_opcode, "MENU", new FieldWindowInstruction(), 0, "NBB");
  623. break;
  624. case OPCODES::MENU2:
  625. ParseOpcode(full_opcode, "MENU2", new FieldWindowInstruction(), 0, "B");
  626. break;
  627. case OPCODES::WINDOW:
  628. ParseOpcode(full_opcode, "WINDOW", new FieldWindowInstruction(), 0, "Bwwww");
  629. break;
  630. case OPCODES::WMOVE:
  631. ParseOpcode(full_opcode, "WMOVE", new FieldWindowInstruction(), 0, "Bss");
  632. break;
  633. case OPCODES::WMODE:
  634. ParseOpcode(full_opcode, "WMODE", new FieldWindowInstruction(), 0, "BBB");
  635. break;
  636. case OPCODES::WREST:
  637. ParseOpcode(full_opcode, "WREST", new FieldWindowInstruction(), 0, "B");
  638. break;
  639. case OPCODES::WCLSE:
  640. ParseOpcode(full_opcode, "WCLSE", new FieldWindowInstruction(), 0, "B");
  641. break;
  642. case OPCODES::WROW:
  643. ParseOpcode(full_opcode, "WROW", new FieldWindowInstruction(), 0, "BB");
  644. break;
  645. case OPCODES::GWCOL:
  646. ParseOpcode(full_opcode, "GWCOL", new FieldWindowInstruction(), 0, "NNBBBB");
  647. break;
  648. case OPCODES::SWCOL:
  649. ParseOpcode(full_opcode, "SWCOL", new FieldWindowInstruction(), 0, "NNBBBB");
  650. break;
  651. // Party
  652. case OPCODES::SPTYE:
  653. ParseOpcode(full_opcode, "SPTYE", new FieldPartyInstruction(), 0, "NNBBB");
  654. break;
  655. case OPCODES::GTPYE:
  656. ParseOpcode(full_opcode, "GTPYE", new FieldPartyInstruction(), 0, "NNBBB");
  657. break;
  658. case OPCODES::GOLDU:
  659. // Goldu can have two argument formats: (nybble, word) or (nybble, byte, 3 bytes)
  660. // Read it as nybble, byte, byte, byte, byte and operate later
  661. ParseOpcode(full_opcode, "GOLDU", new FieldPartyInstruction(), 0, "BBBBB");
  662. break;
  663. case OPCODES::GOLDD:
  664. ParseOpcode(full_opcode, "GOLDD", new FieldPartyInstruction(), 0, "Nww");
  665. break;
  666. case OPCODES::CHGLD:
  667. ParseOpcode(full_opcode, "CHGLD", new FieldPartyInstruction(), 0, "NBB");
  668. break;
  669. case OPCODES::HMPMAX1:
  670. ParseOpcode(full_opcode, "HMPMAX1", new FieldPartyInstruction(), 0, "");
  671. break;
  672. case OPCODES::HMPMAX2:
  673. ParseOpcode(full_opcode, "HMPMAX2", new FieldPartyInstruction(), 0, "");
  674. break;
  675. case OPCODES::MHMMX:
  676. ParseOpcode(full_opcode, "MHMMX", new FieldPartyInstruction(), 0, "");
  677. break;
  678. case OPCODES::HMPMAX3:
  679. ParseOpcode(full_opcode, "HMPMAX3", new FieldPartyInstruction(), 0, "");
  680. break;
  681. case OPCODES::MPU:
  682. ParseOpcode(full_opcode, "MPU", new FieldPartyInstruction(), 0, "NBw");
  683. break;
  684. case OPCODES::MPD:
  685. ParseOpcode(full_opcode, "MPD", new FieldPartyInstruction(), 0, "NBw");
  686. break;
  687. case OPCODES::HPU:
  688. ParseOpcode(full_opcode, "HPU", new FieldPartyInstruction(), 0, "NBw");
  689. break;
  690. case OPCODES::HPD:
  691. ParseOpcode(full_opcode, "HPD", new FieldPartyInstruction(), 0, "NBw");
  692. break;
  693. case OPCODES::STITM:
  694. ParseOpcode(full_opcode, "STITM", new FieldPartyInstruction(), 0, "NwB");
  695. break;
  696. case OPCODES::DLITM:
  697. ParseOpcode(full_opcode, "DLITM", new FieldPartyInstruction(), 0, "NwB");
  698. break;
  699. case OPCODES::CKITM:
  700. ParseOpcode(full_opcode, "CKITM", new FieldPartyInstruction(), 0, "NwB");
  701. break;
  702. case OPCODES::SMTRA:
  703. ParseOpcode(full_opcode, "SMTRA", new FieldPartyInstruction(), 0, "NNBBBB");
  704. break;
  705. case OPCODES::DMTRA:
  706. ParseOpcode(full_opcode, "DMTRA", new FieldPartyInstruction(), 0, "NNBBBBB");
  707. break;
  708. case OPCODES::CMTRA:
  709. ParseOpcode(full_opcode, "CMTRA", new FieldPartyInstruction(), 0, "NNNBBBBBB");
  710. break;
  711. case OPCODES::GETPC:
  712. ParseOpcode(full_opcode, "GETPC", new FieldPartyInstruction(), 0, "NBB");
  713. break;
  714. case OPCODES::PRTYP:
  715. ParseOpcode(full_opcode, "PRTYP", new FieldPartyInstruction(), 0, "B");
  716. break;
  717. case OPCODES::PRTYM:
  718. ParseOpcode(full_opcode, "PRTYM", new FieldPartyInstruction(), 0, "B");
  719. break;
  720. case OPCODES::PRTYE:
  721. ParseOpcode(full_opcode, "PRTYE", new FieldPartyInstruction(), 0, "BBB");
  722. break;
  723. case OPCODES::MMBUD:
  724. ParseOpcode(full_opcode, "MMBUD", new FieldPartyInstruction(), 0, "BB");
  725. break;
  726. case OPCODES::MMBLK:
  727. ParseOpcode(full_opcode, "MMBLK", new FieldPartyInstruction(), 0, "B");
  728. break;
  729. case OPCODES::MMBUK:
  730. ParseOpcode(full_opcode, "MMBUK", new FieldPartyInstruction(), 0, "B");
  731. break;
  732. // Model
  733. case OPCODES::JOIN:
  734. ParseOpcode(full_opcode, "JOIN", new FieldModelInstruction(), 0, "B");
  735. break;
  736. case OPCODES::SPLIT:
  737. ParseOpcode(full_opcode, "SPLIT", new FieldModelInstruction(), 0, "NNNssBssBB");
  738. break;
  739. case OPCODES::BLINK:
  740. ParseOpcode(full_opcode, "BLINK", new FieldModelInstruction(), 0, "B");
  741. break;
  742. case OPCODES::KAWAI:
  743. {
  744. full_opcode = 0;
  745. full_opcode = (full_opcode << 8) + OPCODES::KAWAI;
  746. int length = this->stream_->ReadU8();
  747. assert(length >= 3);
  748. std::ostringstream param_stream;
  749. for (int i = 3; i < length; ++ i) param_stream << "B";
  750. auto parameters = param_stream.str();
  751. opcode = this->stream_->ReadU8();
  752. switch (opcode){
  753. case OPCODES_KAWAI::EYETX:
  754. // Parameters were "BBBB"
  755. ParseOpcode(
  756. opcode, "EYETX", new FieldModelInstruction(), 0, parameters.c_str()
  757. );
  758. break;
  759. case OPCODES_KAWAI::TRNSP:
  760. // Parameters were "B"
  761. ParseOpcode(
  762. opcode, "TRNSP", new FieldModelInstruction(), 0, parameters.c_str()
  763. );
  764. break;
  765. case OPCODES_KAWAI::AMBNT:
  766. // Parameters were "AMBNT"
  767. ParseOpcode(
  768. opcode, "AMBNT",
  769. new FieldModelInstruction(), 0, parameters.c_str()
  770. );
  771. break;
  772. case OPCODES_KAWAI::Unknown03:
  773. ParseOpcode(
  774. opcode, "Unknown03",
  775. new FieldModelInstruction(), 0, parameters.c_str()
  776. );
  777. break;
  778. case OPCODES_KAWAI::Unknown04:
  779. ParseOpcode(
  780. opcode, "Unknown04",
  781. new FieldModelInstruction(), 0, parameters.c_str()
  782. );
  783. break;
  784. case OPCODES_KAWAI::Unknown05:
  785. ParseOpcode(
  786. opcode, "Unknown03",
  787. new FieldModelInstruction(), 0, parameters.c_str()
  788. );
  789. break;
  790. case OPCODES_KAWAI::LIGHT:
  791. ParseOpcode(
  792. opcode, "LIGHT",
  793. new FieldModelInstruction(), 0, parameters.c_str()
  794. );
  795. break;
  796. case OPCODES_KAWAI::Unknown07:
  797. ParseOpcode(
  798. opcode, "Unknown07",
  799. new FieldModelInstruction(), 0, parameters.c_str()
  800. );
  801. break;
  802. case OPCODES_KAWAI::Unknown08:
  803. ParseOpcode(
  804. opcode, "Unknown08",
  805. new FieldModelInstruction(), 0, parameters.c_str()
  806. );
  807. break;
  808. case OPCODES_KAWAI::Unknown09:
  809. ParseOpcode(
  810. opcode, "Unknown09",
  811. new FieldModelInstruction(), 0, parameters.c_str()
  812. );
  813. break;
  814. case OPCODES_KAWAI::SBOBJ:
  815. ParseOpcode(
  816. opcode, "SBOBJ", new FieldModelInstruction(), 0, parameters.c_str()
  817. );
  818. break;
  819. case OPCODES_KAWAI::Unknown0B:
  820. ParseOpcode(
  821. opcode, "Unknown0B",
  822. new FieldModelInstruction(), 0, parameters.c_str()
  823. );
  824. break;
  825. case OPCODES_KAWAI::Unknown0C:
  826. ParseOpcode(
  827. opcode, "Unknown0C", new FieldModelInstruction(), 0, parameters.c_str()
  828. );
  829. break;
  830. case OPCODES_KAWAI::SHINE:
  831. ParseOpcode(
  832. opcode, "SHINE", new FieldModelInstruction(), 0, parameters.c_str()
  833. );
  834. break;
  835. case OPCODES_KAWAI::RESET:
  836. ParseOpcode(
  837. opcode, "RESET", new FieldModelInstruction(), 0, parameters.c_str()
  838. );
  839. break;
  840. default:
  841. throw UnknownSubOpcodeException(this->address_, opcode);
  842. }
  843. this->address_ ++;
  844. this->address_ ++;
  845. break;
  846. }
  847. case OPCODES::KAWIW:
  848. ParseOpcode(full_opcode, "KAWIW", new FieldModelInstruction(), 0, "");
  849. break;
  850. case OPCODES::PMOVA:
  851. ParseOpcode(full_opcode, "PMOVA", new FieldModelInstruction(), 0, "B");
  852. break;
  853. case OPCODES::PDIRA:
  854. ParseOpcode(full_opcode, "PDIRA", new FieldModelInstruction(), 0, "B");
  855. break;
  856. case OPCODES::PTURA:
  857. ParseOpcode(full_opcode, "PTURA", new FieldModelInstruction(), 0, "BBB");
  858. break;
  859. case OPCODES::PGTDR:
  860. ParseOpcode(full_opcode, "PGTDR", new FieldModelInstruction(), 0, "NBB");
  861. break;
  862. case OPCODES::PXYZI:
  863. ParseOpcode(full_opcode, "PXYZI", new FieldModelInstruction(), 0, "NNBBBBB");
  864. break;
  865. case OPCODES::TLKON:
  866. ParseOpcode(full_opcode, "TLKON", new FieldModelInstruction(), 0, "B");
  867. break;
  868. case OPCODES::PC:
  869. ParseOpcode(full_opcode, "PC", new FieldModelInstruction(), 0, "B");
  870. break;
  871. case OPCODES::opCodeCHAR:
  872. ParseOpcode(full_opcode, "CHAR", new FieldModelInstruction(), 0, "B");
  873. break;
  874. case OPCODES::DFANM:
  875. ParseOpcode(full_opcode, "DFANM", new FieldModelInstruction(), 0, "BB");
  876. break;
  877. case OPCODES::ANIME1:
  878. ParseOpcode(full_opcode, "ANIME1", new FieldModelInstruction(), 0, "BB");
  879. break;
  880. case OPCODES::VISI:
  881. ParseOpcode(full_opcode, "VISI", new FieldModelInstruction(), 0, "B");
  882. break;
  883. case OPCODES::XYZI:
  884. ParseOpcode(full_opcode, "XYZI", new FieldModelInstruction(), 0, "NNsssw");
  885. break;
  886. case OPCODES::XYI:
  887. ParseOpcode(full_opcode, "XYI", new FieldModelInstruction(), 0, "NNssw");
  888. break;
  889. case OPCODES::XYZ:
  890. ParseOpcode(full_opcode, "XYZ", new FieldModelInstruction(), 0, "NNsss");
  891. break;
  892. case OPCODES::MOVE:
  893. ParseOpcode(full_opcode, "MOVE", new FieldModelInstruction(), 0, "Nss");
  894. break;
  895. case OPCODES::CMOVE:
  896. ParseOpcode(full_opcode, "CMOVE", new FieldModelInstruction(), 0, "Nss");
  897. break;
  898. case OPCODES::MOVA:
  899. ParseOpcode(full_opcode, "MOVA", new FieldModelInstruction(), 0, "B");
  900. break;
  901. case OPCODES::TURA:
  902. ParseOpcode(full_opcode, "TURA", new FieldModelInstruction(), 0, "BBB");
  903. break;
  904. case OPCODES::ANIMW:
  905. ParseOpcode(full_opcode, "ANIMW", new FieldModelInstruction(), 0, "");
  906. break;
  907. case OPCODES::FMOVE:
  908. ParseOpcode(full_opcode, "FMOVE", new FieldModelInstruction(), 0, "Nss");
  909. break;
  910. case OPCODES::ANIME2:
  911. ParseOpcode(full_opcode, "ANIME2", new FieldModelInstruction(), 0, "BB");
  912. break;
  913. case OPCODES::ANIM_1:
  914. ParseOpcode(full_opcode, "ANIM!1", new FieldModelInstruction(), 0, "BB");
  915. break;
  916. case OPCODES::CANIM1:
  917. ParseOpcode(full_opcode, "CANIM1", new FieldModelInstruction(), 0, "BBBB");
  918. break;
  919. case OPCODES::CANM_1:
  920. ParseOpcode(full_opcode, "CANM!1", new FieldModelInstruction(), 0, "BBBB");
  921. break;
  922. case OPCODES::MSPED:
  923. ParseOpcode(full_opcode, "MSPED", new FieldModelInstruction(), 0, "Nw");
  924. break;
  925. case OPCODES::DIR:
  926. ParseOpcode(full_opcode, "DIR", new FieldModelInstruction(), 0, "BB");
  927. break;
  928. case OPCODES::TURNGEN:
  929. ParseOpcode(full_opcode, "TURNGEN", new FieldModelInstruction(), 0, "NBBBB");
  930. break;
  931. case OPCODES::TURN:
  932. ParseOpcode(full_opcode, "TURN", new FieldModelInstruction(), 0, "NBBBB");
  933. break;
  934. case OPCODES::DIRA:
  935. ParseOpcode(full_opcode, "DIRA", new FieldModelInstruction(), 0, "B");
  936. break;
  937. case OPCODES::GETDIR:
  938. ParseOpcode(full_opcode, "GETDIR", new FieldModelInstruction(), 0, "NBB");
  939. break;
  940. case OPCODES::GETAXY:
  941. ParseOpcode(full_opcode, "GETAXY", new FieldModelInstruction(), 0, "NBBB");
  942. break;
  943. case OPCODES::GETAI:
  944. ParseOpcode(full_opcode, "GETAI", new FieldModelInstruction(), 0, "NBB");
  945. break;
  946. case OPCODES::ANIM_2:
  947. ParseOpcode(full_opcode, "ANIM!2", new FieldModelInstruction(), 0, "BB");
  948. break;
  949. case OPCODES::CANIM2:
  950. ParseOpcode(full_opcode, "CANIM2", new FieldModelInstruction(), 0, "BBBB");
  951. break;
  952. case OPCODES::CANM_2:
  953. ParseOpcode(full_opcode, "CANM!2", new FieldModelInstruction(), 0, "BBBB");
  954. break;
  955. case OPCODES::ASPED:
  956. ParseOpcode(full_opcode, "ASPED", new FieldModelInstruction(), 0, "Nw");
  957. break;
  958. case OPCODES::CC:
  959. ParseOpcode(full_opcode, "CC", new FieldModelInstruction(), 0, "B");
  960. break;
  961. case OPCODES::JUMP:
  962. ParseOpcode(full_opcode, "JUMP", new FieldModelInstruction(), 0, "NNssww");
  963. break;
  964. case OPCODES::AXYZI:
  965. ParseOpcode(full_opcode, "AXYZI", new FieldModelInstruction(), 0, "NNBBBBB");
  966. break;
  967. case OPCODES::LADER:
  968. ParseOpcode(full_opcode, "LADER", new FieldModelInstruction(), 0, "NNssswBBBB");
  969. break;
  970. case OPCODES::OFST:
  971. ParseOpcode(full_opcode, "OFST", new FieldModelInstruction(), 0, "NNBsssw");
  972. break;
  973. case OPCODES::OFSTW:
  974. ParseOpcode(full_opcode, "OFSTW", new FieldModelInstruction(), 0, "");
  975. break;
  976. case OPCODES::TALKR:
  977. ParseOpcode(full_opcode, "TALKR", new FieldModelInstruction(), 0, "NB");
  978. break;
  979. case OPCODES::SLIDR:
  980. ParseOpcode(full_opcode, "SLIDR", new FieldModelInstruction(), 0, "NB");
  981. break;
  982. case OPCODES::SOLID:
  983. ParseOpcode(full_opcode, "SOLID", new FieldModelInstruction(), 0, "B");
  984. break;
  985. case OPCODES::TLKR2:
  986. ParseOpcode(full_opcode, "TLKR2", new FieldModelInstruction(), 0, "Nw");
  987. break;
  988. case OPCODES::SLDR2:
  989. ParseOpcode(full_opcode, "SLDR2", new FieldModelInstruction(), 0, "Nw");
  990. break;
  991. case OPCODES::CCANM:
  992. ParseOpcode(full_opcode, "CCANM", new FieldModelInstruction(), 0, "BBB");
  993. break;
  994. case OPCODES::FCFIX:
  995. ParseOpcode(full_opcode, "FCFIX", new FieldModelInstruction(), 0, "B");
  996. break;
  997. case OPCODES::ANIMB:
  998. ParseOpcode(full_opcode, "ANIMB", new FieldModelInstruction(), 0, "");
  999. break;
  1000. case OPCODES::TURNW:
  1001. ParseOpcode(full_opcode, "TURNW", new FieldModelInstruction(), 0, "");
  1002. break;
  1003. // Walkmesh
  1004. case OPCODES::SLIP:
  1005. ParseOpcode(full_opcode, "SLIP", new FieldWalkmeshInstruction(), 0, "B");
  1006. break;
  1007. case OPCODES::UC:
  1008. ParseOpcode(full_opcode, "UC", new FieldWalkmeshInstruction(), 0, "B");
  1009. break;
  1010. case OPCODES::IDLCK:
  1011. ParseOpcode(full_opcode, "IDLCK", new FieldWalkmeshInstruction(), 0, "wB");
  1012. break;
  1013. case OPCODES::LINON:
  1014. ParseOpcode(full_opcode, "LINON", new FieldWalkmeshInstruction(), 0, "B");
  1015. break;
  1016. case OPCODES::SLINE:
  1017. ParseOpcode(full_opcode, "SLINE", new FieldWalkmeshInstruction(), 0, "NNNssssss");
  1018. break;
  1019. case OPCODES::LINE:
  1020. // Mark function entity owner as line.
  1021. is_line = true;
  1022. ParseOpcode(full_opcode, "LINE", new FieldWalkmeshInstruction(), 0, "ssssss");
  1023. point_a[0] = this->insts_.back()->GetParam(0)->GetSigned();
  1024. point_a[1] = this->insts_.back()->GetParam(1)->GetSigned();
  1025. point_a[2] = this->insts_.back()->GetParam(2)->GetSigned();
  1026. point_b[0] = this->insts_.back()->GetParam(3)->GetSigned();
  1027. point_b[1] = this->insts_.back()->GetParam(4)->GetSigned();
  1028. point_b[2] = this->insts_.back()->GetParam(5)->GetSigned();
  1029. break;
  1030. // Backgnd
  1031. case OPCODES::BGPDH:
  1032. ParseOpcode(full_opcode, "BGPDH", new FieldBackgroundInstruction(), 0, "NBs");
  1033. break;
  1034. case OPCODES::BGSCR:
  1035. ParseOpcode(full_opcode, "BGSCR", new FieldBackgroundInstruction(), 0, "NBss");
  1036. break;
  1037. case OPCODES::MPPAL:
  1038. ParseOpcode(full_opcode, "MPPAL", new FieldBackgroundInstruction(), 0, "NNNBBBBBBB");
  1039. break;
  1040. case OPCODES::BGON:
  1041. ParseOpcode(full_opcode, "BGON", new FieldBackgroundInstruction(), 0, "NBB");
  1042. break;
  1043. case OPCODES::BGOFF:
  1044. ParseOpcode(full_opcode, "BGOFF", new FieldBackgroundInstruction(), 0, "NBB");
  1045. break;
  1046. case OPCODES::BGROL:
  1047. ParseOpcode(full_opcode, "BGROL", new FieldBackgroundInstruction(), 0, "NB");
  1048. break;
  1049. case OPCODES::BGROL2:
  1050. ParseOpcode(full_opcode, "BGROL2", new FieldBackgroundInstruction(), 0, "NB");
  1051. break;
  1052. case OPCODES::BGCLR:
  1053. ParseOpcode(full_opcode, "BGCLR", new FieldBackgroundInstruction(), 0, "NB");
  1054. break;
  1055. case OPCODES::STPAL:
  1056. ParseOpcode(full_opcode, "STPAL", new FieldBackgroundInstruction(), 0, "NBBB");
  1057. break;
  1058. case OPCODES::LDPAL:
  1059. ParseOpcode(full_opcode, "LDPAL", new FieldBackgroundInstruction(), 0, "NBBB");
  1060. break;
  1061. case OPCODES::CPPAL:
  1062. ParseOpcode(full_opcode, "CPPAL", new FieldBackgroundInstruction(), 0, "NBBB");
  1063. break;
  1064. case OPCODES::RTPAL:
  1065. ParseOpcode(full_opcode, "RTPAL", new FieldBackgroundInstruction(), 0, "NNBBBB");
  1066. break;
  1067. case OPCODES::ADPAL:
  1068. ParseOpcode(full_opcode, "ADPAL", new FieldBackgroundInstruction(), 0, "NNNBBBBBB");
  1069. break;
  1070. case OPCODES::MPPAL2:
  1071. ParseOpcode(
  1072. full_opcode, "MPPAL2", new FieldBackgroundInstruction(), 0, "NNNBBBBBB"
  1073. );
  1074. break;
  1075. case OPCODES::STPLS:
  1076. ParseOpcode(full_opcode, "STPLS", new FieldBackgroundInstruction(), 0, "BBBB");
  1077. break;
  1078. case OPCODES::LDPLS:
  1079. ParseOpcode(full_opcode, "LDPLS", new FieldBackgroundInstruction(), 0, "BBBB");
  1080. break;
  1081. case OPCODES::CPPAL2:
  1082. ParseOpcode(full_opcode, "CPPAL2", new FieldBackgroundInstruction(), 0, "BBBBBBB");
  1083. break;
  1084. case OPCODES::RTPAL2:
  1085. ParseOpcode(full_opcode, "RTPAL2", new FieldBackgroundInstruction(), 0, "BBBBBBB");
  1086. break;
  1087. case OPCODES::ADPAL2:
  1088. ParseOpcode(full_opcode, "ADPAL2", new FieldBackgroundInstruction(), 0, "BBBBBBBBBB");
  1089. break;
  1090. // Camera
  1091. case OPCODES::NFADE:
  1092. ParseOpcode(full_opcode, "NFADE", new FieldCameraInstruction(), 0, "NNBBBBBB");
  1093. break;
  1094. case OPCODES::SHAKE:
  1095. ParseOpcode(full_opcode, "SHAKE", new FieldCameraInstruction(), 0, "BBBBBBB");
  1096. break;
  1097. case OPCODES::SCRLO:
  1098. ParseOpcode(full_opcode, "SCRLO", new FieldCameraInstruction(), 0, "B");
  1099. break;
  1100. case OPCODES::SCRLC:
  1101. ParseOpcode(full_opcode, "SCRLC", new FieldCameraInstruction(), 0, "BBBB");
  1102. break;
  1103. case OPCODES::SCRLA:
  1104. ParseOpcode(full_opcode, "SCRLA", new FieldCameraInstruction(), 0, "NwBB");
  1105. break;
  1106. case OPCODES::SCR2D:
  1107. ParseOpcode(full_opcode, "SCR2D", new FieldCameraInstruction(), 0, "Nss");
  1108. break;
  1109. case OPCODES::SCRCC:
  1110. ParseOpcode(full_opcode, "SCRCC", new FieldCameraInstruction(), 0, "");
  1111. break;
  1112. case OPCODES::SCR2DC:
  1113. ParseOpcode(full_opcode, "SCR2DC", new FieldCameraInstruction(), 0, "NNssw");
  1114. break;
  1115. case OPCODES::SCRLW:
  1116. ParseOpcode(full_opcode, "SCRLW", new FieldCameraInstruction(), 0, "");
  1117. break;
  1118. case OPCODES::SCR2DL:
  1119. ParseOpcode(full_opcode, "SCR2DL", new FieldCameraInstruction(), 0, "NNssw");
  1120. break;
  1121. case OPCODES::VWOFT:
  1122. ParseOpcode(full_opcode, "VWOFT", new FieldCameraInstruction(), 0, "NssB");
  1123. break;
  1124. case OPCODES::FADE:
  1125. ParseOpcode(full_opcode, "FADE", new FieldCameraInstruction(), 0, "NNBBBBBB");
  1126. break;
  1127. case OPCODES::FADEW:
  1128. ParseOpcode(full_opcode, "FADEW", new FieldCameraInstruction(), 0, "");
  1129. break;
  1130. case OPCODES::SCRLP:
  1131. ParseOpcode(full_opcode, "SCRLP", new FieldCameraInstruction(), 0, "NwBB");
  1132. break;
  1133. case OPCODES::MVCAM:
  1134. ParseOpcode(full_opcode, "MVCAM", new FieldCameraInstruction(), 0, "B");
  1135. break;
  1136. // AV
  1137. case OPCODES::BGMOVIE:
  1138. ParseOpcode(full_opcode, "BGMOVIE", new FieldMediaInstruction(), 0, "B");
  1139. break;
  1140. case OPCODES::AKAO2:
  1141. ParseOpcode(full_opcode, "AKAO2", new FieldMediaInstruction(), 0, "NNNBwwwww");
  1142. break;
  1143. case OPCODES::MUSIC:
  1144. ParseOpcode(full_opcode, "MUSIC", new FieldMediaInstruction(), 0, "B");
  1145. break;
  1146. case OPCODES::SOUND:
  1147. ParseOpcode(full_opcode, "SOUND", new FieldMediaInstruction(), 0, "NwB");
  1148. break;
  1149. case OPCODES::AKAO:
  1150. ParseOpcode(full_opcode, "AKAO", new FieldMediaInstruction(), 0, "NNNBBwwww");
  1151. break;
  1152. case OPCODES::MUSVT:
  1153. ParseOpcode(full_opcode, "MUSVT", new FieldMediaInstruction(), 0, "B");
  1154. break;
  1155. case OPCODES::MUSVM:
  1156. ParseOpcode(full_opcode, "MUSVM", new FieldMediaInstruction(), 0, "B");
  1157. break;
  1158. case OPCODES::MULCK:
  1159. ParseOpcode(full_opcode, "MULCK", new FieldMediaInstruction(), 0, "B");
  1160. break;
  1161. case OPCODES::BMUSC:
  1162. ParseOpcode(full_opcode, "BMUSC", new FieldMediaInstruction(), 0, "B");
  1163. break;
  1164. case OPCODES::CHMPH:
  1165. ParseOpcode(full_opcode, "CHMPH", new FieldMediaInstruction(), 0, "BBB");
  1166. break;
  1167. case OPCODES::PMVIE:
  1168. ParseOpcode(full_opcode, "PMVIE", new FieldMediaInstruction(), 0, "B");
  1169. break;
  1170. case OPCODES::MOVIE:
  1171. ParseOpcode(full_opcode, "MOVIE", new FieldMediaInstruction(), 0, "");
  1172. break;
  1173. case OPCODES::MVIEF:
  1174. ParseOpcode(full_opcode, "MVIEF", new FieldMediaInstruction(), 0, "NB");
  1175. break;
  1176. case OPCODES::FMUSC:
  1177. ParseOpcode(full_opcode, "FMUSC", new FieldMediaInstruction(), 0, "B");
  1178. break;
  1179. case OPCODES::CMUSC:
  1180. ParseOpcode(full_opcode, "CMUSC", new FieldMediaInstruction(), 0, "BBBBBBB");
  1181. break;
  1182. case OPCODES::CHMST:
  1183. ParseOpcode(full_opcode, "CHMST", new FieldMediaInstruction(), 0, "NB");
  1184. break;
  1185. // Uncat
  1186. case OPCODES::MPDSP:
  1187. ParseOpcode(full_opcode, "MPDSP", new FieldUncategorizedInstruction(), 0, "B");
  1188. break;
  1189. case OPCODES::SETX:
  1190. ParseOpcode(full_opcode, "SETX", new FieldUncategorizedInstruction(), 0, "BBBBBB");
  1191. break;
  1192. case OPCODES::GETX:
  1193. ParseOpcode(full_opcode, "GETX", new FieldUncategorizedInstruction(), 0, "BBBBBB");
  1194. break;
  1195. case OPCODES::SEARCHX:
  1196. ParseOpcode(full_opcode, "SEARCHX", new FieldUncategorizedInstruction(), 0, "BBBBBBBBBB");
  1197. break;
  1198. default:
  1199. throw UnknownOpcodeException(this->address_, opcode);
  1200. }
  1201. this->address_++;
  1202. // Is it within an "if" statement tracking?
  1203. InstPtr i = this->insts_.back();
  1204. if (i->IsCondJump()) exitAddrs.push_back(i->GetDestAddress());
  1205. if (!exitAddrs.empty())
  1206. if (i->GetAddress() == exitAddrs.back()) exitAddrs.pop_back();
  1207. // Only bail if its the first RET that isn't within an "if" block.
  1208. if (full_opcode == OPCODES::RET && exitAddrs.empty()) return is_line;
  1209. }
  1210. return is_line;
  1211. }