Implemented parsing of instruction patches in config file

This commit is contained in:
Mr-Wiseguy 2023-03-24 19:22:30 -04:00
parent 7df3e28c76
commit 9949813018
2 changed files with 50 additions and 6 deletions

View file

@ -33,6 +33,12 @@ namespace RecompPort {
// Mapping of function name to argument types // Mapping of function name to argument types
using DeclaredFunctionMap = std::unordered_map<std::string, std::vector<FunctionArgType>>; using DeclaredFunctionMap = std::unordered_map<std::string, std::vector<FunctionArgType>>;
struct InstructionPatch {
std::string func_name;
int32_t vram;
uint32_t value;
};
struct Config { struct Config {
int32_t entrypoint; int32_t entrypoint;
std::filesystem::path elf_path; std::filesystem::path elf_path;
@ -40,6 +46,7 @@ namespace RecompPort {
std::filesystem::path relocatable_sections_path; std::filesystem::path relocatable_sections_path;
std::vector<std::string> stubbed_funcs; std::vector<std::string> stubbed_funcs;
DeclaredFunctionMap declared_funcs; DeclaredFunctionMap declared_funcs;
std::vector<InstructionPatch> instruction_patches;
Config(const char* path); Config(const char* path);
bool good() { return !bad; } bool good() { return !bad; }

View file

@ -4,13 +4,15 @@
#include "fmt/format.h" #include "fmt/format.h"
#include "recomp_port.h" #include "recomp_port.h"
void get_stubbed_funcs(std::vector<std::string>& stubbed_funcs, const toml::value& patches_data) { std::vector<std::string> get_stubbed_funcs(const toml::value& patches_data) {
std::vector<std::string> stubbed_funcs{};
// Check if the stubs array exists. // Check if the stubs array exists.
const auto& stubs_data = toml::find_or<toml::value>(patches_data, "stubs", toml::value{}); const auto& stubs_data = toml::find_or<toml::value>(patches_data, "stubs", toml::value{});
if (stubs_data.type() == toml::value_t::empty) { if (stubs_data.type() == toml::value_t::empty) {
// No stubs, nothing to do here. // No stubs, nothing to do here.
return; return stubbed_funcs;
} }
// Get the stubs array as an array type. // Get the stubs array as an array type.
@ -24,6 +26,8 @@ void get_stubbed_funcs(std::vector<std::string>& stubbed_funcs, const toml::valu
// Copy the entry into the stubbed function list. // Copy the entry into the stubbed function list.
stubbed_funcs[stub_idx] = stubs_array[stub_idx].as_string(); stubbed_funcs[stub_idx] = stubs_array[stub_idx].as_string();
} }
return stubbed_funcs;
} }
std::unordered_map<std::string, RecompPort::FunctionArgType> arg_type_map{ std::unordered_map<std::string, RecompPort::FunctionArgType> arg_type_map{
@ -53,12 +57,14 @@ std::vector<RecompPort::FunctionArgType> parse_args(const toml::array& args_in)
return ret; return ret;
} }
void get_declared_funcs(RecompPort::DeclaredFunctionMap& declared_funcs, const toml::value& patches_data) { RecompPort::DeclaredFunctionMap get_declared_funcs(const toml::value& patches_data) {
RecompPort::DeclaredFunctionMap declared_funcs{};
// Check if the func array exists. // Check if the func array exists.
const toml::value& funcs_data = toml::find_or<toml::value>(patches_data, "func", toml::value{}); const toml::value& funcs_data = toml::find_or<toml::value>(patches_data, "func", toml::value{});
if (funcs_data.type() == toml::value_t::empty) { if (funcs_data.type() == toml::value_t::empty) {
// No func array, nothing to do here // No func array, nothing to do here
return; return declared_funcs;
} }
// Get the funcs array as an array type. // Get the funcs array as an array type.
@ -72,6 +78,34 @@ void get_declared_funcs(RecompPort::DeclaredFunctionMap& declared_funcs, const t
declared_funcs.emplace(func_name, parse_args(args_in)); declared_funcs.emplace(func_name, parse_args(args_in));
} }
return declared_funcs;
}
std::vector<RecompPort::InstructionPatch> get_instruction_patches(const toml::value& patches_data) {
std::vector<RecompPort::InstructionPatch> ret;
// Check if the instruction patch array exists.
const toml::value& insn_patch_data = toml::find_or<toml::value>(patches_data, "instruction", toml::value{});
if (insn_patch_data.type() == toml::value_t::empty) {
// No instruction patch array, nothing to do here
return ret;
}
// Get the instruction patch array as an array type.
const toml::array& insn_patch_array = insn_patch_data.as_array();
ret.resize(insn_patch_array.size());
// Copy all the patches into the output vector.
for (size_t patch_idx = 0; patch_idx < insn_patch_array.size(); patch_idx++) {
const toml::value& cur_patch = insn_patch_array[patch_idx];
ret[patch_idx].func_name = toml::find<std::string>(cur_patch, "func");
ret[patch_idx].vram = toml::find<int32_t>(cur_patch, "vram");
ret[patch_idx].value = toml::find<uint32_t>(cur_patch, "value");
}
return ret;
} }
std::filesystem::path concat_if_not_empty(const std::filesystem::path& parent, const std::filesystem::path& child) { std::filesystem::path concat_if_not_empty(const std::filesystem::path& parent, const std::filesystem::path& child) {
@ -102,10 +136,13 @@ RecompPort::Config::Config(const char* path) {
const toml::value& patches_data = toml::find_or<toml::value>(config_data, "patches", toml::value{}); const toml::value& patches_data = toml::find_or<toml::value>(config_data, "patches", toml::value{});
if (patches_data.type() != toml::value_t::empty) { if (patches_data.type() != toml::value_t::empty) {
// Stubs array (optional) // Stubs array (optional)
get_stubbed_funcs(stubbed_funcs, patches_data); stubbed_funcs = get_stubbed_funcs(patches_data);
// Functions (optional) // Functions (optional)
get_declared_funcs(declared_funcs, patches_data); declared_funcs = get_declared_funcs(patches_data);
// Single-instruction patches (optional)
instruction_patches = get_instruction_patches(patches_data);
} }
} }
catch (const toml::syntax_error& err) { catch (const toml::syntax_error& err) {