FieldDisassembler.cpp 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243
  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 FF7::FieldDisassembler::MAGIC(0x0502);
  39. const int FF7::FieldDisassembler::NUM_SECTIONS(7);
  40. FF7::FieldDisassembler::FieldDisassembler(
  41. SUDM::IScriptFormatter& 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. FF7::FieldDisassembler::FieldDisassembler(
  52. SUDM::IScriptFormatter& formatter, FieldEngine *engine, InstVec &insts
  53. ): Disassembler(insts), engine_(engine), formatter_(formatter){
  54. section_pointers_size_ = (sizeof(uint32) * NUM_SECTIONS);
  55. }
  56. float FF7::FieldDisassembler::GetScaleFactor() const{return scale_factor_;}
  57. FF7::FieldDisassembler::~FieldDisassembler(){}
  58. void FF7::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 FF7::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 FF7::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> FF7::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 FF7::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_.EntityName(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 FF7::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() == FF7::OPCODES::opCodeCHAR)
  151. return instruction->GetParam(0)->getSigned();
  152. }
  153. }
  154. return -1;
  155. }
  156. void FF7::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 FF7::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. FF7::FieldDisassembler::InstructionRecord FF7::FieldDisassembler::FLOW_OPCODES[] ={
  279. {1, FF7::OPCODES::RET, "RET", "", FF7::FF7ControlFlowInstruction::Create},
  280. {1, FF7::OPCODES::REQ, "REQ", "BU", FF7::FF7ControlFlowInstruction::Create},
  281. {1, FF7::OPCODES::REQSW, "REQSW", "BU", FF7::FF7ControlFlowInstruction::Create},
  282. {1, FF7::OPCODES::REQEW, "REQEW", "BU", FF7::FF7ControlFlowInstruction::Create},
  283. {1, FF7::OPCODES::NOP, "NOP", "", FF7::FieldNoOperationInstruction::Create},
  284. {1, FF7::OPCODES::IFUB, "IFUB", "NNBBBL", FF7::FieldNoOperationInstruction::Create}
  285. };
  286. std::map<std::string, const FF7::FieldDisassembler::InstructionRecord*>
  287. FF7::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 FF7::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 FF7ControlFlowInstruction(), 0, "");
  310. break;
  311. case OPCODES::REQ:
  312. ParseOpcode(full_opcode, "REQ", new FF7ControlFlowInstruction(), 0, "BU");
  313. break;
  314. case OPCODES::REQSW:
  315. ParseOpcode(full_opcode, "REQSW", new FF7ControlFlowInstruction(), 0, "BU");
  316. break;
  317. case OPCODES::REQEW:
  318. ParseOpcode(full_opcode, "REQEW", new FF7ControlFlowInstruction(), 0, "BU");
  319. break;
  320. case OPCODES::PREQ:
  321. ParseOpcode(full_opcode, "PREQ", new FF7ControlFlowInstruction(), 0, "BU");
  322. break;
  323. case OPCODES::PRQSW:
  324. ParseOpcode(full_opcode, "PRQSW", new FF7ControlFlowInstruction(), 0, "BU");
  325. break;
  326. case OPCODES::PRQEW:
  327. ParseOpcode(full_opcode, "PRQEW", new FF7ControlFlowInstruction(), 0, "BU");
  328. break;
  329. case OPCODES::RETTO:
  330. ParseOpcode(full_opcode, "RETTO", new FF7ControlFlowInstruction(), 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 FF7ControlFlowInstruction(), 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. ParseOpcode(full_opcode, "GOLDU", new FieldPartyInstruction(), 0, "Nww");
  660. break;
  661. case OPCODES::GOLDD:
  662. ParseOpcode(full_opcode, "GOLDD", new FieldPartyInstruction(), 0, "Nww");
  663. break;
  664. case OPCODES::CHGLD:
  665. ParseOpcode(full_opcode, "CHGLD", new FieldPartyInstruction(), 0, "NBB");
  666. break;
  667. case OPCODES::HMPMAX1:
  668. ParseOpcode(full_opcode, "HMPMAX1", new FieldPartyInstruction(), 0, "");
  669. break;
  670. case OPCODES::HMPMAX2:
  671. ParseOpcode(full_opcode, "HMPMAX2", new FieldPartyInstruction(), 0, "");
  672. break;
  673. case OPCODES::MHMMX:
  674. ParseOpcode(full_opcode, "MHMMX", new FieldPartyInstruction(), 0, "");
  675. break;
  676. case OPCODES::HMPMAX3:
  677. ParseOpcode(full_opcode, "HMPMAX3", new FieldPartyInstruction(), 0, "");
  678. break;
  679. case OPCODES::MPU:
  680. ParseOpcode(full_opcode, "MPU", new FieldPartyInstruction(), 0, "NBw");
  681. break;
  682. case OPCODES::MPD:
  683. ParseOpcode(full_opcode, "MPD", new FieldPartyInstruction(), 0, "NBw");
  684. break;
  685. case OPCODES::HPU:
  686. ParseOpcode(full_opcode, "HPU", new FieldPartyInstruction(), 0, "NBw");
  687. break;
  688. case OPCODES::HPD:
  689. ParseOpcode(full_opcode, "HPD", new FieldPartyInstruction(), 0, "NBw");
  690. break;
  691. case OPCODES::STITM:
  692. ParseOpcode(full_opcode, "STITM", new FieldPartyInstruction(), 0, "NwB");
  693. break;
  694. case OPCODES::DLITM:
  695. ParseOpcode(full_opcode, "DLITM", new FieldPartyInstruction(), 0, "NwB");
  696. break;
  697. case OPCODES::CKITM:
  698. ParseOpcode(full_opcode, "CKITM", new FieldPartyInstruction(), 0, "NwB");
  699. break;
  700. case OPCODES::SMTRA:
  701. ParseOpcode(full_opcode, "SMTRA", new FieldPartyInstruction(), 0, "NNBBBB");
  702. break;
  703. case OPCODES::DMTRA:
  704. ParseOpcode(full_opcode, "DMTRA", new FieldPartyInstruction(), 0, "NNBBBBB");
  705. break;
  706. case OPCODES::CMTRA:
  707. ParseOpcode(full_opcode, "CMTRA", new FieldPartyInstruction(), 0, "NNNBBBBBB");
  708. break;
  709. case OPCODES::GETPC:
  710. ParseOpcode(full_opcode, "GETPC", new FieldPartyInstruction(), 0, "NBB");
  711. break;
  712. case OPCODES::PRTYP:
  713. ParseOpcode(full_opcode, "PRTYP", new FieldPartyInstruction(), 0, "B");
  714. break;
  715. case OPCODES::PRTYM:
  716. ParseOpcode(full_opcode, "PRTYM", new FieldPartyInstruction(), 0, "B");
  717. break;
  718. case OPCODES::PRTYE:
  719. ParseOpcode(full_opcode, "PRTYE", new FieldPartyInstruction(), 0, "BBB");
  720. break;
  721. case OPCODES::MMBUD:
  722. ParseOpcode(full_opcode, "MMBUD", new FieldPartyInstruction(), 0, "BB");
  723. break;
  724. case OPCODES::MMBLK:
  725. ParseOpcode(full_opcode, "MMBLK", new FieldPartyInstruction(), 0, "B");
  726. break;
  727. case OPCODES::MMBUK:
  728. ParseOpcode(full_opcode, "MMBUK", new FieldPartyInstruction(), 0, "B");
  729. break;
  730. // Model
  731. case OPCODES::JOIN:
  732. ParseOpcode(full_opcode, "JOIN", new FieldModelInstruction(), 0, "B");
  733. break;
  734. case OPCODES::SPLIT:
  735. ParseOpcode(full_opcode, "SPLIT", new FieldModelInstruction(), 0, "NNNssBssBB");
  736. break;
  737. case OPCODES::BLINK:
  738. ParseOpcode(full_opcode, "BLINK", new FieldModelInstruction(), 0, "B");
  739. break;
  740. case OPCODES::KAWAI:
  741. {
  742. full_opcode = 0;
  743. full_opcode = (full_opcode << 8) + OPCODES::KAWAI;
  744. int length = this->stream_->ReadU8();
  745. assert(length >= 3);
  746. std::ostringstream param_stream;
  747. for (int i = 3; i < length; ++ i) param_stream << "B";
  748. auto parameters = param_stream.str();
  749. opcode = this->stream_->ReadU8();
  750. switch (opcode){
  751. case OPCODES_KAWAI::EYETX:
  752. // Parameters were "BBBB"
  753. ParseOpcode(
  754. opcode, "EYETX", new FieldModelInstruction(), 0, parameters.c_str()
  755. );
  756. break;
  757. case OPCODES_KAWAI::TRNSP:
  758. // Parameters were "B"
  759. ParseOpcode(
  760. opcode, "TRNSP", new FieldModelInstruction(), 0, parameters.c_str()
  761. );
  762. break;
  763. case OPCODES_KAWAI::AMBNT:
  764. // Parameters were "AMBNT"
  765. ParseOpcode(
  766. opcode, "AMBNT",
  767. new FieldModelInstruction(), 0, parameters.c_str()
  768. );
  769. break;
  770. case OPCODES_KAWAI::Unknown03:
  771. ParseOpcode(
  772. opcode, "Unknown03",
  773. new FieldModelInstruction(), 0, parameters.c_str()
  774. );
  775. break;
  776. case OPCODES_KAWAI::Unknown04:
  777. ParseOpcode(
  778. opcode, "Unknown04",
  779. new FieldModelInstruction(), 0, parameters.c_str()
  780. );
  781. break;
  782. case OPCODES_KAWAI::Unknown05:
  783. ParseOpcode(
  784. opcode, "Unknown03",
  785. new FieldModelInstruction(), 0, parameters.c_str()
  786. );
  787. break;
  788. case OPCODES_KAWAI::LIGHT:
  789. ParseOpcode(
  790. opcode, "LIGHT",
  791. new FieldModelInstruction(), 0, parameters.c_str()
  792. );
  793. break;
  794. case OPCODES_KAWAI::Unknown07:
  795. ParseOpcode(
  796. opcode, "Unknown07",
  797. new FieldModelInstruction(), 0, parameters.c_str()
  798. );
  799. break;
  800. case OPCODES_KAWAI::Unknown08:
  801. ParseOpcode(
  802. opcode, "Unknown08",
  803. new FieldModelInstruction(), 0, parameters.c_str()
  804. );
  805. break;
  806. case OPCODES_KAWAI::Unknown09:
  807. ParseOpcode(
  808. opcode, "Unknown09",
  809. new FieldModelInstruction(), 0, parameters.c_str()
  810. );
  811. break;
  812. case OPCODES_KAWAI::SBOBJ:
  813. ParseOpcode(
  814. opcode, "SBOBJ", new FieldModelInstruction(), 0, parameters.c_str()
  815. );
  816. break;
  817. case OPCODES_KAWAI::Unknown0B:
  818. ParseOpcode(
  819. opcode, "Unknown0B",
  820. new FieldModelInstruction(), 0, parameters.c_str()
  821. );
  822. break;
  823. case OPCODES_KAWAI::Unknown0C:
  824. ParseOpcode(
  825. opcode, "Unknown0C", new FieldModelInstruction(), 0, parameters.c_str()
  826. );
  827. break;
  828. case OPCODES_KAWAI::SHINE:
  829. ParseOpcode(
  830. opcode, "SHINE", new FieldModelInstruction(), 0, parameters.c_str()
  831. );
  832. break;
  833. case OPCODES_KAWAI::RESET:
  834. ParseOpcode(
  835. opcode, "RESET", new FieldModelInstruction(), 0, parameters.c_str()
  836. );
  837. break;
  838. default:
  839. throw UnknownSubOpcodeException(this->address_, opcode);
  840. }
  841. this->address_ ++;
  842. this->address_ ++;
  843. break;
  844. }
  845. case OPCODES::KAWIW:
  846. ParseOpcode(full_opcode, "KAWIW", new FieldModelInstruction(), 0, "");
  847. break;
  848. case OPCODES::PMOVA:
  849. ParseOpcode(full_opcode, "PMOVA", new FieldModelInstruction(), 0, "B");
  850. break;
  851. case OPCODES::PDIRA:
  852. ParseOpcode(full_opcode, "PDIRA", new FieldModelInstruction(), 0, "B");
  853. break;
  854. case OPCODES::PTURA:
  855. ParseOpcode(full_opcode, "PTURA", new FieldModelInstruction(), 0, "BBB");
  856. break;
  857. case OPCODES::PGTDR:
  858. ParseOpcode(full_opcode, "PGTDR", new FieldModelInstruction(), 0, "NBB");
  859. break;
  860. case OPCODES::PXYZI:
  861. ParseOpcode(full_opcode, "PXYZI", new FieldModelInstruction(), 0, "NNBBBBB");
  862. break;
  863. case OPCODES::TLKON:
  864. ParseOpcode(full_opcode, "TLKON", new FieldModelInstruction(), 0, "B");
  865. break;
  866. case OPCODES::PC:
  867. ParseOpcode(full_opcode, "PC", new FieldModelInstruction(), 0, "B");
  868. break;
  869. case OPCODES::opCodeCHAR:
  870. ParseOpcode(full_opcode, "CHAR", new FieldModelInstruction(), 0, "B");
  871. break;
  872. case OPCODES::DFANM:
  873. ParseOpcode(full_opcode, "DFANM", new FieldModelInstruction(), 0, "BB");
  874. break;
  875. case OPCODES::ANIME1:
  876. ParseOpcode(full_opcode, "ANIME1", new FieldModelInstruction(), 0, "BB");
  877. break;
  878. case OPCODES::VISI:
  879. ParseOpcode(full_opcode, "VISI", new FieldModelInstruction(), 0, "B");
  880. break;
  881. case OPCODES::XYZI:
  882. ParseOpcode(full_opcode, "XYZI", new FieldModelInstruction(), 0, "NNsssw");
  883. break;
  884. case OPCODES::XYI:
  885. ParseOpcode(full_opcode, "XYI", new FieldModelInstruction(), 0, "NNssw");
  886. break;
  887. case OPCODES::XYZ:
  888. ParseOpcode(full_opcode, "XYZ", new FieldModelInstruction(), 0, "NNsss");
  889. break;
  890. case OPCODES::MOVE:
  891. ParseOpcode(full_opcode, "MOVE", new FieldModelInstruction(), 0, "Nss");
  892. break;
  893. case OPCODES::CMOVE:
  894. ParseOpcode(full_opcode, "CMOVE", new FieldModelInstruction(), 0, "Nss");
  895. break;
  896. case OPCODES::MOVA:
  897. ParseOpcode(full_opcode, "MOVA", new FieldModelInstruction(), 0, "B");
  898. break;
  899. case OPCODES::TURA:
  900. ParseOpcode(full_opcode, "TURA", new FieldModelInstruction(), 0, "BBB");
  901. break;
  902. case OPCODES::ANIMW:
  903. ParseOpcode(full_opcode, "ANIMW", new FieldModelInstruction(), 0, "");
  904. break;
  905. case OPCODES::FMOVE:
  906. ParseOpcode(full_opcode, "FMOVE", new FieldModelInstruction(), 0, "Nss");
  907. break;
  908. case OPCODES::ANIME2:
  909. ParseOpcode(full_opcode, "ANIME2", new FieldModelInstruction(), 0, "BB");
  910. break;
  911. case OPCODES::ANIM_1:
  912. ParseOpcode(full_opcode, "ANIM!1", new FieldModelInstruction(), 0, "BB");
  913. break;
  914. case OPCODES::CANIM1:
  915. ParseOpcode(full_opcode, "CANIM1", new FieldModelInstruction(), 0, "BBBB");
  916. break;
  917. case OPCODES::CANM_1:
  918. ParseOpcode(full_opcode, "CANM!1", new FieldModelInstruction(), 0, "BBBB");
  919. break;
  920. case OPCODES::MSPED:
  921. ParseOpcode(full_opcode, "MSPED", new FieldModelInstruction(), 0, "Nw");
  922. break;
  923. case OPCODES::DIR:
  924. ParseOpcode(full_opcode, "DIR", new FieldModelInstruction(), 0, "BB");
  925. break;
  926. case OPCODES::TURNGEN:
  927. ParseOpcode(full_opcode, "TURNGEN", new FieldModelInstruction(), 0, "NBBBB");
  928. break;
  929. case OPCODES::TURN:
  930. ParseOpcode(full_opcode, "TURN", new FieldModelInstruction(), 0, "NBBBB");
  931. break;
  932. case OPCODES::DIRA:
  933. ParseOpcode(full_opcode, "DIRA", new FieldModelInstruction(), 0, "B");
  934. break;
  935. case OPCODES::GETDIR:
  936. ParseOpcode(full_opcode, "GETDIR", new FieldModelInstruction(), 0, "NBB");
  937. break;
  938. case OPCODES::GETAXY:
  939. ParseOpcode(full_opcode, "GETAXY", new FieldModelInstruction(), 0, "NBBB");
  940. break;
  941. case OPCODES::GETAI:
  942. ParseOpcode(full_opcode, "GETAI", new FieldModelInstruction(), 0, "NBB");
  943. break;
  944. case OPCODES::ANIM_2:
  945. ParseOpcode(full_opcode, "ANIM!2", new FieldModelInstruction(), 0, "BB");
  946. break;
  947. case OPCODES::CANIM2:
  948. ParseOpcode(full_opcode, "CANIM2", new FieldModelInstruction(), 0, "BBBB");
  949. break;
  950. case OPCODES::CANM_2:
  951. ParseOpcode(full_opcode, "CANM!2", new FieldModelInstruction(), 0, "BBBB");
  952. break;
  953. case OPCODES::ASPED:
  954. ParseOpcode(full_opcode, "ASPED", new FieldModelInstruction(), 0, "Nw");
  955. break;
  956. case OPCODES::CC:
  957. ParseOpcode(full_opcode, "CC", new FieldModelInstruction(), 0, "B");
  958. break;
  959. case OPCODES::JUMP:
  960. ParseOpcode(full_opcode, "JUMP", new FieldModelInstruction(), 0, "NNssww");
  961. break;
  962. case OPCODES::AXYZI:
  963. ParseOpcode(full_opcode, "AXYZI", new FieldModelInstruction(), 0, "NNBBBBB");
  964. break;
  965. case OPCODES::LADER:
  966. ParseOpcode(full_opcode, "LADER", new FieldModelInstruction(), 0, "NNssswBBBB");
  967. break;
  968. case OPCODES::OFST:
  969. ParseOpcode(full_opcode, "OFST", new FieldModelInstruction(), 0, "NNBsssw");
  970. break;
  971. case OPCODES::OFSTW:
  972. ParseOpcode(full_opcode, "OFSTW", new FieldModelInstruction(), 0, "");
  973. break;
  974. case OPCODES::TALKR:
  975. ParseOpcode(full_opcode, "TALKR", new FieldModelInstruction(), 0, "NB");
  976. break;
  977. case OPCODES::SLIDR:
  978. ParseOpcode(full_opcode, "SLIDR", new FieldModelInstruction(), 0, "NB");
  979. break;
  980. case OPCODES::SOLID:
  981. ParseOpcode(full_opcode, "SOLID", new FieldModelInstruction(), 0, "B");
  982. break;
  983. case OPCODES::TLKR2:
  984. ParseOpcode(full_opcode, "TLKR2", new FieldModelInstruction(), 0, "Nw");
  985. break;
  986. case OPCODES::SLDR2:
  987. ParseOpcode(full_opcode, "SLDR2", new FieldModelInstruction(), 0, "Nw");
  988. break;
  989. case OPCODES::CCANM:
  990. ParseOpcode(full_opcode, "CCANM", new FieldModelInstruction(), 0, "BBB");
  991. break;
  992. case OPCODES::FCFIX:
  993. ParseOpcode(full_opcode, "FCFIX", new FieldModelInstruction(), 0, "B");
  994. break;
  995. case OPCODES::ANIMB:
  996. ParseOpcode(full_opcode, "ANIMB", new FieldModelInstruction(), 0, "");
  997. break;
  998. case OPCODES::TURNW:
  999. ParseOpcode(full_opcode, "TURNW", new FieldModelInstruction(), 0, "");
  1000. break;
  1001. // Walkmesh
  1002. case OPCODES::SLIP:
  1003. ParseOpcode(full_opcode, "SLIP", new FieldWalkmeshInstruction(), 0, "B");
  1004. break;
  1005. case OPCODES::UC:
  1006. ParseOpcode(full_opcode, "UC", new FieldWalkmeshInstruction(), 0, "B");
  1007. break;
  1008. case OPCODES::IDLCK:
  1009. ParseOpcode(full_opcode, "IDLCK", new FieldWalkmeshInstruction(), 0, "wB");
  1010. break;
  1011. case OPCODES::LINON:
  1012. ParseOpcode(full_opcode, "LINON", new FieldWalkmeshInstruction(), 0, "B");
  1013. break;
  1014. case OPCODES::SLINE:
  1015. ParseOpcode(full_opcode, "SLINE", new FieldWalkmeshInstruction(), 0, "NNNssssss");
  1016. break;
  1017. case OPCODES::LINE:
  1018. // Mark function entity owner as line.
  1019. is_line = true;
  1020. ParseOpcode(full_opcode, "LINE", new FieldWalkmeshInstruction(), 0, "ssssss");
  1021. point_a[0] = this->insts_.back()->GetParam(0)->getSigned();
  1022. point_a[1] = this->insts_.back()->GetParam(1)->getSigned();
  1023. point_a[2] = this->insts_.back()->GetParam(2)->getSigned();
  1024. point_b[0] = this->insts_.back()->GetParam(3)->getSigned();
  1025. point_b[1] = this->insts_.back()->GetParam(4)->getSigned();
  1026. point_b[2] = this->insts_.back()->GetParam(5)->getSigned();
  1027. break;
  1028. // Backgnd
  1029. case OPCODES::BGPDH:
  1030. ParseOpcode(full_opcode, "BGPDH", new FieldBackgroundInstruction(), 0, "NBs");
  1031. break;
  1032. case OPCODES::BGSCR:
  1033. ParseOpcode(full_opcode, "BGSCR", new FieldBackgroundInstruction(), 0, "NBss");
  1034. break;
  1035. case OPCODES::MPPAL:
  1036. ParseOpcode(full_opcode, "MPPAL", new FieldBackgroundInstruction(), 0, "NNNBBBBBBB");
  1037. break;
  1038. case OPCODES::BGON:
  1039. ParseOpcode(full_opcode, "BGON", new FieldBackgroundInstruction(), 0, "NBB");
  1040. break;
  1041. case OPCODES::BGOFF:
  1042. ParseOpcode(full_opcode, "BGOFF", new FieldBackgroundInstruction(), 0, "NBB");
  1043. break;
  1044. case OPCODES::BGROL:
  1045. ParseOpcode(full_opcode, "BGROL", new FieldBackgroundInstruction(), 0, "NB");
  1046. break;
  1047. case OPCODES::BGROL2:
  1048. ParseOpcode(full_opcode, "BGROL2", new FieldBackgroundInstruction(), 0, "NB");
  1049. break;
  1050. case OPCODES::BGCLR:
  1051. ParseOpcode(full_opcode, "BGCLR", new FieldBackgroundInstruction(), 0, "NB");
  1052. break;
  1053. case OPCODES::STPAL:
  1054. ParseOpcode(full_opcode, "STPAL", new FieldBackgroundInstruction(), 0, "NBBB");
  1055. break;
  1056. case OPCODES::LDPAL:
  1057. ParseOpcode(full_opcode, "LDPAL", new FieldBackgroundInstruction(), 0, "NBBB");
  1058. break;
  1059. case OPCODES::CPPAL:
  1060. ParseOpcode(full_opcode, "CPPAL", new FieldBackgroundInstruction(), 0, "NBBB");
  1061. break;
  1062. case OPCODES::RTPAL:
  1063. ParseOpcode(full_opcode, "RTPAL", new FieldBackgroundInstruction(), 0, "NNBBBB");
  1064. break;
  1065. case OPCODES::ADPAL:
  1066. ParseOpcode(full_opcode, "ADPAL", new FieldBackgroundInstruction(), 0, "NNNBBBBBB");
  1067. break;
  1068. case OPCODES::MPPAL2:
  1069. ParseOpcode(
  1070. full_opcode, "MPPAL2", new FieldBackgroundInstruction(), 0, "NNNBBBBBB"
  1071. );
  1072. break;
  1073. case OPCODES::STPLS:
  1074. ParseOpcode(full_opcode, "STPLS", new FieldBackgroundInstruction(), 0, "BBBB");
  1075. break;
  1076. case OPCODES::LDPLS:
  1077. ParseOpcode(full_opcode, "LDPLS", new FieldBackgroundInstruction(), 0, "BBBB");
  1078. break;
  1079. case OPCODES::CPPAL2:
  1080. ParseOpcode(full_opcode, "CPPAL2", new FieldBackgroundInstruction(), 0, "BBBBBBB");
  1081. break;
  1082. case OPCODES::RTPAL2:
  1083. ParseOpcode(full_opcode, "RTPAL2", new FieldBackgroundInstruction(), 0, "BBBBBBB");
  1084. break;
  1085. case OPCODES::ADPAL2:
  1086. ParseOpcode(full_opcode, "ADPAL2", new FieldBackgroundInstruction(), 0, "BBBBBBBBBB");
  1087. break;
  1088. // Camera
  1089. case OPCODES::NFADE:
  1090. ParseOpcode(full_opcode, "NFADE", new FieldCameraInstruction(), 0, "NNBBBBBB");
  1091. break;
  1092. case OPCODES::SHAKE:
  1093. ParseOpcode(full_opcode, "SHAKE", new FieldCameraInstruction(), 0, "BBBBBBB");
  1094. break;
  1095. case OPCODES::SCRLO:
  1096. ParseOpcode(full_opcode, "SCRLO", new FieldCameraInstruction(), 0, "B");
  1097. break;
  1098. case OPCODES::SCRLC:
  1099. ParseOpcode(full_opcode, "SCRLC", new FieldCameraInstruction(), 0, "BBBB");
  1100. break;
  1101. case OPCODES::SCRLA:
  1102. ParseOpcode(full_opcode, "SCRLA", new FieldCameraInstruction(), 0, "NwBB");
  1103. break;
  1104. case OPCODES::SCR2D:
  1105. ParseOpcode(full_opcode, "SCR2D", new FieldCameraInstruction(), 0, "Nss");
  1106. break;
  1107. case OPCODES::SCRCC:
  1108. ParseOpcode(full_opcode, "SCRCC", new FieldCameraInstruction(), 0, "");
  1109. break;
  1110. case OPCODES::SCR2DC:
  1111. ParseOpcode(full_opcode, "SCR2DC", new FieldCameraInstruction(), 0, "NNssw");
  1112. break;
  1113. case OPCODES::SCRLW:
  1114. ParseOpcode(full_opcode, "SCRLW", new FieldCameraInstruction(), 0, "");
  1115. break;
  1116. case OPCODES::SCR2DL:
  1117. ParseOpcode(full_opcode, "SCR2DL", new FieldCameraInstruction(), 0, "NNssw");
  1118. break;
  1119. case OPCODES::VWOFT:
  1120. ParseOpcode(full_opcode, "VWOFT", new FieldCameraInstruction(), 0, "NssB");
  1121. break;
  1122. case OPCODES::FADE:
  1123. ParseOpcode(full_opcode, "FADE", new FieldCameraInstruction(), 0, "NNBBBBBB");
  1124. break;
  1125. case OPCODES::FADEW:
  1126. ParseOpcode(full_opcode, "FADEW", new FieldCameraInstruction(), 0, "");
  1127. break;
  1128. case OPCODES::SCRLP:
  1129. ParseOpcode(full_opcode, "SCRLP", new FieldCameraInstruction(), 0, "NwBB");
  1130. break;
  1131. case OPCODES::MVCAM:
  1132. ParseOpcode(full_opcode, "MVCAM", new FieldCameraInstruction(), 0, "B");
  1133. break;
  1134. // AV
  1135. case OPCODES::BGMOVIE:
  1136. ParseOpcode(full_opcode, "BGMOVIE", new FieldMediaInstruction(), 0, "B");
  1137. break;
  1138. case OPCODES::AKAO2:
  1139. ParseOpcode(full_opcode, "AKAO2", new FieldMediaInstruction(), 0, "NNNBwwwww");
  1140. break;
  1141. case OPCODES::MUSIC:
  1142. ParseOpcode(full_opcode, "MUSIC", new FieldMediaInstruction(), 0, "B");
  1143. break;
  1144. case OPCODES::SOUND:
  1145. ParseOpcode(full_opcode, "SOUND", new FieldMediaInstruction(), 0, "NwB");
  1146. break;
  1147. case OPCODES::AKAO:
  1148. ParseOpcode(full_opcode, "AKAO", new FieldMediaInstruction(), 0, "NNNBBwwww");
  1149. break;
  1150. case OPCODES::MUSVT:
  1151. ParseOpcode(full_opcode, "MUSVT", new FieldMediaInstruction(), 0, "B");
  1152. break;
  1153. case OPCODES::MUSVM:
  1154. ParseOpcode(full_opcode, "MUSVM", new FieldMediaInstruction(), 0, "B");
  1155. break;
  1156. case OPCODES::MULCK:
  1157. ParseOpcode(full_opcode, "MULCK", new FieldMediaInstruction(), 0, "B");
  1158. break;
  1159. case OPCODES::BMUSC:
  1160. ParseOpcode(full_opcode, "BMUSC", new FieldMediaInstruction(), 0, "B");
  1161. break;
  1162. case OPCODES::CHMPH:
  1163. ParseOpcode(full_opcode, "CHMPH", new FieldMediaInstruction(), 0, "BBB");
  1164. break;
  1165. case OPCODES::PMVIE:
  1166. ParseOpcode(full_opcode, "PMVIE", new FieldMediaInstruction(), 0, "B");
  1167. break;
  1168. case OPCODES::MOVIE:
  1169. ParseOpcode(full_opcode, "MOVIE", new FieldMediaInstruction(), 0, "");
  1170. break;
  1171. case OPCODES::MVIEF:
  1172. ParseOpcode(full_opcode, "MVIEF", new FieldMediaInstruction(), 0, "NB");
  1173. break;
  1174. case OPCODES::FMUSC:
  1175. ParseOpcode(full_opcode, "FMUSC", new FieldMediaInstruction(), 0, "B");
  1176. break;
  1177. case OPCODES::CMUSC:
  1178. ParseOpcode(full_opcode, "CMUSC", new FieldMediaInstruction(), 0, "BBBBBBB");
  1179. break;
  1180. case OPCODES::CHMST:
  1181. ParseOpcode(full_opcode, "CHMST", new FieldMediaInstruction(), 0, "NB");
  1182. break;
  1183. // Uncat
  1184. case OPCODES::MPDSP:
  1185. ParseOpcode(full_opcode, "MPDSP", new FieldUncategorizedInstruction(), 0, "B");
  1186. break;
  1187. case OPCODES::SETX:
  1188. ParseOpcode(full_opcode, "SETX", new FieldUncategorizedInstruction(), 0, "BBBBBB");
  1189. break;
  1190. case OPCODES::GETX:
  1191. ParseOpcode(full_opcode, "GETX", new FieldUncategorizedInstruction(), 0, "BBBBBB");
  1192. break;
  1193. case OPCODES::SEARCHX:
  1194. ParseOpcode(full_opcode, "SEARCHX", new FieldUncategorizedInstruction(), 0, "BBBBBBBBBB");
  1195. break;
  1196. default:
  1197. throw UnknownOpcodeException(this->address_, opcode);
  1198. }
  1199. this->address_++;
  1200. // Is it within an "if" statement tracking?
  1201. InstPtr i = this->insts_.back();
  1202. if (i->IsCondJump()) exitAddrs.push_back(i->GetDestAddress());
  1203. if (!exitAddrs.empty())
  1204. if (i->GetAddress() == exitAddrs.back()) exitAddrs.pop_back();
  1205. // Only bail if its the first RET that isn't within an "if" block.
  1206. if (full_opcode == OPCODES::RET && exitAddrs.empty()) return is_line;
  1207. }
  1208. return is_line;
  1209. }