From 3a37b4503d23b624a3fd700de331609e13c7eb5a Mon Sep 17 00:00:00 2001 From: Mr-Wiseguy Date: Thu, 23 Jan 2025 02:48:48 -0500 Subject: [PATCH] Add manual patch symbols (syms.ld) to the output overlay file and relocs --- include/recompiler/context.h | 6 +++++ src/main.cpp | 45 +++++++++++++++++++++++++++++------- src/recompilation.cpp | 4 +--- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/include/recompiler/context.h b/include/recompiler/context.h index 1d3f2e4..0d0009b 100644 --- a/include/recompiler/context.h +++ b/include/recompiler/context.h @@ -565,6 +565,12 @@ namespace N64Recomp { void set_all_reference_sections_relocatable() { all_reference_sections_relocatable = true; } + + bool is_manual_patch_symbol(uint32_t vram) const { + // Zero-sized symbols between 0x8F000000 and 0x90000000 are manually specified symbols for use with patches. + // TODO make this configurable or come up with a more sensible solution for dealing with manual symbols for patches. + return vram >= 0x8F000000 && vram < 0x90000000; + } }; class Generator; diff --git a/src/main.cpp b/src/main.cpp index 6c56954..aa28864 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -866,13 +866,6 @@ int main(int argc, char** argv) { ); } - fmt::print(func_header_file, - "\n" - "#ifdef __cplusplus\n" - "}}\n" - "#endif\n" - ); - { std::ofstream overlay_file(config.output_func_path / "recomp_overlays.inl"); std::string section_load_table = "static SectionTableEntry section_table[] = {\n"; @@ -933,7 +926,7 @@ int main(int argc, char** argv) { fmt::print(overlay_file, "static RelocEntry {}[] = {{\n", section_relocs_array_name); for (const N64Recomp::Reloc& reloc : section_relocs) { - if (reloc.target_section != N64Recomp::SectionAbsolute) { + if (reloc.target_section != N64Recomp::SectionAbsolute || context.is_manual_patch_symbol(reloc.target_section_offset)) { uint32_t target_section_offset; if (reloc.target_section == N64Recomp::SectionEvent) { target_section_offset = reloc.symbol_index; @@ -1012,9 +1005,45 @@ int main(int argc, char** argv) { // Add a dummy element at the end to ensure the array has a valid length because C doesn't allow zero-size arrays. fmt::print(overlay_file, " NULL\n"); fmt::print(overlay_file, "}};\n"); + + // Collect manual patch symbols. + std::vector> manual_patch_syms{}; + + for (const auto& func : context.functions) { + if (func.words.empty() && context.is_manual_patch_symbol(func.vram)) { + manual_patch_syms.emplace_back(func.vram, func.name); + } + } + + // Sort the manual patch symbols by vram. + std::sort(manual_patch_syms.begin(), manual_patch_syms.end(), [](const auto& lhs, const auto& rhs) { + return lhs.first < rhs.first; + }); + + // Emit the manual patch symbols. + fmt::print(overlay_file, + "\n" + "static const ManualPatchSymbol manual_patch_symbols[] = {{\n" + ); + for (const auto& manual_patch_sym_entry : manual_patch_syms) { + fmt::print(overlay_file, " {{ 0x{:08X}, {} }},\n", manual_patch_sym_entry.first, manual_patch_sym_entry.second); + + fmt::print(func_header_file, + "void {}(uint8_t* rdram, recomp_context* ctx);\n", manual_patch_sym_entry.second); + } + // Add a dummy element at the end to ensure the array has a valid length because C doesn't allow zero-size arrays. + fmt::print(overlay_file, " {{ 0, NULL }}\n"); + fmt::print(overlay_file, "}};\n"); } } + fmt::print(func_header_file, + "\n" + "#ifdef __cplusplus\n" + "}}\n" + "#endif\n" + ); + if (!config.output_binary_path.empty()) { std::ofstream output_binary{config.output_binary_path, std::ios::binary}; output_binary.write(reinterpret_cast(context.rom.data()), context.rom.size()); diff --git a/src/recompilation.cpp b/src/recompilation.cpp index 5403ff1..ceb8496 100644 --- a/src/recompilation.cpp +++ b/src/recompilation.cpp @@ -46,9 +46,7 @@ JalResolutionResult resolve_jal(const N64Recomp::Context& context, size_t cur_se // Zero-sized symbol handling. unless there's only one matching target. if (target_func.words.empty()) { - // Allow zero-sized symbols between 0x8F000000 and 0x90000000 for use with patches. - // TODO make this configurable or come up with a more sensible solution for dealing with manual symbols for patches. - if (target_func.vram < 0x8F000000 || target_func.vram > 0x90000000) { + if (!context.is_manual_patch_symbol(target_func.vram)) { continue; } }