ff7_field_disassembler.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. #pragma once
  2. #include "simple_disassembler.h"
  3. #include "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 scriptIndex,
  313. size_t scriptEntryPoint,
  314. uint32 nextScriptEntryPoint,
  315. bool isStart,
  316. bool isEnd);
  317. void AddFunc(std::string entityName, size_t entityIndex, size_t scriptIndex, uint32 nextScriptEntryPoint, const bool isStart, const bool isEnd, bool toReturnOnly, std::string funcName);
  318. void ReadOpCodesToPositionOrReturn(size_t endPos);
  319. std::unique_ptr<Function> StartFunction(size_t scriptIndex);
  320. FF7FieldEngine* mEngine;
  321. uint32 mHeaderEndPos = 0;
  322. void ReadHeader();
  323. void ReadHeader(BinaryReader& reader)
  324. {
  325. mHeader.Read(reader);
  326. mHeaderEndPos = reader.Position();
  327. }
  328. const static int kMagic = 0x0502;
  329. const static int kNumSections = 7;
  330. int16 kSectionPointersSize = sizeof(uint32) * kNumSections;
  331. enum eSections
  332. {
  333. eScript = 0,
  334. eWalkMesh = 1,
  335. eTileMap = 2,
  336. eCameraMatrix = 3,
  337. eTriggers = 4,
  338. eEncounter = 5,
  339. eModels = 6
  340. };
  341. std::array<uint32, 7> mSections;
  342. uint32 GetEndOfScriptOffset(uint16 curEntryPoint, size_t entityIndex, size_t scriptIndex);
  343. struct ScriptHeader
  344. {
  345. uint16 mMagic;
  346. uint8 mNumberOfEntities;
  347. uint8 mNumberOfModels;
  348. uint16 mOffsetToStrings;
  349. uint16 mNumberOfAkaoOffsets; // Specifies the number of Akao/tuto blocks/offsets
  350. uint16 mScale; // Scale of field. For move and talk calculation (9bit fixed point).
  351. std::array<uint16, 3> mBlank;
  352. std::array<char, 8> mCreator;// Field creator (never shown)
  353. std::array<char, 8> mName;// Field name (never shown)
  354. std::vector<std::array<char, 8>> mFieldEntityNames; // Count is mNumberOfEntities
  355. std::vector<uint32> mAkaoOffsets; // Akao/Tuto block offsets, count is mNumberOfAkaoOffsets
  356. // Entity script entry points, or more explicitly, subroutine offsets
  357. std::vector<std::array<uint16, 32>> mEntityScripts; // Count is mNumberOfEntities
  358. void Read(BinaryReader& r)
  359. {
  360. mMagic = r.ReadU16();
  361. if (mMagic != kMagic)
  362. {
  363. throw FF7ScriptHeaderInvalidException();
  364. }
  365. mNumberOfEntities = r.ReadU8();
  366. mNumberOfModels = r.ReadU8();
  367. mOffsetToStrings = r.ReadU16();
  368. mNumberOfAkaoOffsets = r.ReadU16();
  369. mScale = r.ReadU16();
  370. for (int i = 0; i < 3; i++)
  371. {
  372. mBlank[i] = r.ReadU16();
  373. }
  374. for (int i = 0; i < 8; i++)
  375. {
  376. mCreator[i] = r.ReadU8();
  377. }
  378. for (int i = 0; i < 8; i++)
  379. {
  380. mName[i] = r.ReadU8();
  381. }
  382. for (int i = 0; i < mNumberOfEntities; i++)
  383. {
  384. std::array<char, 8> name;
  385. for (int j = 0; j < 8; j++)
  386. {
  387. name[j] = r.ReadU8();
  388. }
  389. mFieldEntityNames.emplace_back(name);
  390. }
  391. for (int i = 0; i < mNumberOfAkaoOffsets; i++)
  392. {
  393. mAkaoOffsets.emplace_back(r.ReadU32());
  394. }
  395. mEntityScripts.reserve(mNumberOfEntities);
  396. for (int i = 0; i < mNumberOfEntities; i++)
  397. {
  398. std::array<uint16, 32> scripts;
  399. for (int j = 0; j < 32; j++)
  400. {
  401. scripts[j] = r.ReadU16();
  402. }
  403. mEntityScripts.push_back(scripts);
  404. }
  405. }
  406. };
  407. ScriptHeader mHeader;
  408. bool mbFromRaw = false;
  409. SUDM::IScriptFormatter& mFormatter;
  410. float mScaleFactor = 1.0f;
  411. };
  412. }