ff7_field_engine.h 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009
  1. /*
  2. * Q-Gears
  3. * Copyright (C) 2022 Q-Gears Team
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program 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. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #pragma once
  19. #include "decompiler/decompiler_engine.h"
  20. #include <string>
  21. #include <vector>
  22. #include "sudm.h"
  23. namespace FF7{
  24. /**
  25. * Represents the FF7 Field engine.
  26. */
  27. class FF7FieldEngine : public Engine{
  28. public:
  29. /**
  30. * FF7FieldEngine constructor.
  31. *
  32. * Generates a FF7FieldEngine.
  33. *
  34. * @param formatter[in] The formatter to be used by the engine.
  35. * @param scriptName The script name.
  36. */
  37. FF7FieldEngine(
  38. SUDM::IScriptFormatter& formatter, std::string scriptName
  39. ) : mFormatter(formatter), mScriptName(scriptName){
  40. setOutputStackEffect(false);
  41. }
  42. /**
  43. * Destructor.
  44. */
  45. FF7FieldEngine(const FF7FieldEngine&) = delete;
  46. /**
  47. * Destructor.
  48. */
  49. FF7FieldEngine& operator = (const FF7FieldEngine&) = delete;
  50. /**
  51. * Represents an entity.
  52. *
  53. * An entity can be almost anything in a field map: the playable
  54. * character, an NPC, an item, a line...
  55. */
  56. class Entity{
  57. public:
  58. /**
  59. * Entity constructor.
  60. *
  61. * It doesn't initialize any of the fields.
  62. */
  63. Entity() = default;
  64. /**
  65. * Entity constructor.
  66. *
  67. * Instantiates an entity with a name.
  68. *
  69. * @param name[in] Entity name.
  70. */
  71. Entity(const std::string& name): mName(name), is_line_(false){}
  72. /**
  73. * Retrieves the entity name.
  74. *
  75. * @return The entity name
  76. */
  77. std::string Name() const{
  78. return mName;
  79. }
  80. /**
  81. * Retrieves a function.
  82. *
  83. * Retrieves the name of a function from it's index.
  84. *
  85. * @param index[in] Function index.
  86. * @return Function name.
  87. * @throws InternalDecompilerError if there is no function
  88. * with the specified index.
  89. * @todo What is a function here? An Opcode?
  90. */
  91. std::string FunctionByIndex(size_t index) const{
  92. auto it = mFunctions.find(index);
  93. if (it == std::end(mFunctions)){
  94. throw InternalDecompilerError();
  95. }
  96. return it->second;
  97. }
  98. /**
  99. * Adds a function to the engine.
  100. *
  101. * Must be added by name and index.
  102. *
  103. * @param name[in] Function name. If the entity is a line,
  104. * the name will be overridden.
  105. * @param index[in] Function index.
  106. * @todo What is a function here? An Opcode?
  107. */
  108. void AddFunction(const std::string& name, size_t index){
  109. // TODO: Delete renaming and test. It should work.
  110. std::string new_name = name;
  111. if (is_line_){
  112. switch (index){
  113. case 2: new_name = "on_enter_line"; break;
  114. case 3: new_name = "on_move_to_line"; break;
  115. case 4: new_name = "on_cross_line"; break;
  116. case 5: new_name = "on_leave_line"; break;
  117. }
  118. }
  119. mFunctions[index] = new_name;
  120. }
  121. /**
  122. * Indicates if the entity is a line.
  123. * @TODO: Make private.
  124. */
  125. bool is_line_;
  126. /**
  127. * The first point of the line.
  128. * @TODO: Make private.
  129. */
  130. std::vector<float> point_a_;
  131. /**
  132. * The first point of the line.
  133. * @TODO: Make private.
  134. */
  135. std::vector<float> point_b_;
  136. float ax, ay, az, bx, by, bz;
  137. private:
  138. /**
  139. * Entity name.
  140. */
  141. std::string mName;
  142. /**
  143. * Function list.
  144. * @todo What is a function here? An Opcode?
  145. */
  146. std::map< size_t, std::string > mFunctions;
  147. };
  148. /**
  149. * Retrieves the dissasembler.
  150. *
  151. * @param insts[in] List of instructions.
  152. * @param rawScriptData[in] Script data, raw format.
  153. * @return Pointer to the dissasembler.
  154. * @todo Understand and document properly.
  155. */
  156. virtual std::unique_ptr<Disassembler> getDisassembler(
  157. InstVec &insts, const std::vector<unsigned char>& rawScriptData
  158. ) override;
  159. /**
  160. * Retrieves the dissasembler.
  161. *
  162. * @param insts[in] List of instructions.
  163. * @return Pointer to the dissasembler.
  164. * @todo Understand and document properly.
  165. */
  166. virtual std::unique_ptr<Disassembler> getDisassembler(
  167. InstVec &insts
  168. ) override;
  169. /**
  170. * Retrieves the code generator.
  171. *
  172. * @param insts[in] List of instructions.
  173. * @param output[in] Pointer to the output (file, stream...).
  174. * @return Pointer to the generator.
  175. * @todo Understand and document properly.
  176. */
  177. virtual std::unique_ptr<CodeGenerator> getCodeGenerator(
  178. const InstVec& insts, std::ostream &output
  179. ) override;
  180. /**
  181. * Postprocessing actions to apply to the scripts.
  182. *
  183. * @param insts[in] Instruction list.
  184. * @param g[in] Code graph.
  185. * @todo Understand and document properly.
  186. * @todo What is the graph used to?
  187. */
  188. virtual void postCFG(InstVec &insts, Graph g) override;
  189. /**
  190. * Indicates if instructions are purely grouped.
  191. *
  192. * @return True if instructions are purely grouped.
  193. * @todo What is pure grouping?
  194. */
  195. virtual bool usePureGrouping() const override{return false;}
  196. /**
  197. * Retrieves all entities in the map.
  198. *
  199. * @return A map of entities, with the name and index.
  200. */
  201. std::map<std::string, int> GetEntities() const;
  202. /**
  203. * Retrieves all line entities in the map.
  204. *
  205. * @param A list of line entities.
  206. */
  207. std::vector<SUDM::FF7::Field::Line> GetLineList() const;
  208. /**
  209. * Retrieves all entities in the map.
  210. *
  211. * @return A map of entities, with the name and index.
  212. */
  213. std::map<size_t, Entity> GetEntityIndexMap() const{
  214. return mEntityIndexMap;
  215. }
  216. /**
  217. * Adds a function to an entity.
  218. *
  219. * @param entityName Name of the entity.
  220. * @param entityIndex Index of the entity.
  221. * @param functionName Name of the function.
  222. * @param functionIndex Index of the function.
  223. */
  224. void AddEntityFunction(
  225. const std::string& entityName, size_t entityIndex,
  226. const std::string& funcName, size_t funcIndex
  227. );
  228. /**
  229. * Marks an entity as a line.
  230. *
  231. * @param entity_index Index of the entity.
  232. * @param line[in] True to mark the entity as a line, false to
  233. * unmark it.
  234. * @param point_a[in] First point of the line. Can be null if line
  235. * is false.
  236. * @param point_b[in] Second point of the line. Can be null if
  237. * line is false.
  238. */
  239. void MarkEntityAsLine(
  240. size_t entity_index, bool line,
  241. std::vector<float> point_a, std::vector<float> point_b
  242. );
  243. /**
  244. * Checks if an entity has been marked as a line.
  245. *
  246. * @param entity_index[in] Index of the entity to check.
  247. * @return True if the entity is a line. False if it isn't, or if
  248. * there is no such entity.
  249. */
  250. bool EntityIsLine(size_t entity_index);
  251. /**
  252. * Retrieves an entity.
  253. *
  254. * @param index[in] Index of the entity to retrieve.
  255. * @throws InternalDecompilerError if there is no entity at the
  256. * specified index.
  257. */
  258. const Entity& EntityByIndex(size_t index) const{
  259. auto it = mEntityIndexMap.find(index);
  260. if (it == std::end(mEntityIndexMap)){
  261. throw InternalDecompilerError();
  262. }
  263. return it->second;
  264. }
  265. /**
  266. * Retrieves the scale factor for the map.
  267. *
  268. * @return Map scale factor.
  269. */
  270. float ScaleFactor() const {return mScaleFactor;}
  271. /**
  272. * Retrieves the script name.
  273. *
  274. * @return The script name.
  275. */
  276. const std::string& ScriptName() const { return mScriptName; }
  277. private:
  278. /**
  279. * Removes extraneous return statements.
  280. *
  281. * Usefull for scripts that only contain one one return
  282. * statement.
  283. *
  284. * @param insts[in|out] List of instructions to proccess. Extraneous
  285. * return statements will be deleted from the instructions.
  286. * @param g[in] Code graph.
  287. * @todo What is the graph used to?
  288. */
  289. void RemoveExtraneousReturnStatements(InstVec& insts, Graph g);
  290. /**
  291. * Removes trailing infinite loops.
  292. *
  293. * In FF7 some scripts ends with an infinite loop to keep it alive.
  294. * in QGears this isn't required, and can cause infinite loops, so
  295. * they can be removed.
  296. *
  297. * @param insts[in|out] List of instructions to proccess. Trailing
  298. * infinite loops will be deleted from the instructions.
  299. * @param g[in] Code graph.
  300. * @todo What is the graph used to?
  301. */
  302. void RemoveTrailingInfiniteLoops(InstVec& insts, Graph g);
  303. /**
  304. * Tries to detect scripts with trailing infinite loops.
  305. *
  306. * In FF7 some scripts ends with an infinite loop to keep it alive.
  307. * in QGears this isn't required, and can cause infinite loops, so
  308. * they can be removed. This function marks them, so they can be
  309. * deleted with @{see FF7FieldEngine::RemoveTrailingInfiniteLoops}
  310. */
  311. void MarkInfiniteLoopGroups(InstVec& insts, Graph g);
  312. /**
  313. * The script formatter.
  314. */
  315. SUDM::IScriptFormatter& mFormatter;
  316. /**
  317. * The entity index map for the field.
  318. */
  319. std::map<size_t, Entity> mEntityIndexMap;
  320. /**
  321. * The map scale factor.
  322. */
  323. float mScaleFactor = 1.0f;
  324. /**
  325. * The script name.
  326. */
  327. std::string mScriptName;
  328. };
  329. /**
  330. * An unconditional map jump instruction.
  331. */
  332. class FF7UncondJumpInstruction : public UncondJumpInstruction{
  333. public:
  334. /**
  335. * Whether or not this is really a call to a script function.
  336. */
  337. bool _isCall;
  338. /**
  339. * Constructor.
  340. */
  341. FF7UncondJumpInstruction() : _isCall(false) {}
  342. /**
  343. * Indicates if the instruction is a function call.
  344. *
  345. * @return true if the instruction is a function call, false if not.
  346. */
  347. virtual bool isFuncCall() const;
  348. /**
  349. * Indicates if the instruction is an unconditional jump.
  350. *
  351. * @return true if the instruction is an unconditional jump, false
  352. * if it's not.
  353. */
  354. virtual bool isUncondJump() const;
  355. /**
  356. * Retrieves the destination address of the jump.
  357. *
  358. * @return The offset (number of bytes) to jump from the beginning
  359. * of the instruction.
  360. */
  361. virtual uint32 getDestAddress() const;
  362. /**
  363. * Processes the instruction.
  364. *
  365. * @param func[in] Function to process.
  366. * @param stack[out] Function stack.
  367. * @param engine[in] Engine.
  368. * @param codeGen[in] Code generator.
  369. * @todo Func and engine are unused?
  370. * @todo Understand and document properly.
  371. */
  372. virtual void processInst(
  373. Function& func, ValueStack &stack,
  374. Engine *engine, CodeGenerator *codeGen
  375. ) override;
  376. /**
  377. * Prints the instruction
  378. *
  379. * @param output The stram to print the instruction to.
  380. * @todo Understand and document properly.
  381. */
  382. virtual std::ostream& print(std::ostream &output) const override;
  383. };
  384. /**
  385. * A conditional map jump instruction.
  386. */
  387. class FF7CondJumpInstruction : public CondJumpInstruction{
  388. public:
  389. /**
  390. * Processes the instruction.
  391. *
  392. * @param func[in] Function to process.
  393. * @param stack[out] Function stack.
  394. * @param engine[in] Engine.
  395. * @param codeGen[in] Code generator.
  396. * @todo Func and engine are unused?
  397. * @todo Understand and document properly.
  398. */
  399. virtual void processInst(
  400. Function& func, ValueStack &stack,
  401. Engine *engine, CodeGenerator *codeGen
  402. ) override;
  403. /**
  404. * Retrieves the destination address of the jump.
  405. *
  406. * @return The offset (number of bytes) to jump from the beginning
  407. * of the instruction.
  408. */
  409. virtual uint32 getDestAddress() const override;
  410. /**
  411. * Prints the instruction
  412. *
  413. * @param output The stram to print the instruction to.
  414. * @todo Understand and document properly.
  415. */
  416. virtual std::ostream& print(std::ostream &output) const override;
  417. };
  418. /**
  419. * A script flow control instruction.
  420. */
  421. class FF7ControlFlowInstruction : public KernelCallInstruction{
  422. public:
  423. /**
  424. * Create a FF7ControlFlowInstruction.
  425. *
  426. * @return Pointer to the newly created instruction.
  427. */
  428. static InstPtr Create(){return new FF7ControlFlowInstruction();}
  429. /**
  430. * Processes the instruction.
  431. *
  432. * @param func[in] Function to process.
  433. * @param stack[out] Function stack.
  434. * @param engine[in] Engine.
  435. * @param codeGen[in] Code generator.
  436. * @todo Func and engine are unused?
  437. * @todo Understand and document properly.
  438. */
  439. virtual void processInst(
  440. Function& func, ValueStack &stack,
  441. Engine *engine, CodeGenerator *codeGen
  442. ) override;
  443. private:
  444. /**
  445. * Processes a REQ command.
  446. *
  447. * Opcode: 0x01
  448. * Short name: REQ
  449. * Long name: Request remote execution (asynchronous,
  450. * non-guaranteed)
  451. *
  452. * Memory layout
  453. * 0x01
  454. * E
  455. * P/F
  456. *
  457. * Arguments
  458. *
  459. * const UByte E: The ID of the target entity.
  460. * const Bit[3] P: The priority at which we want to execute the
  461. * remote script (high 3 bits of byte).
  462. * const Bit[5] F: The ID of the specific member function of E to be
  463. * executed (low 5 bits of byte).
  464. *
  465. * Requests that a remote entity executes one of its member
  466. * functions at a specified priority. The request is asynchronous
  467. * and returns immediately without waiting for the remote execution
  468. * to start or finish. If the specified priority is already busy
  469. * executing, the request will fail silently.
  470. *
  471. * @param codegen[in|out] Code generator. Output lines are appended
  472. * to it.
  473. * @param engine[in] The engine instance to fetch entities.
  474. */
  475. void processREQ(
  476. CodeGenerator* codeGen,
  477. const FF7FieldEngine& engine
  478. );
  479. /**
  480. * Processes a REQSW command.
  481. *
  482. * Opcode: 0x02
  483. * Short name: REQSW
  484. * Long name: Request remote execution (asynchronous execution,
  485. * guaranteed)
  486. *
  487. * Memory layout
  488. * 0x02
  489. * E
  490. * P/F
  491. *
  492. * Arguments
  493. *
  494. * const UByte E: The ID of the target entity.
  495. * const Bit[3] P: The priority at which we want to execute the
  496. * remote script (high 3 bits of byte).
  497. * const Bit[5] F: The ID of the specific member function of E to be
  498. * executed (low 5 bits of byte).
  499. *
  500. * Requests that a remote entity executes one of its member
  501. * functions at a specified priority. If the specified priority is
  502. * already busy executing, the request will block until it becomes
  503. * available and only then return. The remote execution is still
  504. * carried out asynchronously, with no notification of completion.
  505. *
  506. * @param codegen[in|out] Code generator. Output lines are appended
  507. * to it.
  508. * @param engine[in] The engine instance to fetch entities.
  509. */
  510. void processREQSW(
  511. CodeGenerator* codeGen,
  512. const FF7FieldEngine& engine
  513. );
  514. /**
  515. * Processes a REQEW command.
  516. *
  517. * Opcode: 0x03
  518. * Short name: REQEW
  519. * Long name: Request remote execution (synchronous, guaranteed)
  520. *
  521. * Memory layout
  522. * 0x03
  523. * E
  524. * P/F
  525. *
  526. * Arguments
  527. *
  528. * const UByte E: The ID of the target entity.
  529. * const Bit[3] P: The priority at which we want to execute the
  530. * remote script (high 3 bits of byte).
  531. * const Bit[5] F: The ID of the specific member function of E to be
  532. * executed (low 5 bits of byte).
  533. *
  534. * Requests that a remote entity executes one of its member
  535. * functions at a specified priority. The request will block until
  536. * remote execution has finished before returning.
  537. *
  538. * @param codegen[in|out] Code generator. Output lines are appended
  539. * to it.
  540. * @param engine[in] The engine instance to fetch entities.
  541. */
  542. void processREQEW(
  543. CodeGenerator* codeGen,
  544. const FF7FieldEngine& engine
  545. );
  546. /**
  547. * Processes a RETTO command.
  548. *
  549. * Opcode: 0x07
  550. * Short name: RETTO
  551. * Long name: Return To
  552. *
  553. * Memory layout
  554. * 0x07
  555. * P/F
  556. *
  557. * Arguments
  558. * const Bit[3] P: The priority at which we want to execute the
  559. * remote script (high 3 bits of byte).
  560. * const Bit[5] F: The ID of the specific member function of the
  561. * current entity to be executed to (low 5 bits
  562. * of byte).
  563. *
  564. * Stops the active script loop for this entity and also any script
  565. * loops (except the main) that are queuing to be executed after the
  566. * current script. This is essentially the same as adding a RET onto
  567. * each of the active / queued scripts next execution position and
  568. * returning the current op index to index for each script. Then the
  569. * script control is passed to the script F within the current
  570. * entity with the priority P.
  571. *
  572. * @param codegen[in|out] Code generator. Output lines are appended
  573. * to it.
  574. */
  575. void processRETTO(CodeGenerator* codeGen);
  576. /**
  577. * Processes a WAIT command.
  578. *
  579. * Opcode: 0x24
  580. * Short name: WAIT
  581. * Long name: Wait
  582. *
  583. * Memory layout
  584. * 0x24
  585. * A
  586. *
  587. * Arguments
  588. * const UShort A: Amount (number of frames) to wait.
  589. *
  590. * Pauses current script execution for a specific amount of time.
  591. * Rather than a specific time value in milliseconds/seconds,
  592. * the amount specifies the number of frames that must be drawn
  593. * before execution resumes. Since the game runs at 30fps,
  594. * WAIT(0x1E) (or WAIT(30) in decimal) will pause script execution
  595. * for 1 second, WAIT(0x96) will pause for 5 seconds, and so on.
  596. *
  597. * @param codegen[in|out] Code generator. Output lines are appended
  598. * to it.
  599. */
  600. void processWAIT(CodeGenerator* codeGen);
  601. };
  602. /**
  603. * A module instruction.
  604. */
  605. class FF7ModuleInstruction : public KernelCallInstruction{
  606. public:
  607. /**
  608. * Processes the instruction.
  609. *
  610. * @param func[in] Function to process.
  611. * @param stack[out] Function stack.
  612. * @param engine[in] Engine.
  613. * @param codeGen[in] Code generator.
  614. * @todo Func and engine are unused?
  615. * @todo Understand and document properly.
  616. */
  617. virtual void processInst(
  618. Function& func, ValueStack &stack,
  619. Engine *engine, CodeGenerator *codeGen
  620. ) override;
  621. private:
  622. /**
  623. * Processes a BATTLE command.
  624. *
  625. * Opcode: 0x70
  626. * Short name: BATTLE
  627. * Long name: Start battle
  628. *
  629. * Memory layout
  630. * 0x70
  631. * B
  632. * N
  633. * N
  634. *
  635. * Arguments
  636. * const UByte B: Bank (16-bit) to retrieve the address of the
  637. * battle ID, or zero if it is given as a literal
  638. * value.
  639. * const UWord N: Battle ID, or address to find ID if B is
  640. * non-zero.
  641. *
  642. * This launches the battle module with whatever battle number is
  643. * used in the argument, or the value retrieved from memory location
  644. * N if B is non-zero. Battle 1, 2, and 999 (0x03E7) are debug
  645. * battles.
  646. *
  647. * @param codegen[in|out] Code generator. Output lines are appended
  648. * to it.
  649. */
  650. void processBATTLE(CodeGenerator* codeGen);
  651. /**
  652. * Processes a BTLON command.
  653. *
  654. * Opcode: 0x71
  655. * Short name: BTLON
  656. * Long name: Battle switch
  657. *
  658. * Memory layout
  659. * 0x71
  660. * S
  661. *
  662. * Arguments
  663. * const UByte S: Switch battles on/off (0/1, respectively).
  664. *
  665. * Turns random encounters on or off for this field. Note that if a
  666. * field does not have any Encounter Data set in its field file,
  667. * battles will not occur regardless of the argument passed with
  668. * this opcode.
  669. *
  670. * @param codegen[in|out] Code generator. Output lines are appended
  671. * to it.
  672. */
  673. void processBTLON(CodeGenerator* codeGen);
  674. /**
  675. * Processes a MAPJUMP command.
  676. *
  677. * Opcode: 0x60
  678. * Short name: BTLON
  679. * Long name: Change Field
  680. *
  681. * Memory layout
  682. * 0x60
  683. * I
  684. * I
  685. * X
  686. * X
  687. * Y
  688. * Y
  689. * Z
  690. * Z
  691. * D
  692. *
  693. * Arguments
  694. * const UShort I: Field ID of the map to jump to.
  695. * const Short X: X-coordinate of the player on the next field.
  696. * const Short Y: Y-coordinate of the player on the next field.
  697. * const Short Z: Z-coordinate of the player on the next field.
  698. * const UByte D: Direction the character will be facing on the
  699. * next field, in the standard game format.
  700. *
  701. * Switches fields to the one indicated by I, and places the
  702. * character at the coordinates and direction specified. This is an
  703. * alternative to using a gateway, and can complement their usage as
  704. * it allows for more than 12 gateways by simulating their behaviour
  705. * through a LINE which, when crossed, executes a MAPJUMP.
  706. *
  707. * @param codegen[in|out] Code generator. Output lines are appended
  708. * to it.
  709. * @param func[in] Function
  710. * @todo What is func for?
  711. */
  712. void processMAPJUMP(CodeGenerator* codeGen, Function& func);
  713. };
  714. class FF7MathInstruction : public StoreInstruction
  715. {
  716. public:
  717. virtual void processInst(Function& func, ValueStack &stack, Engine *engine, CodeGenerator *codeGen) override;
  718. private:
  719. void processSaturatedPLUS(CodeGenerator* codeGen);
  720. void processSaturatedPLUS2(CodeGenerator* codeGen);
  721. void processSaturatedMINUS(CodeGenerator* codeGen);
  722. void processSaturatedMINUS2(CodeGenerator* codeGen);
  723. void processSaturatedINC(CodeGenerator* codeGen);
  724. void processSaturatedINC2(CodeGenerator* codeGen);
  725. void processSaturatedDEC(CodeGenerator* codeGen);
  726. void processSaturatedDEC2(CodeGenerator* codeGen);
  727. void processRDMSD(CodeGenerator* codeGen);
  728. void processSETBYTE_SETWORD(CodeGenerator* codeGen);
  729. void processBITON(CodeGenerator* codeGen);
  730. void processPLUSx_MINUSx(CodeGenerator* codeGen, const std::string& op);
  731. void processINCx_DECx(CodeGenerator* codeGen, const std::string& op);
  732. void processRANDOM(CodeGenerator* codeGen);
  733. };
  734. class FF7WindowInstruction : public KernelCallInstruction
  735. {
  736. public:
  737. virtual void processInst(Function& func, ValueStack &stack, Engine *engine, CodeGenerator *codeGen) override;
  738. private:
  739. void processMESSAGE(CodeGenerator* codeGen, const std::string& scriptName);
  740. void processMPNAM(CodeGenerator* codeGen);
  741. void processMENU2(CodeGenerator* codeGen);
  742. void processWINDOW(CodeGenerator* codeGen);
  743. void processWCLSE(CodeGenerator* codeGen);
  744. };
  745. class FF7PartyInstruction : public KernelCallInstruction
  746. {
  747. public:
  748. virtual void processInst(Function& func, ValueStack &stack, Engine *engine, CodeGenerator *codeGen) override;
  749. private:
  750. void processSTITM(CodeGenerator* codeGen);
  751. void processPRTYE(CodeGenerator* codeGen);
  752. };
  753. class FF7ModelInstruction : public KernelCallInstruction
  754. {
  755. public:
  756. virtual void processInst(Function& func, ValueStack &stack, Engine *engine, CodeGenerator *codeGen) override;
  757. private:
  758. void processTLKON(CodeGenerator* codeGen, const std::string& entity);
  759. void processPC(CodeGenerator* codeGen, const std::string& entity);
  760. void processCHAR(CodeGenerator* codeGen, const std::string& entity);
  761. void processDFANM(CodeGenerator* codeGen, const std::string& entity, int charId);
  762. void processANIME1(CodeGenerator* codeGen, const std::string& entity, int charId);
  763. void processVISI(CodeGenerator* codeGen, const std::string& entity);
  764. void processXYZI(CodeGenerator* codeGen, const std::string& entity);
  765. void processMOVE(CodeGenerator* codeGen, const std::string& entity);
  766. void processMSPED(CodeGenerator* codeGen, const std::string& entity);
  767. void processDIR(CodeGenerator* codeGen, const std::string& entity);
  768. void processTURNGEN(CodeGenerator* codeGen, const std::string& entity);
  769. void processGETAI(CodeGenerator* codeGen, const FF7FieldEngine& engine);
  770. void processANIM_2(CodeGenerator* codeGen, const std::string& entity, int charId);
  771. void processCANIM2(CodeGenerator* codeGen, const std::string& entity, int charId);
  772. void processCANM_2(CodeGenerator* codeGen, const std::string& entity, int charId);
  773. void processCC(CodeGenerator* codeGen, const FF7FieldEngine& engine);
  774. void processSOLID(CodeGenerator* codeGen, const std::string& entity);
  775. /**
  776. * Processes an OFST opcode.
  777. *
  778. * Opcode: 0xC3
  779. * Short name: OFST
  780. * Long name: Offset Object
  781. *
  782. * Memory layout (8 bytes)
  783. * |0xC3|B1/B2|B3/B4|T|X|Y|Z|S|
  784. *
  785. * Arguments:
  786. * - const Bit[4] B1: Bank to retrieve X offset, or zero if X is
  787. * specified as a literal.
  788. * - const Bit[4] B2: Bank to retrieve Y offset, or zero if Y is
  789. * specified as a literal.
  790. * - const Bit[4] B3: Bank to retrieve Z offset, or zero if Z is
  791. * specified as a literal.
  792. * - const Bit[4] B4: Bank to retrieve speed, or zero if S is specified
  793. * as a literal.
  794. * - const UByte T: Type of movement.
  795. * - const Short X: X offset amount, relative to current position, or
  796. * address to find X offset, if B1 is non-zero.
  797. * - const Short Y: Y offset amount, relative to current position, or
  798. * address to find Y offset, if B2 is non-zero.
  799. * - const Short Z: Z offset amount, relative to current position, or
  800. * address to find Z offset, if B3 is non-zero.
  801. * - const UShort S: Speed of the offset movement, if type is non-zero,
  802. * or address to find speed, if B4 is non-zero.
  803. *
  804. * Offsets the field object, belonging to the entity whose script this
  805. * opcode resides in, by a certain amount. After being offset, the
  806. * character continues to be constrained in movement as defined by the
  807. * walkmesh's shape, but at a certain distance away from the normal
  808. * walkmesh position. Other field objects are unaffected, and their
  809. * position or movements are maintained on the walkmesh's original
  810. * position. If B1, B2, B3 or B4 is non-zero, then the value for that
  811. * particular component is taken from memory using the corresponding
  812. * bank and address specified, rather than as a literal value. Both
  813. * retrieved values and literals can be used for different components.
  814. * If using T, X, Y or S as addresses, the lower byte should hold the
  815. * address whilst the higher byte should be zero. The amount to offset
  816. * is specified relative to the current position. If Type is specified,
  817. * the object moves gradually from its current point to the offset
  818. * position; this can be used to simulate movements such as elevators.
  819. * Any type outside the range in the table will cause the offset not to
  820. * occur. If the object is set to move gradually, then the speed of
  821. * offset can be set; the greater the number, the slower the object
  822. * moves to its target offset. Script execution may also be halted
  823. * until the gradual offset has been completed. For this, see OFSTW.
  824. *
  825. * @param codeGen The code generator.
  826. * @param entity[in] The entity name.
  827. */
  828. void processOFST(CodeGenerator* codegen, const std::string& entity);
  829. };
  830. class FF7WalkmeshInstruction : public KernelCallInstruction
  831. {
  832. public:
  833. virtual void processInst(Function& func, ValueStack &stack, Engine *engine, CodeGenerator *codeGen) override;
  834. private:
  835. void processUC(CodeGenerator* codeGen);
  836. /**
  837. * Processes a LINE opcode.
  838. *
  839. * Opcode: 0xD0
  840. * Short name: LINE
  841. * Long name: Line definition
  842. *
  843. * Memory layout (7 bytes)
  844. * |0xD0|XA|YA|ZA|XB|YB|ZB|
  845. *
  846. * Arguments:
  847. * - const Short XA: X-coordinate of the first point of the line.
  848. * - const Short YA: Y-coordinate of the first point of the line.
  849. * - const Short ZA: Z-coordinate of the first point of the line.
  850. * - const Short XB: X-coordinate of the second point of the line.
  851. * - const Short YB: Y-coordinate of the second point of the line.
  852. * - const Short ZB: Z-coordinate of the second point of the line.
  853. *
  854. * Defines a line on the walkmesh that, when crossed by a playable
  855. * character, causes one of the entity's scripts to be executed. These
  856. * are similar to the triggers in Section 8. All the lines in the
  857. * current field can be turned on or off by using the LINON opcode.
  858. *
  859. * There are generally 6 scripts (other than the init and main) if the entity is a LINE.
  860. * - script index 2 -> S1 - [OK].
  861. * - script index 3 -> S2 - Move.
  862. * - script index 4 -> S3 - Move.
  863. * - script index 5 -> S4 - Go.
  864. * - script index 6 -> S5 - Go 1x.
  865. * - script index 7 -> S6 - Go away.
  866. *
  867. * @param codeGen The code generator.
  868. * @param entity[in] The entity name.
  869. */
  870. void processLINE(CodeGenerator* codeGen, const std::string& entity);
  871. };
  872. class FF7BackgroundInstruction : public KernelCallInstruction
  873. {
  874. public:
  875. virtual void processInst(Function& func, ValueStack &stack, Engine *engine, CodeGenerator *codeGen) override;
  876. private:
  877. void processBGON(CodeGenerator* codeGen);
  878. void processBGOFF(CodeGenerator* codeGen);
  879. void processBGCLR(CodeGenerator* codeGen);
  880. void processSTPAL(CodeGenerator* codeGen);
  881. void processLDPAL(CodeGenerator* codeGen);
  882. void processCPPAL(CodeGenerator* codeGen);
  883. void processADPAL(CodeGenerator* codeGen);
  884. void processMPPAL2(CodeGenerator* codeGen);
  885. void processSTPLS(CodeGenerator* codeGen);
  886. void processLDPLS(CodeGenerator* codeGen);
  887. };
  888. class FF7CameraInstruction : public KernelCallInstruction
  889. {
  890. public:
  891. virtual void processInst(Function& func, ValueStack &stack, Engine *engine, CodeGenerator *codeGen) override;
  892. private:
  893. void processNFADE(CodeGenerator* codeGen);
  894. void processSCR2D(CodeGenerator* codeGen);
  895. void processSCR2DC(CodeGenerator* codeGen);
  896. void processFADE(CodeGenerator* codeGen);
  897. };
  898. class FF7AudioVideoInstruction : public KernelCallInstruction
  899. {
  900. public:
  901. virtual void processInst(Function& func, ValueStack &stack, Engine *engine, CodeGenerator *codeGen) override;
  902. private:
  903. void processAKAO2(CodeGenerator* codeGen);
  904. void processMUSIC(CodeGenerator* codeGen);
  905. void processSOUND(CodeGenerator* codeGen);
  906. void processAKAO(CodeGenerator* codeGen);
  907. void processMULCK(CodeGenerator* codeGen);
  908. void processPMVIE(CodeGenerator* codeGen);
  909. void processMOVIE(CodeGenerator* codeGen);
  910. void processMVIEF(CodeGenerator* codeGen);
  911. };
  912. class FF7UncategorizedInstruction : public KernelCallInstruction
  913. {
  914. public:
  915. virtual void processInst(Function& func, ValueStack &stack, Engine *engine, CodeGenerator *codeGen) override;
  916. };
  917. class FF7NoOperationInstruction : public Instruction
  918. {
  919. public:
  920. static InstPtr Create() { return new FF7NoOperationInstruction(); }
  921. virtual void processInst(Function& func, ValueStack &stack, Engine *engine, CodeGenerator *codeGen) override;
  922. };
  923. }