mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2025-05-29 23:03:16 +00:00
Implement nrm filename toml input, renaming list, trace mode, and context dumping flag (#111)
* implement nrm filename toml input * change name of mod toml setting to 'mod_filename' * add renaming and re mode * fix --dump-context arg, fix entrypoint detection * refactor re_mode to function_trace_mode * adjust trace mode to use a general TRACE_ENTRY() macro * fix some renaming and trace mode comments, revert no toml entrypoint code, add TODO to broken block * fix arg2 check and usage string
This commit is contained in:
parent
d33d381617
commit
17438755a1
9 changed files with 95 additions and 12 deletions
|
@ -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 trace mode if enabled (optional)
|
||||
std::optional<bool> trace_mode_opt = input_data["trace_mode"].value<bool>();
|
||||
if (trace_mode_opt.has_value()) {
|
||||
trace_mode = trace_mode_opt.value();
|
||||
if (trace_mode) {
|
||||
recomp_include += "\n#include \"trace.h\"";
|
||||
}
|
||||
}
|
||||
else {
|
||||
trace_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 trace_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;
|
||||
|
|
|
@ -58,8 +58,9 @@ bool read_symbols(N64Recomp::Context& context, const ELFIO::elfio& elf_file, ELF
|
|||
continue;
|
||||
}
|
||||
|
||||
if (section_index < context.sections.size()) {
|
||||
if (section_index < context.sections.size()) {
|
||||
// Check if this symbol is the entrypoint
|
||||
// TODO this never fires, the check is broken due to signedness
|
||||
if (elf_config.has_entrypoint && value == elf_config.entrypoint_address && type == ELFIO::STT_FUNC) {
|
||||
if (found_entrypoint_func) {
|
||||
fmt::print(stderr, "Ambiguous entrypoint: {}\n", name);
|
||||
|
|
35
src/main.cpp
35
src/main.cpp
|
@ -272,12 +272,18 @@ int main(int argc, char** argv) {
|
|||
std::exit(EXIT_FAILURE);
|
||||
};
|
||||
|
||||
// TODO expose a way to dump the context from the command line.
|
||||
bool dumping_context = false;
|
||||
bool dumping_context;
|
||||
|
||||
if (argc != 2) {
|
||||
fmt::print("Usage: {} [config file]\n", argv[0]);
|
||||
std::exit(EXIT_SUCCESS);
|
||||
if (argc >= 3) {
|
||||
std::string arg2 = argv[2];
|
||||
if (arg2 == "--dump-context") {
|
||||
dumping_context = true;
|
||||
} else {
|
||||
fmt::print("Usage: {} <config file> [--dump-context]\n", argv[0]);
|
||||
std::exit(EXIT_SUCCESS);
|
||||
}
|
||||
} else {
|
||||
dumping_context = false;
|
||||
}
|
||||
|
||||
const char* config_path = argv[1];
|
||||
|
@ -485,10 +491,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 rename it.
|
||||
// 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 trace mode parameter.
|
||||
context.trace_mode = config.trace_mode;
|
||||
|
||||
// Apply any single-instruction patches.
|
||||
for (const N64Recomp::InstructionPatch& patch : config.instruction_patches) {
|
||||
// Check if the specified function exists.
|
||||
|
|
|
@ -745,6 +745,12 @@ bool N64Recomp::recompile_function(const N64Recomp::Context& context, const N64R
|
|||
" int c1cs = 0;\n", // cop1 conditional signal
|
||||
func.name);
|
||||
|
||||
if (context.trace_mode) {
|
||||
fmt::print(output_file,
|
||||
" TRACE_ENTRY();",
|
||||
func.name);
|
||||
}
|
||||
|
||||
// Skip analysis and recompilation of this function is stubbed.
|
||||
if (!func.stubbed) {
|
||||
// Use a set to sort and deduplicate labels
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "n64recomp.h"
|
||||
|
||||
const std::unordered_set<std::string> N64Recomp::reimplemented_funcs{
|
||||
const std::unordered_set<std::string> N64Recomp::reimplemented_funcs {
|
||||
// OS initialize functions
|
||||
"__osInitialize_common",
|
||||
"osInitialize",
|
||||
|
@ -557,7 +557,7 @@ const std::unordered_set<std::string> N64Recomp::ignored_funcs {
|
|||
"kdebugserver",
|
||||
};
|
||||
|
||||
const std::unordered_set<std::string> N64Recomp::renamed_funcs{
|
||||
const std::unordered_set<std::string> N64Recomp::renamed_funcs {
|
||||
// Math
|
||||
"sincosf",
|
||||
"sinf",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue