ff7_field_codegen.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. #pragma once
  2. #include "decompiler_codegen.h"
  3. #include <boost/algorithm/string.hpp>
  4. #include <deque>
  5. #include <unordered_map>
  6. #include "make_unique.h"
  7. #include "sudm.h"
  8. namespace FF7
  9. {
  10. class FunctionMetaData
  11. {
  12. public:
  13. // Meta data format can be:
  14. // start_end_entityname
  15. // start_entityname
  16. // end_entity_name
  17. FunctionMetaData(std::string metaData)
  18. {
  19. Parse(metaData);
  20. }
  21. bool IsStart() const
  22. {
  23. return mStart;
  24. }
  25. bool IsEnd() const
  26. {
  27. return mEnd;
  28. }
  29. std::string EntityName()
  30. {
  31. return mEntityName;
  32. }
  33. int CharacterId()
  34. {
  35. return mCharacterId;
  36. }
  37. private:
  38. void Parse(std::string str)
  39. {
  40. std::deque<std::string> strs;
  41. boost::split(strs, str, boost::is_any_of("_"), boost::token_compress_on);
  42. if (!strs.empty())
  43. {
  44. auto tmp = strs.front();
  45. strs.pop_front();
  46. ParseStart(tmp, strs);
  47. }
  48. }
  49. void ParseStart(const std::string& item, std::deque<std::string>& strs)
  50. {
  51. if (item == "start")
  52. {
  53. mStart = true;
  54. if (!strs.empty())
  55. {
  56. auto tmp = strs.front();
  57. strs.pop_front();
  58. ParseEnd(tmp, strs);
  59. }
  60. }
  61. else
  62. {
  63. ParseEnd(item, strs);
  64. }
  65. }
  66. void ParseEnd(const std::string& item, std::deque<std::string>& strs)
  67. {
  68. if (item == "end")
  69. {
  70. mEnd = true;
  71. if (!strs.empty())
  72. {
  73. auto tmp = strs.front();
  74. strs.pop_front();
  75. ParseCharId(tmp, strs);
  76. }
  77. }
  78. else
  79. {
  80. ParseCharId(item, strs);
  81. }
  82. }
  83. void ParseCharId(const std::string& item, std::deque<std::string>& strs)
  84. {
  85. if (!item.empty())
  86. {
  87. mCharacterId = std::stoi(item);
  88. }
  89. if (!strs.empty())
  90. {
  91. auto tmp = strs.front();
  92. strs.pop_front();
  93. ParseEntity(tmp, strs);
  94. }
  95. }
  96. void ParseEntity(const std::string& item, std::deque<std::string>& strs)
  97. {
  98. mEntityName = item;
  99. for (auto& part : strs)
  100. {
  101. if (!part.empty())
  102. {
  103. mEntityName += "_" + part;
  104. }
  105. }
  106. }
  107. bool mEnd = false;
  108. bool mStart = false;
  109. std::string mEntityName;
  110. int mCharacterId = -1;
  111. };
  112. class FF7CodeGenerator : public CodeGenerator
  113. {
  114. public:
  115. FF7CodeGenerator(Engine *engine, const InstVec& insts, std::ostream &output)
  116. : CodeGenerator(engine, output, kFIFOArgOrder, kLIFOArgOrder),
  117. mInsts(insts)
  118. {
  119. mTargetLang = std::make_unique<LuaTargetLanguage>();
  120. }
  121. protected:
  122. virtual std::string constructFuncSignature(const Function &func) override;
  123. virtual void onEndFunction(const Function& func) override;
  124. virtual void onBeforeStartFunction(const Function& func) override;
  125. virtual void onStartFunction(const Function& func) override;
  126. virtual bool OutputOnlyRequiredLabels() const override { return true; }
  127. private:
  128. const InstVec& mInsts;
  129. };
  130. class FF7SimpleCodeGenerator : public CodeGenerator
  131. {
  132. public:
  133. FF7SimpleCodeGenerator(Engine *engine, const InstVec& insts, std::ostream &output, SUDM::IScriptFormatter& formatter)
  134. : CodeGenerator(engine, output, kFIFOArgOrder, kLIFOArgOrder),
  135. mInsts(insts), mFormatter(formatter)
  136. {
  137. mTargetLang = std::make_unique<LuaTargetLanguage>();
  138. }
  139. virtual void generate(InstVec& insts, const Graph &g) override;
  140. virtual void addOutputLine(std::string s, bool unindentBefore = false, bool indentAfter = false) override;
  141. float ScaleFactor() const;
  142. protected:
  143. virtual std::string constructFuncSignature(const Function &func) override;
  144. virtual void onEndFunction(const Function& func) override;
  145. virtual void onBeforeStartFunction(const Function& func) override;
  146. virtual void onStartFunction(const Function& func) override;
  147. virtual bool OutputOnlyRequiredLabels() const override { return true; }
  148. private:
  149. const InstVec& mInsts;
  150. std::vector<CodeLine> mLines;
  151. public:
  152. SUDM::IScriptFormatter& mFormatter;
  153. };
  154. namespace FF7CodeGeneratorHelpers
  155. {
  156. enum struct ValueType : int
  157. {
  158. Integer = 0,
  159. Float = 1
  160. };
  161. const std::string FormatInstructionNotImplemented(const std::string& entity, uint32 address, uint32 opcode);
  162. const std::string FormatInstructionNotImplemented(const std::string& entity, uint32 address, const Instruction& instruction);
  163. const std::string FormatBool(uint32 value);
  164. const std::string FormatInvertedBool(uint32 value);
  165. template<typename TValue>
  166. const std::string FormatValueOrVariable(SUDM::IScriptFormatter& formatter, uint32 bank, TValue valueOrAddress, ValueType valueType = ValueType::Integer, float scale = 1.0f)
  167. {
  168. switch (bank)
  169. {
  170. case 0:
  171. switch (valueType)
  172. {
  173. case ValueType::Float:
  174. // TODO: check for zero
  175. return std::to_string(valueOrAddress / scale);
  176. case ValueType::Integer:
  177. default:
  178. return std::to_string(valueOrAddress);
  179. }
  180. case 1:
  181. case 2:
  182. case 3:
  183. case 13:
  184. case 15:
  185. {
  186. const auto address = static_cast<uint32>(valueOrAddress) & 0xFF;
  187. const auto friendlyName = formatter.VarName(bank, valueOrAddress);
  188. if (friendlyName.empty())
  189. {
  190. return (boost::format("FFVII.Data.var_%1%_%2%") % bank % address).str();
  191. }
  192. return (boost::format("FFVII.Data.%1%") % friendlyName).str();
  193. }
  194. case 5:
  195. case 6:
  196. {
  197. const auto address = static_cast<uint32>(valueOrAddress)& 0xFF;
  198. const auto friendlyName = formatter.VarName(bank, address);
  199. if (friendlyName.empty())
  200. {
  201. return (boost::format("FFVII.Data.temp_%1%_%2%") % bank % address).str();
  202. }
  203. return "FFVII.Data." + friendlyName;
  204. }
  205. default:
  206. //throw UnknownBankException();
  207. return (boost::format("FFVII.Data.unknown_%1%_%2%") % bank % (static_cast<uint32>(valueOrAddress) & 0xFF)).str();
  208. }
  209. }
  210. }
  211. }