| 159 | }; |
| 160 | |
| 161 | void dump_context(const N64Recomp::Context& context, const std::unordered_map<uint16_t, std::vector<N64Recomp::DataSymbol>>& data_syms, const std::filesystem::path& func_path, const std::filesystem::path& data_path) { |
| 162 | std::ofstream func_context_file {func_path}; |
| 163 | std::ofstream data_context_file {data_path}; |
| 164 | |
| 165 | fmt::print(func_context_file, "# Autogenerated from an ELF via N64Recomp\n"); |
| 166 | fmt::print(data_context_file, "# Autogenerated from an ELF via N64Recomp\n"); |
| 167 | |
| 168 | auto print_section = [](std::ofstream& output_file, const std::string& name, uint32_t rom_addr, uint32_t ram_addr, uint32_t size) { |
| 169 | if (rom_addr == (uint32_t)-1) { |
| 170 | fmt::print(output_file, |
| 171 | "[[section]]\n" |
| 172 | "name = \"{}\"\n" |
| 173 | "vram = 0x{:08X}\n" |
| 174 | "size = 0x{:X}\n" |
| 175 | "\n", |
| 176 | name, ram_addr, size); |
| 177 | } |
| 178 | else { |
| 179 | fmt::print(output_file, |
| 180 | "[[section]]\n" |
| 181 | "name = \"{}\"\n" |
| 182 | "rom = 0x{:08X}\n" |
| 183 | "vram = 0x{:08X}\n" |
| 184 | "size = 0x{:X}\n" |
| 185 | "\n", |
| 186 | name, rom_addr, ram_addr, size); |
| 187 | } |
| 188 | }; |
| 189 | |
| 190 | for (size_t section_index = 0; section_index < context.sections.size(); section_index++) { |
| 191 | const N64Recomp::Section& section = context.sections[section_index]; |
| 192 | const std::vector<size_t>& section_funcs = context.section_functions[section_index]; |
| 193 | if (!section_funcs.empty()) { |
| 194 | print_section(func_context_file, section.name, section.rom_addr, section.ram_addr, section.size); |
| 195 | |
| 196 | // Dump relocs into the function context file. |
| 197 | if (!section.relocs.empty()) { |
| 198 | std::vector<std::reference_wrapper<const N64Recomp::Reloc>> sorted_relocs; |
| 199 | for (const N64Recomp::Reloc& reloc : section.relocs) { |
| 200 | if (reloc.target_section == section_index || reloc.target_section == section.bss_section_index) { |
| 201 | // TODO allow emitting MIPS32 relocs for specific sections via a toml option for TLB mapping support. |
| 202 | if (reloc.type == N64Recomp::RelocType::R_MIPS_HI16 || reloc.type == N64Recomp::RelocType::R_MIPS_LO16 || reloc.type == N64Recomp::RelocType::R_MIPS_26) { |
| 203 | sorted_relocs.push_back(reloc); |
| 204 | } |
| 205 | } |
| 206 | } |
| 207 | std::sort(sorted_relocs.begin(), sorted_relocs.end(), [](auto& a, auto& b) { |
| 208 | return a.get().address < b.get().address; |
| 209 | }); |
| 210 | |
| 211 | fmt::print(func_context_file, "relocs = [\n"); |
| 212 | for (const N64Recomp::Reloc& reloc : sorted_relocs) { |
| 213 | fmt::print(func_context_file, " {{ type = \"{}\", vram = 0x{:08X}, target_vram = 0x{:08X} }},\n", |
| 214 | reloc_names[static_cast<int>(reloc.type)], reloc.address, reloc.target_section_offset + section.ram_addr); |
| 215 | } |
| 216 | fmt::print(func_context_file, "]\n\n"); |
| 217 | } |
| 218 | |