FieldBackgroundInstruction.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * V-Gears
  3. * Copyright (C) 2022 V-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. #include <cstdint>
  19. #include <iostream>
  20. #include <sstream>
  21. #include <boost/format.hpp>
  22. #include "decompiler/field/instruction/FieldBackgroundInstruction.h"
  23. #include "decompiler/field/FieldEngine.h"
  24. #include "decompiler/field/FieldCodeGenerator.h"
  25. #include "decompiler/field/FieldDisassembler.h"
  26. void FieldBackgroundInstruction::ProcessInst(
  27. Function& func, ValueStack&, Engine* engine, CodeGenerator *code_gen
  28. ){
  29. FunctionMetaData md(func.metadata);
  30. //std::cout << "Background opcode: " << opcode_ << "\n";
  31. switch (opcode_){
  32. case OPCODES::BGPDH: ProcessBGPDH(code_gen); break;
  33. case OPCODES::BGSCR: ProcessBGSCR(code_gen); break;
  34. case OPCODES::MPPAL: code_gen->WriteTodo(md.GetEntityName(), "MPPAL"); break;
  35. case OPCODES::BGON: ProcessBGON(code_gen, static_cast<FieldEngine&>(*engine)); break;
  36. case OPCODES::BGOFF: ProcessBGOFF(code_gen, static_cast<FieldEngine&>(*engine)); break;
  37. case OPCODES::BGROL: code_gen->WriteTodo(md.GetEntityName(), "BGROL"); break;
  38. case OPCODES::BGROL2: code_gen->WriteTodo(md.GetEntityName(), "BGROL2"); break;
  39. case OPCODES::BGCLR: ProcessBGCLR(code_gen, static_cast<FieldEngine&>(*engine)); break;
  40. case OPCODES::STPAL: ProcessSTPAL(code_gen); break;
  41. case OPCODES::LDPAL: ProcessLDPAL(code_gen); break;
  42. case OPCODES::CPPAL: ProcessCPPAL(code_gen); break;
  43. case OPCODES::RTPAL: code_gen->WriteTodo(md.GetEntityName(), "RTPAL"); break;
  44. case OPCODES::ADPAL: ProcessADPAL(code_gen); break;
  45. case OPCODES::MPPAL2: ProcessMPPAL2(code_gen); break;
  46. case OPCODES::STPLS: ProcessSTPLS(code_gen); break;
  47. case OPCODES::LDPLS: ProcessLDPLS(code_gen); break;
  48. case OPCODES::CPPAL2: code_gen->WriteTodo(md.GetEntityName(), "CPPAL2"); break;
  49. case OPCODES::ADPAL2: code_gen->WriteTodo(md.GetEntityName(), "ADPAL2"); break;
  50. case OPCODES::RTPAL2: code_gen->WriteTodo(md.GetEntityName(), "RTPAL2"); break;
  51. default:
  52. code_gen->AddOutputLine(FieldCodeGenerator::FormatInstructionNotImplemented(
  53. md.GetEntityName(), address_, opcode_
  54. ));
  55. }
  56. }
  57. void FieldBackgroundInstruction::ProcessBGPDH(CodeGenerator* code_gen){
  58. // Parallax distance of a background layer. The layer is a value, and the distance can be a
  59. // value or a variable (the bank is the first nibble).
  60. FieldCodeGenerator* cg = static_cast<FieldCodeGenerator*>(code_gen);
  61. const auto& distance = FieldCodeGenerator::FormatValueOrVariable(
  62. cg->GetFormatter(), params_[0]->GetUnsigned(), static_cast<int>(
  63. static_cast<int16_t>(params_[3]->GetUnsigned() & 0xFFFF)
  64. )
  65. );
  66. code_gen->AddOutputLine((
  67. boost::format("background2d:set_layer_parallax(%1%, %2%)") % params_[2]->GetUnsigned()
  68. % distance
  69. ).str());
  70. }
  71. void FieldBackgroundInstruction::ProcessBGSCR(CodeGenerator* code_gen){
  72. // Speed at which a background layer scrolls by itself, on each axis. The layer is a value. X
  73. // and Y can be values or variables, with the bank in the first and second nibbles.
  74. FieldCodeGenerator* cg = static_cast<FieldCodeGenerator*>(code_gen);
  75. const auto& x = FieldCodeGenerator::FormatValueOrVariable(
  76. cg->GetFormatter(), params_[0]->GetUnsigned(), static_cast<int>(
  77. static_cast<int16_t>(params_[3]->GetUnsigned() & 0xFFFF)
  78. )
  79. );
  80. const auto& y = FieldCodeGenerator::FormatValueOrVariable(
  81. cg->GetFormatter(), params_[1]->GetUnsigned(), static_cast<int>(
  82. static_cast<int16_t>(params_[4]->GetUnsigned() & 0xFFFF)
  83. )
  84. );
  85. code_gen->AddOutputLine((
  86. boost::format("background2d:set_layer_scroll(%1%, %2%, %3%)") % params_[2]->GetUnsigned()
  87. % x % y
  88. ).str());
  89. }
  90. void FieldBackgroundInstruction::ProcessBGON(CodeGenerator* code_gen, FieldEngine& engine){
  91. engine.AddBackgroundArea(params_[0]->GetUnsigned() == 0 ? params_[2]->GetUnsigned() : -1);
  92. FieldCodeGenerator* cg = static_cast<FieldCodeGenerator*>(code_gen);
  93. const auto& background_id = FieldCodeGenerator::FormatValueOrVariable(
  94. cg->GetFormatter(), params_[0]->GetUnsigned(), params_[2]->GetUnsigned()
  95. );
  96. const auto& layer_id = FieldCodeGenerator::FormatValueOrVariable(
  97. cg->GetFormatter(), params_[1]->GetUnsigned(), params_[3]->GetUnsigned()
  98. );
  99. code_gen->AddOutputLine(
  100. (boost::format("background2d:area_on(%1%, %2%)") % background_id % layer_id).str()
  101. );
  102. }
  103. void FieldBackgroundInstruction::ProcessBGOFF(CodeGenerator* code_gen, FieldEngine& engine){
  104. engine.AddBackgroundArea(params_[0]->GetUnsigned() == 0 ? params_[2]->GetUnsigned() : -1);
  105. FieldCodeGenerator* cg = static_cast<FieldCodeGenerator*>(code_gen);
  106. const auto& background_id = FieldCodeGenerator::FormatValueOrVariable(
  107. cg->GetFormatter(), params_[0]->GetUnsigned(), params_[2]->GetUnsigned()
  108. );
  109. const auto& layer_id = FieldCodeGenerator::FormatValueOrVariable(
  110. cg->GetFormatter(), params_[1]->GetUnsigned(), params_[3]->GetUnsigned()
  111. );
  112. code_gen->AddOutputLine(
  113. (boost::format("background2d:area_off(%1%, %2%)") % background_id % layer_id).str()
  114. );
  115. }
  116. void FieldBackgroundInstruction::ProcessBGCLR(CodeGenerator* code_gen, FieldEngine& engine){
  117. engine.AddBackgroundArea(params_[1]->GetUnsigned() == 0 ? params_[2]->GetUnsigned() : -1);
  118. FieldCodeGenerator* cg = static_cast<FieldCodeGenerator*>(code_gen);
  119. const auto& background_id = FieldCodeGenerator::FormatValueOrVariable(
  120. cg->GetFormatter(), params_[1]->GetUnsigned(), params_[2]->GetUnsigned()
  121. );
  122. code_gen->AddOutputLine(
  123. (boost::format("background2d:area_clear(%1%)") % background_id).str()
  124. );
  125. }
  126. void FieldBackgroundInstruction::ProcessSTPAL(CodeGenerator* code_gen){
  127. FieldCodeGenerator* cg = static_cast<FieldCodeGenerator*>(code_gen);
  128. const auto& source = FieldCodeGenerator::FormatValueOrVariable(
  129. cg->GetFormatter(), params_[0]->GetUnsigned(), params_[2]->GetUnsigned()
  130. );
  131. const auto& destination = FieldCodeGenerator::FormatValueOrVariable(
  132. cg->GetFormatter(), params_[1]->GetUnsigned(), params_[3]->GetUnsigned()
  133. );
  134. auto num_entries = params_[4]->GetUnsigned() + 1;
  135. code_gen->AddOutputLine((
  136. boost::format("-- store palette %1% to position %2%, start CLUT index 0, %3% entries")
  137. % source % destination % num_entries
  138. ).str());
  139. }
  140. void FieldBackgroundInstruction::ProcessLDPAL(CodeGenerator* code_gen){
  141. FieldCodeGenerator* cg = static_cast<FieldCodeGenerator*>(code_gen);
  142. const auto& source = FieldCodeGenerator::FormatValueOrVariable(
  143. cg->GetFormatter(), params_[0]->GetUnsigned(), params_[2]->GetUnsigned()
  144. );
  145. const auto& destination = FieldCodeGenerator::FormatValueOrVariable(
  146. cg->GetFormatter(), params_[1]->GetUnsigned(), params_[3]->GetUnsigned()
  147. );
  148. auto num_entries = params_[4]->GetUnsigned() + 1;
  149. code_gen->AddOutputLine((
  150. boost::format("-- load palette %2% from position %1%, start CLUT index 0, %3% entries")
  151. % source % destination % num_entries
  152. ).str());
  153. }
  154. void FieldBackgroundInstruction::ProcessCPPAL(CodeGenerator* code_gen){
  155. FieldCodeGenerator* cg = static_cast<FieldCodeGenerator*>(code_gen);
  156. const auto& source = FieldCodeGenerator::FormatValueOrVariable(
  157. cg->GetFormatter(), params_[0]->GetUnsigned(), params_[2]->GetUnsigned()
  158. );
  159. const auto& destination = FieldCodeGenerator::FormatValueOrVariable(
  160. cg->GetFormatter(), params_[1]->GetUnsigned(), params_[3]->GetUnsigned()
  161. );
  162. auto num_entries = params_[4]->GetUnsigned() + 1;
  163. code_gen->AddOutputLine((
  164. boost::format("-- copy palette %1% to palette %2%, %3% entries")
  165. % source % destination % num_entries
  166. ).str());
  167. }
  168. void FieldBackgroundInstruction::ProcessADPAL(CodeGenerator* code_gen){
  169. FieldCodeGenerator* cg = static_cast<FieldCodeGenerator*>(code_gen);
  170. const auto& source = FieldCodeGenerator::FormatValueOrVariable(
  171. cg->GetFormatter(), params_[0]->GetUnsigned(), params_[6]->GetUnsigned()
  172. );
  173. const auto& destination = FieldCodeGenerator::FormatValueOrVariable(
  174. cg->GetFormatter(), params_[1]->GetUnsigned(), params_[7]->GetUnsigned()
  175. );
  176. const auto& r = FieldCodeGenerator::FormatValueOrVariable(
  177. cg->GetFormatter(), params_[4]->GetUnsigned(), params_[10]->GetUnsigned()
  178. );
  179. const auto& g = FieldCodeGenerator::FormatValueOrVariable(
  180. cg->GetFormatter(), params_[3]->GetUnsigned(), params_[9]->GetUnsigned()
  181. );
  182. const auto& b = FieldCodeGenerator::FormatValueOrVariable(
  183. cg->GetFormatter(), params_[2]->GetUnsigned(), params_[8]->GetUnsigned()
  184. );
  185. auto num_entries = params_[11]->GetUnsigned() + 1;
  186. code_gen->AddOutputLine((
  187. boost::format(
  188. "-- add RGB(%3%, %4%, %5%) to %6% entries of palette stored at position %1%, "
  189. "storing result in position %2%"
  190. ) % source % destination % r % g % b % num_entries
  191. ).str());
  192. }
  193. void FieldBackgroundInstruction::ProcessMPPAL2(CodeGenerator* code_gen){
  194. FieldCodeGenerator* cg = static_cast<FieldCodeGenerator*>(code_gen);
  195. const auto& source = FieldCodeGenerator::FormatValueOrVariable(
  196. cg->GetFormatter(), params_[0]->GetUnsigned(), params_[6]->GetUnsigned()
  197. );
  198. const auto& destination = FieldCodeGenerator::FormatValueOrVariable(
  199. cg->GetFormatter(), params_[1]->GetUnsigned(), params_[7]->GetUnsigned()
  200. );
  201. const auto& r = FieldCodeGenerator::FormatValueOrVariable(
  202. cg->GetFormatter(), params_[4]->GetUnsigned(), params_[10]->GetUnsigned()
  203. );
  204. const auto& g = FieldCodeGenerator::FormatValueOrVariable(
  205. cg->GetFormatter(), params_[3]->GetUnsigned(), params_[9]->GetUnsigned()
  206. );
  207. const auto& b = FieldCodeGenerator::FormatValueOrVariable(
  208. cg->GetFormatter(), params_[2]->GetUnsigned(), params_[8]->GetUnsigned()
  209. );
  210. auto num_entries = params_[11]->GetUnsigned() + 1;
  211. code_gen->AddOutputLine((
  212. boost::format(
  213. "-- multiply RGB(%3%, %4%, %5%) by %6% entries of palette stored at position %1%, "
  214. "storing result in position %2%"
  215. ) % source % destination % r % g % b % num_entries).str());
  216. }
  217. void FieldBackgroundInstruction::ProcessSTPLS(CodeGenerator* code_gen){
  218. auto source = params_[0]->GetUnsigned();
  219. auto destination = params_[1]->GetUnsigned();
  220. auto start_clut = params_[2]->GetUnsigned();
  221. auto num_entries = params_[3]->GetUnsigned() + 1;
  222. code_gen->AddOutputLine((
  223. boost::format("-- store palette %1% to position %2%, start CLUT index %3%, %4% entries")
  224. % source % destination % start_clut % num_entries
  225. ).str());
  226. }
  227. void FieldBackgroundInstruction::ProcessLDPLS(CodeGenerator* code_gen){
  228. auto source = params_[0]->GetUnsigned();
  229. auto destination = params_[1]->GetUnsigned();
  230. auto startClut = params_[2]->GetUnsigned();
  231. auto num_entries = params_[3]->GetUnsigned() + 1;
  232. code_gen->AddOutputLine((
  233. boost::format("-- load palette %2% from position %1%, start CLUT index %3%, %4% entries")
  234. % source % destination % startClut % num_entries
  235. ).str());
  236. }