From c1a6dc93bfa5977de0ea256562058be4f1b73353 Mon Sep 17 00:00:00 2001 From: Wiseguy <68165316+Mr-Wiseguy@users.noreply.github.com> Date: Sat, 19 Jul 2025 03:39:41 -0400 Subject: [PATCH] Implement fixed address and globally loaded sections in mods, respect section index in mod self-section relocs (#150) --- include/recompiler/context.h | 2 ++ src/mod_symbols.cpp | 19 ++++++++++++++++++- src/recompilation.cpp | 10 ++++++++-- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/include/recompiler/context.h b/include/recompiler/context.h index a3f0ac6..7b8c1f7 100644 --- a/include/recompiler/context.h +++ b/include/recompiler/context.h @@ -104,6 +104,8 @@ namespace N64Recomp { bool executable = false; bool relocatable = false; // TODO is this needed? relocs being non-empty should be an equivalent check. bool has_mips32_relocs = false; + bool fixed_address = false; // Only used in mods, indicates that the section shouldn't be relocated or placed into mod memory. + bool globally_loaded = false; // Only used in mods, indicates that the section's functions should be globally loaded. Does not actually load the section's contents into ram. std::optional got_ram_addr = std::nullopt; }; diff --git a/src/mod_symbols.cpp b/src/mod_symbols.cpp index ab80b04..c65b08e 100644 --- a/src/mod_symbols.cpp +++ b/src/mod_symbols.cpp @@ -20,6 +20,11 @@ struct FileSubHeaderV1 { uint32_t string_data_size; }; +enum class SectionFlags : uint32_t { + FixedAddress = 1 << 0, + GloballyLoaded = 1 << 1, +}; + struct SectionHeaderV1 { uint32_t flags; uint32_t file_offset; @@ -172,10 +177,22 @@ bool parse_v1(std::span data, const std::unordered_mapbss_size; cur_section.name = "mod_section_" + std::to_string(section_index); cur_section.relocatable = true; + cur_section.fixed_address = (section_header->flags & static_cast(SectionFlags::FixedAddress)) != 0; + cur_section.globally_loaded = (section_header->flags & static_cast(SectionFlags::GloballyLoaded)) != 0; + + if (cur_section.fixed_address && !cur_section.globally_loaded) { + printf("Fixed address sections that aren't globally loaded aren't currently supported\n"); + return false; + } + + if (cur_section.globally_loaded && !cur_section.fixed_address) { + printf("A globally loaded section must have a fixed address\n"); + return false; + } + uint32_t num_funcs = section_header->num_funcs; uint32_t num_relocs = section_header->num_relocs; - const FuncV1* funcs = reinterpret_data(data, offset, num_funcs); if (funcs == nullptr) { printf("Failed to read funcs (count: %d)\n", num_funcs); diff --git a/src/recompilation.cpp b/src/recompilation.cpp index 5cfe8e5..a54b85f 100644 --- a/src/recompilation.cpp +++ b/src/recompilation.cpp @@ -152,6 +152,7 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con } N64Recomp::RelocType reloc_type = N64Recomp::RelocType::R_MIPS_NONE; + bool has_reloc = false; uint32_t reloc_section = 0; uint32_t reloc_target_section_offset = 0; size_t reloc_reference_symbol = (size_t)-1; @@ -162,6 +163,7 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con // Check if this instruction has a reloc. if (section.relocs.size() > 0 && section.relocs[reloc_index].address == instr_vram) { + has_reloc = true; // Get the reloc data for this instruction const auto& reloc = section.relocs[reloc_index]; reloc_section = reloc.target_section; @@ -257,7 +259,7 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con return true; }; - auto print_func_call_by_address = [&generator, reloc_target_section_offset, reloc_section, reloc_reference_symbol, reloc_type, &context, &func, &static_funcs_out, &needs_link_branch, &print_indent, &process_delay_slot, &print_link_branch] + auto print_func_call_by_address = [&generator, reloc_target_section_offset, has_reloc, reloc_section, reloc_reference_symbol, reloc_type, &context, &func, &static_funcs_out, &needs_link_branch, &print_indent, &process_delay_slot, &print_link_branch] (uint32_t target_func_vram, bool tail_call = false, bool indent = false) { bool call_by_lookup = false; @@ -294,7 +296,11 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con } } else { - JalResolutionResult jal_result = resolve_jal(context, func.section_index, target_func_vram, matched_func_index); + uint32_t target_section = func.section_index; + if (has_reloc) { + target_section = reloc_section; + } + JalResolutionResult jal_result = resolve_jal(context, target_section, target_func_vram, matched_func_index); switch (jal_result) { case JalResolutionResult::NoMatch: