mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2025-05-22 03:14:59 +00:00
add renaming and re mode
This commit is contained in:
parent
2632d435b0
commit
0cc8edcf40
7 changed files with 79 additions and 9 deletions
|
@ -216,6 +216,9 @@ namespace N64Recomp {
|
|||
// List of symbols from events, which contains the names of events that this context provides.
|
||||
std::vector<EventSymbol> event_symbols;
|
||||
|
||||
// Causes functions to print their name to the console the first time they're called.
|
||||
bool re_mode;
|
||||
|
||||
// Imports sections and function symbols from a provided context into this context's reference sections and reference functions.
|
||||
bool import_reference_context(const Context& reference_context);
|
||||
// Reads a data symbol file and adds its contents into this context's reference data symbols.
|
||||
|
|
|
@ -93,7 +93,7 @@ std::vector<std::string> get_ignored_funcs(const toml::table* patches_data) {
|
|||
// Make room for all the ignored funcs in the array.
|
||||
ignored_funcs.reserve(ignored_funcs_array->size());
|
||||
|
||||
// Gather the stubs and place them into the array.
|
||||
// Gather the ignored and place them into the array.
|
||||
ignored_funcs_array->for_each([&ignored_funcs](auto&& el) {
|
||||
if constexpr (toml::is_string<decltype(el)>) {
|
||||
ignored_funcs.push_back(*el);
|
||||
|
@ -104,6 +104,29 @@ std::vector<std::string> get_ignored_funcs(const toml::table* patches_data) {
|
|||
return ignored_funcs;
|
||||
}
|
||||
|
||||
std::vector<std::string> get_renamed_funcs(const toml::table* patches_data) {
|
||||
std::vector<std::string> renamed_funcs{};
|
||||
|
||||
// Check if the renamed funcs array exists.
|
||||
const toml::node_view renamed_funcs_data = (*patches_data)["renamed"];
|
||||
|
||||
if (renamed_funcs_data.is_array()) {
|
||||
const toml::array* renamed_funcs_array = renamed_funcs_data.as_array();
|
||||
|
||||
// Make room for all the renamed funcs in the array.
|
||||
renamed_funcs.reserve(renamed_funcs_array->size());
|
||||
|
||||
// Gather the renamed and place them into the array.
|
||||
renamed_funcs_array->for_each([&renamed_funcs](auto&& el) {
|
||||
if constexpr (toml::is_string<decltype(el)>) {
|
||||
renamed_funcs.push_back(*el);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return renamed_funcs;
|
||||
}
|
||||
|
||||
std::vector<N64Recomp::FunctionSize> get_func_sizes(const toml::table* patches_data) {
|
||||
std::vector<N64Recomp::FunctionSize> func_sizes{};
|
||||
|
||||
|
@ -377,6 +400,9 @@ N64Recomp::Config::Config(const char* path) {
|
|||
// Ignored funcs array (optional)
|
||||
ignored_funcs = get_ignored_funcs(table);
|
||||
|
||||
// Renamed funcs array (optional)
|
||||
renamed_funcs = get_renamed_funcs(table);
|
||||
|
||||
// Single-instruction patches (optional)
|
||||
instruction_patches = get_instruction_patches(table);
|
||||
|
||||
|
@ -387,6 +413,18 @@ N64Recomp::Config::Config(const char* path) {
|
|||
function_hooks = get_function_hooks(table);
|
||||
}
|
||||
|
||||
// Use RE mode if enabled (optional)
|
||||
std::optional<bool> re_mode_opt = input_data["re_mode"].value<bool>();
|
||||
if (re_mode_opt.has_value()) {
|
||||
re_mode = re_mode_opt.value();
|
||||
if (re_mode) {
|
||||
recomp_include += "\n#include <stdio.h>\n#include <stdlib.h>";
|
||||
}
|
||||
}
|
||||
else {
|
||||
re_mode = false;
|
||||
}
|
||||
|
||||
// Function reference symbols file (optional)
|
||||
std::optional<std::string> func_reference_syms_file_opt = input_data["func_reference_syms_file"].value<std::string>();
|
||||
if (func_reference_syms_file_opt.has_value()) {
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace N64Recomp {
|
|||
bool single_file_output;
|
||||
bool use_absolute_symbols;
|
||||
bool unpaired_lo16_warnings;
|
||||
bool re_mode;
|
||||
bool allow_exports;
|
||||
bool strict_patch_mode;
|
||||
std::filesystem::path elf_path;
|
||||
|
@ -54,6 +55,7 @@ namespace N64Recomp {
|
|||
std::filesystem::path output_binary_path;
|
||||
std::vector<std::string> stubbed_funcs;
|
||||
std::vector<std::string> ignored_funcs;
|
||||
std::vector<std::string> renamed_funcs;
|
||||
std::vector<InstructionPatch> instruction_patches;
|
||||
std::vector<FunctionHook> function_hooks;
|
||||
std::vector<FunctionSize> manual_func_sizes;
|
||||
|
|
|
@ -60,7 +60,7 @@ bool read_symbols(N64Recomp::Context& context, const ELFIO::elfio& elf_file, ELF
|
|||
|
||||
if (section_index < context.sections.size()) {
|
||||
// Check if this symbol is the entrypoint
|
||||
if (elf_config.has_entrypoint && value == elf_config.entrypoint_address && type == ELFIO::STT_FUNC) {
|
||||
if (elf_config.has_entrypoint && (uint32_t) value == (uint32_t) elf_config.entrypoint_address && (type == ELFIO::STT_FUNC || type == ELFIO::STT_NOTYPE)) {
|
||||
if (found_entrypoint_func) {
|
||||
fmt::print(stderr, "Ambiguous entrypoint: {}\n", name);
|
||||
return false;
|
||||
|
@ -105,7 +105,7 @@ bool read_symbols(N64Recomp::Context& context, const ELFIO::elfio& elf_file, ELF
|
|||
auto section_offset = value - elf_file.sections[section_index]->get_address();
|
||||
const uint32_t* words = reinterpret_cast<const uint32_t*>(elf_file.sections[section_index]->get_data() + section_offset);
|
||||
uint32_t vram = static_cast<uint32_t>(value);
|
||||
uint32_t num_instructions = type == ELFIO::STT_FUNC ? size / 4 : 0;
|
||||
uint32_t num_instructions = (type == ELFIO::STT_FUNC || type == ELFIO::STT_NOTYPE) ? size / 4 : 0;
|
||||
uint32_t rom_address = static_cast<uint32_t>(section_offset + section.rom_addr);
|
||||
|
||||
section.function_addrs.push_back(vram);
|
||||
|
|
25
src/main.cpp
25
src/main.cpp
|
@ -273,10 +273,10 @@ int main(int argc, char** argv) {
|
|||
};
|
||||
|
||||
// TODO expose a way to dump the context from the command line.
|
||||
bool dumping_context = false;
|
||||
bool dumping_context = argc > 2;
|
||||
|
||||
if (argc != 2) {
|
||||
fmt::print("Usage: {} [config file]\n", argv[0]);
|
||||
if (argc > 3) {
|
||||
fmt::print("Usage: {} [config file] (should-dump)\n", argv[0]);
|
||||
std::exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -485,10 +485,27 @@ int main(int argc, char** argv) {
|
|||
// This helps prevent typos in the config file or functions renamed between versions from causing issues.
|
||||
exit_failure(fmt::format("Function {} is set as ignored in the config file but does not exist!", ignored_func));
|
||||
}
|
||||
// Mark the function as .
|
||||
// Mark the function as ignored.
|
||||
context.functions[func_find->second].ignored = true;
|
||||
}
|
||||
|
||||
// Rename any functions specified in the config file.
|
||||
for (const std::string& renamed_func : config.renamed_funcs) {
|
||||
// Check if the specified function exists.
|
||||
auto func_find = context.functions_by_name.find(renamed_func);
|
||||
if (func_find == context.functions_by_name.end()) {
|
||||
// Function doesn't exist, present an error to the user instead of silently failing to mark it as ignored.
|
||||
// This helps prevent typos in the config file or functions renamed between versions from causing issues.
|
||||
exit_failure(fmt::format("Function {} is set as renamed in the config file but does not exist!", renamed_func));
|
||||
}
|
||||
// Rename the function.
|
||||
N64Recomp::Function* func = &context.functions[func_find->second];
|
||||
func->name = func->name + "_recomp";
|
||||
}
|
||||
|
||||
// Propogate the re_mode parameter.
|
||||
context.re_mode = config.re_mode;
|
||||
|
||||
// Apply any single-instruction patches.
|
||||
for (const N64Recomp::InstructionPatch& patch : config.instruction_patches) {
|
||||
// Check if the specified function exists.
|
||||
|
|
|
@ -745,6 +745,16 @@ bool N64Recomp::recompile_function(const N64Recomp::Context& context, const N64R
|
|||
" int c1cs = 0;\n", // cop1 conditional signal
|
||||
func.name);
|
||||
|
||||
if (context.re_mode) {
|
||||
fmt::print(output_file,
|
||||
" static int {0}_was_called = 0;\n"
|
||||
" if ({0}_was_called == 0) {{\n"
|
||||
" fprintf(stderr, \"new function: {0}\\n\");\n"
|
||||
" {0}_was_called = 1;\n"
|
||||
" }}\n",
|
||||
func.name);
|
||||
}
|
||||
|
||||
// Skip analysis and recompilation of this function is stubbed.
|
||||
if (!func.stubbed) {
|
||||
// Use a set to sort and deduplicate labels
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue