ff7_field_disassembler.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. #pragma once
  2. #include "decompiler/simple_disassembler.h"
  3. #include "decompiler/sudm.h"
  4. #include <array>
  5. class BinaryReader;
  6. class Function;
  7. namespace FF7
  8. {
  9. enum eOpcodes
  10. {
  11. RET = 0x0,
  12. REQ = 0x01,
  13. REQSW = 0x02,
  14. REQEW = 0x03,
  15. PREQ = 0x04,
  16. PRQSW = 0x05,
  17. PRQEW = 0x06,
  18. RETTO = 0x07,
  19. JOIN = 0x08,
  20. SPLIT = 0x09,
  21. SPTYE = 0x0A,
  22. GTPYE = 0x0B,
  23. DSKCG = 0x0E,
  24. SPECIAL = 0x0F,
  25. JMPF = 0x10,
  26. JMPFL = 0x11,
  27. JMPB = 0x12,
  28. JMPBL = 0x13,
  29. IFUB = 0x14,
  30. IFUBL = 0x15,
  31. IFSW = 0x16,
  32. IFSWL = 0x17,
  33. IFUW = 0x18,
  34. IFUWL = 0x19,
  35. MINIGAME = 0x20,
  36. TUTOR = 0x21,
  37. BTMD2 = 0x22,
  38. BTRLD = 0x23,
  39. WAIT = 0x24,
  40. NFADE = 0x25,
  41. BLINK = 0x26,
  42. BGMOVIE = 0x27,
  43. KAWAI = 0x28,
  44. KAWIW = 0x29,
  45. PMOVA = 0x2A,
  46. SLIP = 0x2B,
  47. BGPDH = 0x2C,
  48. BGSCR = 0x2D,
  49. WCLS = 0x2E,
  50. WSIZW = 0x2F,
  51. IFKEY = 0x30,
  52. IFKEYON = 0x31,
  53. IFKEYOFF = 0x32,
  54. UC = 0x33,
  55. PDIRA = 0x34,
  56. PTURA = 0x35,
  57. WSPCL = 0x36,
  58. WNUMB = 0x37,
  59. STTIM = 0x38,
  60. GOLDU = 0x39,
  61. GOLDD = 0x3A,
  62. CHGLD = 0x3B,
  63. HMPMAX1 = 0x3C,
  64. HMPMAX2 = 0x3D,
  65. MHMMX = 0x3E,
  66. HMPMAX3 = 0x3F,
  67. MESSAGE = 0x40,
  68. MPARA = 0x41,
  69. MPRA2 = 0x42,
  70. MPNAM = 0x43,
  71. MPU = 0x45,
  72. MPD = 0x47,
  73. ASK = 0x48,
  74. MENU = 0x49,
  75. MENU2 = 0x4A,
  76. BTLTB = 0x4B,
  77. HPU = 0x4D,
  78. HPD = 0x4F,
  79. WINDOW = 0x50,
  80. WMOVE = 0x51,
  81. WMODE = 0x52,
  82. WREST = 0x53,
  83. WCLSE = 0x54,
  84. WROW = 0x55,
  85. GWCOL = 0x56,
  86. SWCOL = 0x57,
  87. STITM = 0x58,
  88. DLITM = 0x59,
  89. CKITM = 0x5A,
  90. SMTRA = 0x5B,
  91. DMTRA = 0x5C,
  92. CMTRA = 0x5D,
  93. SHAKE = 0x5E,
  94. NOP = 0x5F,
  95. MAPJUMP = 0x60,
  96. SCRLO = 0x61,
  97. SCRLC = 0x62,
  98. SCRLA = 0x63,
  99. SCR2D = 0x64,
  100. SCRCC = 0x65,
  101. SCR2DC = 0x66,
  102. SCRLW = 0x67,
  103. SCR2DL = 0x68,
  104. MPDSP = 0x69,
  105. VWOFT = 0x6A,
  106. FADE = 0x6B,
  107. FADEW = 0x6C,
  108. IDLCK = 0x6D,
  109. LSTMP = 0x6E,
  110. SCRLP = 0x6F,
  111. BATTLE = 0x70,
  112. BTLON = 0x71,
  113. BTLMD = 0x72,
  114. PGTDR = 0x73,
  115. GETPC = 0x74,
  116. PXYZI = 0x75,
  117. PLUS_ = 0x76, // PLUS!
  118. PLUS2_ = 0x77, // PLUS2!
  119. MINUS_ = 0x78, // MINUS!
  120. MINUS2_ = 0x79, // MINUS2!
  121. INC_ = 0x7A, // INC!
  122. INC2_ = 0x7B, // INC2!
  123. DEC_ = 0x7C, // DEC!
  124. DEC2_ = 0x7D, // DEC2!
  125. TLKON = 0x7E,
  126. RDMSD = 0x7F,
  127. SETBYTE = 0x80,
  128. SETWORD = 0x81,
  129. BITON = 0x82,
  130. BITOFF = 0x83,
  131. BITXOR = 0x84,
  132. PLUS = 0x85,
  133. PLUS2 = 0x86,
  134. MINUS = 0x87,
  135. MINUS2 = 0x88,
  136. MUL = 0x89,
  137. MUL2 = 0x8A,
  138. DIV = 0x8B,
  139. DIV2 = 0x8C,
  140. MOD = 0x8D,
  141. MOD2 = 0x8E,
  142. AND = 0x8F,
  143. AND2 = 0x90,
  144. OR = 0x91,
  145. OR2 = 0x92,
  146. XOR = 0x93,
  147. XOR2 = 0x94,
  148. INC = 0x95,
  149. INC2 = 0x96,
  150. DEC = 0x97,
  151. DEC2 = 0x98,
  152. RANDOM = 0x99,
  153. LBYTE = 0x9A,
  154. HBYTE = 0x9B,
  155. TWOBYTE = 0x9C,
  156. SETX = 0x9D,
  157. GETX = 0x9E,
  158. SEARCHX = 0x9F,
  159. PC = 0xA0,
  160. opCodeCHAR = 0xA1,
  161. DFANM = 0xA2,
  162. ANIME1 = 0xA3,
  163. VISI = 0xA4,
  164. XYZI = 0xA5,
  165. XYI = 0xA6,
  166. XYZ = 0xA7,
  167. MOVE = 0xA8,
  168. CMOVE = 0xA9,
  169. MOVA = 0xAA,
  170. TURA = 0xAB,
  171. ANIMW = 0xAC,
  172. FMOVE = 0xAD,
  173. ANIME2 = 0xAE,
  174. ANIM_1 = 0xAF, // ANIM!1
  175. CANIM1 = 0xB0,
  176. CANM_1 = 0xB1, // CANM!1
  177. MSPED = 0xB2,
  178. DIR = 0xB3,
  179. TURNGEN = 0xB4,
  180. TURN = 0xB5,
  181. DIRA = 0xB6,
  182. GETDIR = 0xB7,
  183. GETAXY = 0xB8,
  184. GETAI = 0xB9,
  185. ANIM_2 = 0xBA, // ANIM!2
  186. CANIM2 = 0xBB,
  187. CANM_2 = 0xBC, // CANM!2
  188. ASPED = 0xBD,
  189. CC = 0xBF,
  190. JUMP = 0xC0,
  191. AXYZI = 0xC1,
  192. LADER = 0xC2,
  193. OFST = 0xC3,
  194. OFSTW = 0xC4,
  195. TALKR = 0xC5,
  196. SLIDR = 0xC6,
  197. SOLID = 0xC7,
  198. PRTYP = 0xC8,
  199. PRTYM = 0xC9,
  200. PRTYE = 0xCA,
  201. IFPRTYQ = 0xCB,
  202. IFMEMBQ = 0xCC,
  203. MMBUD = 0xCD,
  204. MMBLK = 0xCE,
  205. MMBUK = 0xCF,
  206. LINE = 0xD0,
  207. LINON = 0xD1,
  208. MPJPO = 0xD2,
  209. SLINE = 0xD3,
  210. SIN = 0xD4,
  211. COS = 0xD5,
  212. TLKR2 = 0xD6,
  213. SLDR2 = 0xD7,
  214. PMJMP = 0xD8,
  215. PMJMP2 = 0xD9,
  216. AKAO2 = 0xDA,
  217. FCFIX = 0xDB,
  218. CCANM = 0xDC,
  219. ANIMB = 0xDD,
  220. TURNW = 0xDE,
  221. MPPAL = 0xDF,
  222. BGON = 0xE0,
  223. BGOFF = 0xE1,
  224. BGROL = 0xE2,
  225. BGROL2 = 0xE3,
  226. BGCLR = 0xE4,
  227. STPAL = 0xE5,
  228. LDPAL = 0xE6,
  229. CPPAL = 0xE7,
  230. RTPAL = 0xE8,
  231. ADPAL = 0xE9,
  232. MPPAL2 = 0xEA,
  233. STPLS = 0xEB,
  234. LDPLS = 0xEC,
  235. CPPAL2 = 0xED,
  236. RTPAL2 = 0xEE,
  237. ADPAL2 = 0xEF,
  238. MUSIC = 0xF0,
  239. SOUND = 0xF1,
  240. AKAO = 0xF2,
  241. MUSVT = 0xF3,
  242. MUSVM = 0xF4,
  243. MULCK = 0xF5,
  244. BMUSC = 0xF6,
  245. CHMPH = 0xF7,
  246. PMVIE = 0xF8,
  247. MOVIE = 0xF9,
  248. MVIEF = 0xFA,
  249. MVCAM = 0xFB,
  250. FMUSC = 0xFC,
  251. CMUSC = 0xFD,
  252. CHMST = 0xFE,
  253. GAMEOVER = 0xFF
  254. };
  255. enum eSpecialOpcodes
  256. {
  257. ARROW = 0xF5,
  258. PNAME = 0xF6,
  259. GMSPD = 0xF7,
  260. SMSPD = 0xF8,
  261. FLMAT = 0xF9,
  262. FLITM = 0xFA,
  263. BTLCK = 0xFB,
  264. MVLCK = 0xFC,
  265. SPCNM = 0xFD,
  266. RSGLB = 0xFE,
  267. CLITM = 0xFF
  268. };
  269. enum eKawaiOpcodes
  270. {
  271. EYETX = 0x00,
  272. TRNSP = 0x01,
  273. AMBNT = 0x02,
  274. Unknown03 = 0x03, // Makou Reactor can write these unknowns, so we'll include them for now
  275. Unknown04 = 0x04,
  276. Unknown05 = 0x05,
  277. LIGHT = 0x06,
  278. Unknown07 = 0x07,
  279. Unknown08 = 0x08,
  280. Unknown09 = 0x09,
  281. SBOBJ = 0x0A,
  282. Unknown0B = 0x0B,
  283. Unknown0C = 0x0C,
  284. SHINE = 0x0D,
  285. RESET = 0xFF
  286. };
  287. struct TInstructRecord
  288. {
  289. unsigned char mOpCodeSize;
  290. unsigned int mOpCode;
  291. const char* mMnemonic;
  292. const char* mArgumentFormat;
  293. std::function<InstPtr()> mFactoryFunc;
  294. };
  295. std::map<std::string, const TInstructRecord*> FieldInstructions();
  296. class FF7FieldEngine;
  297. class FF7Disassembler : public SimpleDisassembler
  298. {
  299. public:
  300. FF7Disassembler(SUDM::IScriptFormatter& formatter, FF7FieldEngine* engine, InstVec& insts);
  301. FF7Disassembler(SUDM::IScriptFormatter& formatter, FF7FieldEngine* engine, InstVec& insts, const std::vector<unsigned char>& rawScriptData);
  302. ~FF7Disassembler();
  303. private:
  304. // DO NOT USE - todo, remove from base
  305. virtual void open(const char *filename) override;
  306. public:
  307. virtual void doDisassemble() override;
  308. float ScaleFactor() const { return mScaleFactor; }
  309. private:
  310. void DisassembleIndivdualScript(std::string entityName,
  311. size_t entityIndex,
  312. size_t scriptEntryPoint,
  313. size_t scriptIndex,
  314. uint32 nextScriptEntryPoint,
  315. bool isStart,
  316. bool isEnd);
  317. /**
  318. * Adds a function to the engine.
  319. *
  320. * @param entity_name[in] Name of the entity that owns the function.
  321. * @param entity_index[in] Index of the entity that owns the function.
  322. * @param script_index[in] Index of the script within the entity.
  323. * @param next_script_entry_point[in] Start position of the next
  324. * script (or the ending position of this one, plus one).
  325. * @param is_start[in] @todo Understand and document.
  326. * @param is_end[in] @todo Understand and document.
  327. * @param to_return_only[in] True to read the script only until the
  328. * first return.
  329. * @param func_name[in] Name of the function. If the entity is a line,
  330. * the provided name will be overridden and set to the standard line
  331. * entity script names.
  332. */
  333. void AddFunc(
  334. std::string entity_name, size_t entity_index, size_t script_index,
  335. uint32 next_script_entry_point, const bool is_start, const bool is_end,
  336. bool to_return_only, std::string func_name
  337. );
  338. /**
  339. * Reads opcodes from a script, and detects lines.
  340. *
  341. * It stops when it reaches the ending position or a RET opcode,
  342. * whatever comes first. It also detects if one of the read opcodes
  343. * LINE, which means that the entity is a line
  344. *
  345. * @param end_pos[in] The last position to read. Opcodes will be read
  346. * until this, or until a RET is found.
  347. * @param point_a[out] If a LINE opcode is found, the first point will
  348. * be saved here.
  349. * @param point_b[out] If a LINE opcode is found, the second point
  350. * will be saved here.
  351. * @return True if LINE opcode found, false if not.
  352. */
  353. bool ReadOpCodesToPositionOrReturn(
  354. size_t end_pos, std::vector<float>& point_a, std::vector<float>& point_b
  355. );
  356. /**
  357. * Initializes a function for an entity.
  358. *
  359. * @param script_index[in] Index of the script.
  360. */
  361. std::unique_ptr<Function> StartFunction(size_t scriptIndex);
  362. FF7FieldEngine* mEngine;
  363. uint32 mHeaderEndPos = 0;
  364. void ReadHeader();
  365. void ReadHeader(BinaryReader& reader)
  366. {
  367. mHeader.Read(reader);
  368. mHeaderEndPos = reader.Position();
  369. }
  370. const static int kMagic = 0x0502;
  371. const static int kNumSections = 7;
  372. int16 kSectionPointersSize = sizeof(uint32) * kNumSections;
  373. enum eSections
  374. {
  375. eScript = 0,
  376. eWalkMesh = 1,
  377. eTileMap = 2,
  378. eCameraMatrix = 3,
  379. eTriggers = 4,
  380. eEncounter = 5,
  381. eModels = 6
  382. };
  383. std::array<uint32, 7> mSections;
  384. uint32 GetEndOfScriptOffset(uint16 curEntryPoint, size_t entityIndex, size_t scriptIndex);
  385. struct ScriptHeader
  386. {
  387. uint16 mMagic;
  388. uint8 mNumberOfEntities;
  389. uint8 mNumberOfModels;
  390. uint16 mOffsetToStrings;
  391. uint16 mNumberOfAkaoOffsets; // Specifies the number of Akao/tuto blocks/offsets
  392. uint16 mScale; // Scale of field. For move and talk calculation (9bit fixed point).
  393. std::array<uint16, 3> mBlank;
  394. std::array<char, 8> mCreator;// Field creator (never shown)
  395. std::array<char, 8> mName;// Field name (never shown)
  396. std::vector<std::array<char, 8>> mFieldEntityNames; // Count is mNumberOfEntities
  397. std::vector<uint32> mAkaoOffsets; // Akao/Tuto block offsets, count is mNumberOfAkaoOffsets
  398. // Entity script entry points, or more explicitly, subroutine offsets
  399. std::vector<std::array<uint16, 32>> mEntityScripts; // Count is mNumberOfEntities
  400. void Read(BinaryReader& r)
  401. {
  402. mMagic = r.ReadU16();
  403. if (mMagic != kMagic)
  404. {
  405. throw FF7ScriptHeaderInvalidException();
  406. }
  407. mNumberOfEntities = r.ReadU8();
  408. mNumberOfModels = r.ReadU8();
  409. mOffsetToStrings = r.ReadU16();
  410. mNumberOfAkaoOffsets = r.ReadU16();
  411. mScale = r.ReadU16();
  412. for (int i = 0; i < 3; i++)
  413. {
  414. mBlank[i] = r.ReadU16();
  415. }
  416. for (int i = 0; i < 8; i++)
  417. {
  418. mCreator[i] = r.ReadU8();
  419. }
  420. for (int i = 0; i < 8; i++)
  421. {
  422. mName[i] = r.ReadU8();
  423. }
  424. for (int i = 0; i < mNumberOfEntities; i++)
  425. {
  426. std::array<char, 8> name;
  427. for (int j = 0; j < 8; j++)
  428. {
  429. name[j] = r.ReadU8();
  430. }
  431. mFieldEntityNames.emplace_back(name);
  432. }
  433. for (int i = 0; i < mNumberOfAkaoOffsets; i++)
  434. {
  435. mAkaoOffsets.emplace_back(r.ReadU32());
  436. }
  437. mEntityScripts.reserve(mNumberOfEntities);
  438. for (int i = 0; i < mNumberOfEntities; i++)
  439. {
  440. std::array<uint16, 32> scripts;
  441. for (int j = 0; j < 32; j++)
  442. {
  443. scripts[j] = r.ReadU16();
  444. }
  445. mEntityScripts.push_back(scripts);
  446. }
  447. }
  448. };
  449. ScriptHeader mHeader;
  450. bool mbFromRaw = false;
  451. SUDM::IScriptFormatter& mFormatter;
  452. float mScaleFactor = 1.0f;
  453. };
  454. }