diff --git a/PowerRecomp/recompiler.cpp b/PowerRecomp/recompiler.cpp index c0ca801..a868b8b 100644 --- a/PowerRecomp/recompiler.cpp +++ b/PowerRecomp/recompiler.cpp @@ -325,6 +325,51 @@ bool Recompiler::Recompile( } }; + auto midAsmHook = config.midAsmHooks.find(base); + if (midAsmHook != config.midAsmHooks.end()) + { + print("\t{}(", midAsmHook->second.name); + for (auto& reg : midAsmHook->second.registers) + { + if (out.back() != '(') + out += ", "; + + switch (reg[0]) + { + case 'c': + if (reg == "ctr") + out += ctr(); + else + out += cr(std::atoi(reg.c_str() + 2)); + break; + + case 'x': + out += xer(); + break; + + case 'r': + if (reg == "reserved") + out += reserved(); + else + out += r(std::atoi(reg.c_str() + 1)); + break; + + case 'f': + if (reg == "fpscr") + out += "ctx.fpscr"; + else + out += f(std::atoi(reg.c_str() + 1)); + break; + + case 'v': + out += v(std::atoi(reg.c_str() + 1)); + break; + } + } + + println(");"); + } + int id = insn.opcode->id; // Handling instructions that don't disassemble correctly for some reason here @@ -2092,6 +2137,48 @@ bool Recompiler::Recompile(const Function& fn) for (auto label : switchTable->second.labels) labels.emplace(label); } + + auto midAsmHook = config.midAsmHooks.find(addr); + if (midAsmHook != config.midAsmHooks.end()) + { + print("extern void {}(", midAsmHook->second.name); + for (auto& reg : midAsmHook->second.registers) + { + if (out.back() != '(') + out += ", "; + + switch (reg[0]) + { + case 'c': + if (reg == "ctr") + print("PPCRegister& ctr"); + else + print("PPCCRRegister& {}", reg); + break; + + case 'x': + print("PPCXERRegister& xer"); + break; + + case 'r': + print("PPCRegister& {}", reg); + break; + + case 'f': + if (reg == "fpscr") + print("PPCFPSCRRegister& fpscr"); + else + print("PPCRegister& {}", reg); + break; + + case 'v': + print("PPCVRegister& {}", reg); + break; + } + } + + println(");\n"); + } } auto symbol = image.symbols.find(fn.base); diff --git a/PowerRecomp/recompiler_config.cpp b/PowerRecomp/recompiler_config.cpp index 69485f4..05bb6ef 100644 --- a/PowerRecomp/recompiler_config.cpp +++ b/PowerRecomp/recompiler_config.cpp @@ -73,4 +73,20 @@ void RecompilerConfig::Load(const std::string_view& configFilePath) } } } + + if (auto midAsmHookArray = toml["midasm_hook"].as_array()) + { + for (auto& entry : *midAsmHookArray) + { + auto& table = *entry.as_table(); + + RecompilerMidAsmHook midAsmHook; + midAsmHook.name = *table["name"].value(); + for (auto& reg : *table["registers"].as_array()) + { + midAsmHook.registers.push_back(*reg.value()); + } + midAsmHooks.emplace(*table["address"].value(), std::move(midAsmHook)); + } + } } diff --git a/PowerRecomp/recompiler_config.h b/PowerRecomp/recompiler_config.h index 3a4b7a7..9bd238d 100644 --- a/PowerRecomp/recompiler_config.h +++ b/PowerRecomp/recompiler_config.h @@ -6,6 +6,12 @@ struct RecompilerSwitchTable std::vector labels; }; +struct RecompilerMidAsmHook +{ + std::string name; + std::vector registers; +}; + struct RecompilerConfig { std::string directoryPath; @@ -33,6 +39,7 @@ struct RecompilerConfig uint32_t setJmpAddress = 0; std::unordered_map functions; std::unordered_map invalidInstructions; + std::unordered_map midAsmHooks; void Load(const std::string_view& configFilePath); };