Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
#include <filesystem>
|
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <span>
|
|
|
|
|
|
Implement live recompiler (#114)
This commit implements the "live recompiler", which is another backend for the recompiler that generates platform-specific assembly at runtime. This is still static recompilation as opposed to dynamic recompilation, as it still requires information about the binary to recompile and leverages the same static analysis that the C recompiler uses. However, similarly to dynamic recompilation it's aimed at recompiling binaries at runtime, mainly for modding purposes.
The live recompiler leverages a library called sljit to generate platform-specific code. This library provides an API that's implemented on several platforms, including the main targets of this component: x86_64 and ARM64.
Performance is expected to be slower than the C recompiler, but should still be plenty fast enough for running large amounts of recompiled code without an issue. Considering these ROMs can often be run through an interpreter and still hit their full speed, performance should not be a concern for running native code even if it's less optimal than the C recompiler's codegen.
As mentioned earlier, the main use of the live recompiler will be for loading mods in the N64Recomp runtime. This makes it so that modders don't need to ship platform-specific binaries for their mods, and allows fixing bugs with recompilation down the line without requiring modders to update their binaries.
This PR also includes a utility for testing the live recompiler. It accepts binaries in a custom format which contain the instructions, input data, and target data. Documentation for the test format as well as most of the tests that were used to validate the live recompiler can be found here. The few remaining tests were hacked together binaries that I put together very hastily, so they need to be cleaned up and will probably be uploaded at a later date. The only test in that suite that doesn't currently succeed is the div test, due to unknown behavior when the two operands aren't properly sign extended to 64 bits. This has no bearing on practical usage, since the inputs will always be sign extended as expected.
2024-12-31 16:11:40 -05:00
|
|
|
#include "recompiler/context.h"
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
#include "rabbitizer.hpp"
|
|
|
|
|
|
|
|
|
|
static std::vector<uint8_t> read_file(const std::filesystem::path& path, bool& found) {
|
|
|
|
|
std::vector<uint8_t> ret;
|
|
|
|
|
found = false;
|
|
|
|
|
|
|
|
|
|
std::ifstream file{ path, std::ios::binary};
|
|
|
|
|
|
|
|
|
|
if (file.good()) {
|
|
|
|
|
file.seekg(0, std::ios::end);
|
|
|
|
|
ret.resize(file.tellg());
|
|
|
|
|
file.seekg(0, std::ios::beg);
|
|
|
|
|
|
|
|
|
|
file.read(reinterpret_cast<char*>(ret.data()), ret.size());
|
|
|
|
|
found = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, const char** argv) {
|
2024-09-09 22:49:57 -04:00
|
|
|
if (argc != 5) {
|
|
|
|
|
printf("Usage: %s [mod symbol file] [mod binary file] [recomp symbols file] [output C file]\n", argv[0]);
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
return EXIT_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
bool found;
|
|
|
|
|
std::vector<uint8_t> symbol_data = read_file(argv[1], found);
|
|
|
|
|
if (!found) {
|
|
|
|
|
fprintf(stderr, "Failed to open symbol file\n");
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<uint8_t> rom_data = read_file(argv[2], found);
|
|
|
|
|
if (!found) {
|
|
|
|
|
fprintf(stderr, "Failed to open ROM\n");
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::span<const char> symbol_data_span { reinterpret_cast<const char*>(symbol_data.data()), symbol_data.size() };
|
|
|
|
|
|
|
|
|
|
std::vector<uint8_t> dummy_rom{};
|
|
|
|
|
N64Recomp::Context reference_context{};
|
2024-09-09 22:49:57 -04:00
|
|
|
if (!N64Recomp::Context::from_symbol_file(argv[3], std::move(dummy_rom), reference_context, false)) {
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
printf("Failed to load provided function reference symbol file\n");
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//for (const std::filesystem::path& cur_data_sym_path : data_reference_syms_file_paths) {
|
|
|
|
|
// if (!reference_context.read_data_reference_syms(cur_data_sym_path)) {
|
|
|
|
|
// printf("Failed to load provided data reference symbol file\n");
|
|
|
|
|
// return EXIT_FAILURE;
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
std::unordered_map<uint32_t, uint16_t> sections_by_vrom{};
|
|
|
|
|
for (uint16_t section_index = 0; section_index < reference_context.sections.size(); section_index++) {
|
|
|
|
|
sections_by_vrom[reference_context.sections[section_index].rom_addr] = section_index;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
N64Recomp::Context mod_context;
|
|
|
|
|
|
2024-09-09 22:49:57 -04:00
|
|
|
N64Recomp::ModSymbolsError error = N64Recomp::parse_mod_symbols(symbol_data_span, rom_data, sections_by_vrom, mod_context);
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
if (error != N64Recomp::ModSymbolsError::Good) {
|
|
|
|
|
fprintf(stderr, "Error parsing mod symbols: %d\n", (int)error);
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-09 22:49:57 -04:00
|
|
|
mod_context.import_reference_context(reference_context);
|
|
|
|
|
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
// Populate R_MIPS_26 reloc symbol indices. Start by building a map of vram address to matching reference symbols.
|
|
|
|
|
std::unordered_map<uint32_t, std::vector<size_t>> reference_symbols_by_vram{};
|
|
|
|
|
for (size_t reference_symbol_index = 0; reference_symbol_index < mod_context.num_regular_reference_symbols(); reference_symbol_index++) {
|
|
|
|
|
const auto& sym = mod_context.get_regular_reference_symbol(reference_symbol_index);
|
|
|
|
|
uint16_t section_index = sym.section_index;
|
|
|
|
|
if (section_index != N64Recomp::SectionAbsolute) {
|
|
|
|
|
uint32_t section_vram = mod_context.get_reference_section_vram(section_index);
|
|
|
|
|
reference_symbols_by_vram[section_vram + sym.section_offset].push_back(reference_symbol_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Use the mapping to populate the symbol index for every R_MIPS_26 reference symbol reloc.
|
|
|
|
|
for (auto& section : mod_context.sections) {
|
|
|
|
|
for (auto& reloc : section.relocs) {
|
|
|
|
|
if (reloc.type == N64Recomp::RelocType::R_MIPS_26 && reloc.reference_symbol) {
|
|
|
|
|
if (mod_context.is_regular_reference_section(reloc.target_section)) {
|
|
|
|
|
uint32_t section_vram = mod_context.get_reference_section_vram(reloc.target_section);
|
|
|
|
|
uint32_t target_vram = section_vram + reloc.target_section_offset;
|
|
|
|
|
|
|
|
|
|
auto find_funcs_it = reference_symbols_by_vram.find(target_vram);
|
|
|
|
|
bool found = false;
|
|
|
|
|
if (find_funcs_it != reference_symbols_by_vram.end()) {
|
|
|
|
|
for (size_t symbol_index : find_funcs_it->second) {
|
|
|
|
|
const auto& cur_symbol = mod_context.get_reference_symbol(reloc.target_section, symbol_index);
|
|
|
|
|
if (cur_symbol.section_index == reloc.target_section) {
|
|
|
|
|
reloc.symbol_index = symbol_index;
|
|
|
|
|
found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!found) {
|
|
|
|
|
fprintf(stderr, "Failed to find R_MIPS_26 relocation target in section %d with vram 0x%08X\n", reloc.target_section, target_vram);
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mod_context.rom = std::move(rom_data);
|
|
|
|
|
|
|
|
|
|
std::vector<std::vector<uint32_t>> static_funcs_by_section{};
|
|
|
|
|
static_funcs_by_section.resize(mod_context.sections.size());
|
|
|
|
|
|
2024-09-12 18:54:08 -04:00
|
|
|
const char* output_file_path = argv[4];
|
|
|
|
|
std::ofstream output_file { output_file_path };
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
|
|
|
|
|
RabbitizerConfig_Cfg.pseudos.pseudoMove = false;
|
|
|
|
|
RabbitizerConfig_Cfg.pseudos.pseudoBeqz = false;
|
|
|
|
|
RabbitizerConfig_Cfg.pseudos.pseudoBnez = false;
|
|
|
|
|
RabbitizerConfig_Cfg.pseudos.pseudoNot = false;
|
|
|
|
|
RabbitizerConfig_Cfg.pseudos.pseudoBal = false;
|
|
|
|
|
|
|
|
|
|
output_file << "#include \"mod_recomp.h\"\n\n";
|
|
|
|
|
|
2024-09-09 22:49:57 -04:00
|
|
|
// Write the API version.
|
|
|
|
|
output_file << "RECOMP_EXPORT uint32_t recomp_api_version = 1;\n\n";
|
|
|
|
|
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
output_file << "// Values populated by the runtime:\n\n";
|
|
|
|
|
|
|
|
|
|
// Write import function pointer array and defines (i.e. `#define testmod_inner_import imported_funcs[0]`)
|
|
|
|
|
output_file << "// Array of pointers to imported functions with defines to alias their names.\n";
|
|
|
|
|
size_t num_imports = mod_context.import_symbols.size();
|
|
|
|
|
for (size_t import_index = 0; import_index < num_imports; import_index++) {
|
|
|
|
|
const auto& import = mod_context.import_symbols[import_index];
|
|
|
|
|
output_file << "#define " << import.base.name << " imported_funcs[" << import_index << "]\n";
|
|
|
|
|
}
|
2024-09-09 22:49:57 -04:00
|
|
|
|
|
|
|
|
output_file << "RECOMP_EXPORT recomp_func_t* imported_funcs[" << std::max(size_t{1}, num_imports) << "] = {0};\n";
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
output_file << "\n";
|
|
|
|
|
|
|
|
|
|
// Use reloc list to write reference symbol function pointer array and defines (i.e. `#define func_80102468 reference_symbol_funcs[0]`)
|
|
|
|
|
output_file << "// Array of pointers to functions from the original ROM with defines to alias their names.\n";
|
2024-09-12 18:54:08 -04:00
|
|
|
std::unordered_set<std::string> written_reference_symbols{};
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
size_t num_reference_symbols = 0;
|
|
|
|
|
for (const auto& section : mod_context.sections) {
|
|
|
|
|
for (const auto& reloc : section.relocs) {
|
|
|
|
|
if (reloc.type == N64Recomp::RelocType::R_MIPS_26 && reloc.reference_symbol && mod_context.is_regular_reference_section(reloc.target_section)) {
|
|
|
|
|
const auto& sym = mod_context.get_reference_symbol(reloc.target_section, reloc.symbol_index);
|
2024-09-12 18:54:08 -04:00
|
|
|
|
|
|
|
|
// Prevent writing multiple of the same define. This means there are duplicate symbols in the array if a function is called more than once,
|
|
|
|
|
// but only the first of each set of duplicates is referenced. This is acceptable, since offline mod recompilation is mainly meant for debug purposes.
|
|
|
|
|
if (!written_reference_symbols.contains(sym.name)) {
|
|
|
|
|
output_file << "#define " << sym.name << " reference_symbol_funcs[" << num_reference_symbols << "]\n";
|
|
|
|
|
written_reference_symbols.emplace(sym.name);
|
|
|
|
|
}
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
num_reference_symbols++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-09 22:49:57 -04:00
|
|
|
// C doesn't allow 0-sized arrays, so always add at least one member to all arrays. The actual size will be pulled from the mod symbols.
|
|
|
|
|
output_file << "RECOMP_EXPORT recomp_func_t* reference_symbol_funcs[" << std::max(size_t{1},num_reference_symbols) << "] = {0};\n\n";
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
|
|
|
|
|
// Write provided event array (maps internal event indices to global ones).
|
2024-09-09 22:49:57 -04:00
|
|
|
output_file << "// Base global event index for this mod's events.\n";
|
|
|
|
|
output_file << "RECOMP_EXPORT uint32_t base_event_index;\n\n";
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
|
|
|
|
|
// Write the event trigger function pointer.
|
|
|
|
|
output_file << "// Pointer to the runtime function for triggering events.\n";
|
|
|
|
|
output_file << "RECOMP_EXPORT void (*recomp_trigger_event)(uint8_t* rdram, recomp_context* ctx, uint32_t) = NULL;\n\n";
|
|
|
|
|
|
2024-09-12 18:54:08 -04:00
|
|
|
// Write the get_function pointer.
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
output_file << "// Pointer to the runtime function for looking up functions from vram address.\n";
|
|
|
|
|
output_file << "RECOMP_EXPORT recomp_func_t* (*get_function)(int32_t vram) = NULL;\n\n";
|
|
|
|
|
|
2024-09-12 18:54:08 -04:00
|
|
|
// Write the cop0_status_write pointer.
|
|
|
|
|
output_file << "// Pointer to the runtime function for performing a cop0 status register write.\n";
|
|
|
|
|
output_file << "RECOMP_EXPORT void (*cop0_status_write)(recomp_context* ctx, gpr value) = NULL;\n\n";
|
|
|
|
|
|
|
|
|
|
// Write the cop0_status_read pointer.
|
|
|
|
|
output_file << "// Pointer to the runtime function for performing a cop0 status register read.\n";
|
|
|
|
|
output_file << "RECOMP_EXPORT gpr (*cop0_status_read)(recomp_context* ctx) = NULL;\n\n";
|
|
|
|
|
|
|
|
|
|
// Write the switch_error pointer.
|
|
|
|
|
output_file << "// Pointer to the runtime function for reporting switch case errors.\n";
|
|
|
|
|
output_file << "RECOMP_EXPORT void (*switch_error)(const char* func, uint32_t vram, uint32_t jtbl) = NULL;\n\n";
|
|
|
|
|
|
|
|
|
|
// Write the do_break pointer.
|
|
|
|
|
output_file << "// Pointer to the runtime function for handling the break instruction.\n";
|
|
|
|
|
output_file << "RECOMP_EXPORT void (*do_break)(uint32_t vram) = NULL;\n\n";
|
|
|
|
|
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
// Write the section_addresses pointer.
|
|
|
|
|
output_file << "// Pointer to the runtime's array of loaded section addresses for the base ROM.\n";
|
|
|
|
|
output_file << "RECOMP_EXPORT int32_t* reference_section_addresses = NULL;\n\n";
|
|
|
|
|
|
|
|
|
|
// Write the local section addresses pointer array.
|
|
|
|
|
size_t num_sections = mod_context.sections.size();
|
|
|
|
|
output_file << "// Array of this mod's loaded section addresses.\n";
|
2024-09-09 22:49:57 -04:00
|
|
|
output_file << "RECOMP_EXPORT int32_t section_addresses[" << std::max(size_t{1}, num_sections) << "] = {0};\n\n";
|
|
|
|
|
|
|
|
|
|
// Create a set of the export indices to avoid renaming them.
|
|
|
|
|
std::unordered_set<size_t> export_indices{mod_context.exported_funcs.begin(), mod_context.exported_funcs.end()};
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
|
2024-09-12 18:54:08 -04:00
|
|
|
// Name all the functions in a first pass so function calls emitted in the second are correct. Also emit function prototypes.
|
|
|
|
|
output_file << "// Function prototypes.\n";
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
for (size_t func_index = 0; func_index < mod_context.functions.size(); func_index++) {
|
|
|
|
|
auto& func = mod_context.functions[func_index];
|
2024-09-12 18:54:08 -04:00
|
|
|
// Don't rename exports since they already have a name from the mod symbol file.
|
2024-09-09 22:49:57 -04:00
|
|
|
if (!export_indices.contains(func_index)) {
|
|
|
|
|
func.name = "mod_func_" + std::to_string(func_index);
|
|
|
|
|
}
|
2024-09-12 18:54:08 -04:00
|
|
|
output_file << "RECOMP_FUNC void " << func.name << "(uint8_t* rdram, recomp_context* ctx);\n";
|
|
|
|
|
}
|
|
|
|
|
output_file << "\n";
|
|
|
|
|
|
|
|
|
|
// Perform a second pass for recompiling all the functions.
|
|
|
|
|
for (size_t func_index = 0; func_index < mod_context.functions.size(); func_index++) {
|
Implement live recompiler (#114)
This commit implements the "live recompiler", which is another backend for the recompiler that generates platform-specific assembly at runtime. This is still static recompilation as opposed to dynamic recompilation, as it still requires information about the binary to recompile and leverages the same static analysis that the C recompiler uses. However, similarly to dynamic recompilation it's aimed at recompiling binaries at runtime, mainly for modding purposes.
The live recompiler leverages a library called sljit to generate platform-specific code. This library provides an API that's implemented on several platforms, including the main targets of this component: x86_64 and ARM64.
Performance is expected to be slower than the C recompiler, but should still be plenty fast enough for running large amounts of recompiled code without an issue. Considering these ROMs can often be run through an interpreter and still hit their full speed, performance should not be a concern for running native code even if it's less optimal than the C recompiler's codegen.
As mentioned earlier, the main use of the live recompiler will be for loading mods in the N64Recomp runtime. This makes it so that modders don't need to ship platform-specific binaries for their mods, and allows fixing bugs with recompilation down the line without requiring modders to update their binaries.
This PR also includes a utility for testing the live recompiler. It accepts binaries in a custom format which contain the instructions, input data, and target data. Documentation for the test format as well as most of the tests that were used to validate the live recompiler can be found here. The few remaining tests were hacked together binaries that I put together very hastily, so they need to be cleaned up and will probably be uploaded at a later date. The only test in that suite that doesn't currently succeed is the div test, due to unknown behavior when the two operands aren't properly sign extended to 64 bits. This has no bearing on practical usage, since the inputs will always be sign extended as expected.
2024-12-31 16:11:40 -05:00
|
|
|
if (!N64Recomp::recompile_function(mod_context, func_index, output_file, static_funcs_by_section, true)) {
|
2024-09-12 18:54:08 -04:00
|
|
|
output_file.close();
|
|
|
|
|
std::error_code ec;
|
|
|
|
|
std::filesystem::remove(output_file_path, ec);
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
}
|
Modding Support PR 1 (Instruction tables, modding support, mod symbol format, library conversion) (#89)
* Initial implementation of binary operation table
* Initial implementation of unary operation table
* More binary op types, moved binary expression string generation into separate function
* Added and implemented conditional branch instruction table
* Fixed likely swap on bgezal, fixed extra indent branch close and missing
indent on branch statement
* Add operands for other uses of float registers
* Added CHECK_FR generation to binary operation processing, moved float comparison instructions to binary op table
* Finished moving float arithmetic instructions to operation tables
* Added store instruction operation table
* Created Generator interface, separated operation types and tables and C generation code into new files
* Fix mov.d using the wrong input operand
* Move recompiler core logic into a core library and make the existing CLI consume the core library
* Removed unnecessary config input to recompilation functions
* Moved parts of recomp_port.h into new internal headers in src folder
* Changed recomp port naming to N64Recomp
* Remove some unused code and document which Context fields are actually required for recompilation
* Implement mod symbol parsing
* Restructure mod symbols to make replacements global instead of per-section
* Refactor elf parsing into static Context method for reusability
* Move elf parsing into a separate library
* WIP elf to mod tool, currently working without relocations or API exports/imports
* Make mod tool emit relocs and patch binary for non-relocatable symbol references as needed
* Implemented writing import and exports in the mod tool
* Add dependencies to the mod symbol format, finish exporting and importing of mod symbols
* Add first pass offline mod recompiler (generates C from mods that can be compiled and linked into a dynamic library)
* Add strict mode and ability to generate exports for normal recompilation (for patches)
* Move mod context fields into base context, move import symbols into separate vector, misc cleanup
* Some cleanup by making some Context members private
* Add events (from dependencies and exported) and callbacks to the mod symbol format and add support to them in elf parsing
* Add runtime-driven fields to offline mod recompiler, fix event symbol relocs using the wrong section in the mod tool
* Move file header writing outside of function recompilation
* Allow cross-section relocations, encode exact target section in mod relocations, add way to tag reference symbol relocations
* Add local symbol addresses array to offline mod recompiler output and rename original one to reference section addresses
* Add more comments to the offline mod recompiler's output
* Fix handling of section load addresses to match objcopy behavior, added event parsing to dependency tomls, minor cleanup
* Fixed incorrect size used for finding section segments
* Add missing includes for libstdc++
* Rework callbacks and imports to use the section name for identifying the dependency instead of relying on per-dependency tomls
2024-08-26 23:06:34 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
|
}
|