ff7_field_codegen.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #pragma once
  2. #include "decompiler/decompiler_codegen.h"
  3. #include <boost/algorithm/string.hpp>
  4. #include <deque>
  5. #include <unordered_map>
  6. #include "common/make_unique.h"
  7. #include "decompiler/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. /**
  167. * Formats a data access for a map script.
  168. *
  169. * If possible, it will look for friendly names for variables.
  170. *
  171. * @param formatter[in] Formatter to look up variable friendly names.
  172. * @param bank[in] The memory bank to use.
  173. * @param value_or_address[in] The value or memory address to use.
  174. * When bank is 0, it will be considered as a value. When bank is non
  175. * 0, it will be considered an address of the bank.
  176. * @param value_type[in] Data type to use. Used only when getting
  177. * a value, not a bank address.
  178. * @param scale[in] Scale to scale values to. Used only when using
  179. * float values, unused when type is integer or when using a bank
  180. * address.
  181. * @return String with the friendly variable name, value, or bank
  182. * address.
  183. */
  184. const std::string FormatValueOrVariable(
  185. SUDM::IScriptFormatter& formatter, uint32 bank, TValue valueOrAddress,
  186. ValueType valueType = ValueType::Integer, float scale = 1.0f
  187. ){
  188. switch (bank){
  189. case 0:
  190. switch (valueType){
  191. // TODO: check for zero
  192. case ValueType::Float: return std::to_string(valueOrAddress / scale);
  193. case ValueType::Integer: return std::to_string(valueOrAddress);
  194. default: return std::to_string(valueOrAddress);
  195. }
  196. case 1:
  197. case 2:
  198. case 3:
  199. case 13:
  200. case 15:
  201. {
  202. const auto address = static_cast<uint32>(valueOrAddress) & 0xFF;
  203. const auto friendly_name = formatter.VarName(bank, valueOrAddress);
  204. if (friendly_name.empty())
  205. return (boost::format("FFVII.Banks[%1%][%2%]") % bank % address).str();
  206. return (boost::format("FFVII.Data.%1%") % friendly_name).str();
  207. }
  208. case 5:
  209. case 6:
  210. {
  211. const auto address = static_cast<uint32>(valueOrAddress)& 0xFF;
  212. const auto friendly_name = formatter.VarName(bank, address);
  213. if (friendly_name.empty())
  214. return (boost::format("FFVII.Banks[%1%][%2%]") % bank % address).str();
  215. return "FFVII.Data." + friendly_name;
  216. }
  217. default:
  218. //throw UnknownBankException();
  219. return (boost::format(
  220. "FFVII.Banks[%1%][%2%]") % bank % (static_cast<uint32>(valueOrAddress) & 0xFF)
  221. ).str();
  222. }
  223. }
  224. }
  225. }