diff --git a/N64Recomp b/N64Recomp index 8781eb4..2af6f2d 160000 --- a/N64Recomp +++ b/N64Recomp @@ -1 +1 @@ -Subproject commit 8781eb44acbf55cb6a109d2aa5529aadb95a419d +Subproject commit 2af6f2d161f755ca68f8baeb4dc5b69ef58a862c diff --git a/librecomp/include/librecomp/mods.hpp b/librecomp/include/librecomp/mods.hpp index ee983cc..824a3d2 100644 --- a/librecomp/include/librecomp/mods.hpp +++ b/librecomp/include/librecomp/mods.hpp @@ -30,6 +30,7 @@ namespace N64Recomp { class Context; struct LiveGeneratorOutput; + class ShimFunction; }; namespace recomp { @@ -348,7 +349,7 @@ namespace recomp { void check_dependencies(ModHandle& mod, std::vector>& errors); CodeModLoadError init_mod_code(uint8_t* rdram, const std::unordered_map& section_vrom_map, ModHandle& mod, int32_t load_address, bool hooks_available, uint32_t& ram_used, std::string& error_param); CodeModLoadError load_mod_code(uint8_t* rdram, ModHandle& mod, uint32_t base_event_index, std::string& error_param); - CodeModLoadError resolve_code_dependencies(ModHandle& mod, const std::unordered_map& base_patched_funcs, std::string& error_param); + CodeModLoadError resolve_code_dependencies(ModHandle& mod, size_t mod_index, const std::unordered_map& base_patched_funcs, std::string& error_param); void add_opened_mod(ModManifest&& manifest, ConfigStorage&& config_storage, std::vector&& game_indices, std::vector&& detected_content_types, std::vector&& thumbnail); void close_mods(); std::vector regenerate_with_hooks( @@ -388,6 +389,8 @@ namespace recomp { // Tracks which hook slots have already been processed. Used to regenerate vanilla functions as needed // to add hooks to any functions that weren't already replaced by a mod. std::vector processed_hook_slots; + // Generated shim functions to use for implementing shim exports. + std::vector> shim_functions; ConfigSchema empty_schema; std::vector empty_bytes; size_t num_events = 0; diff --git a/librecomp/include/librecomp/overlays.hpp b/librecomp/include/librecomp/overlays.hpp index 40cbb96..35703bd 100644 --- a/librecomp/include/librecomp/overlays.hpp +++ b/librecomp/include/librecomp/overlays.hpp @@ -25,6 +25,7 @@ namespace recomp { void register_patches(const char* patch_data, size_t patch_size, SectionTableEntry* code_sections, size_t num_sections); void register_base_export(const std::string& name, recomp_func_t* func); + void register_ext_base_export(const std::string& name, recomp_func_ext_t* func); void register_base_exports(const FunctionExport* exports); void register_base_events(char const* const* event_names); void register_manual_patch_symbols(const ManualPatchSymbol* manual_patch_symbols); @@ -38,6 +39,7 @@ namespace recomp { bool get_func_entry_by_section_index_function_offset(uint16_t code_section_index, uint32_t function_offset, FuncEntry& func_out); recomp_func_t* get_func_by_section_index_function_offset(uint16_t code_section_index, uint32_t function_offset); recomp_func_t* get_base_export(const std::string& export_name); + recomp_func_ext_t* get_ext_base_export(const std::string& export_name); size_t get_base_event_index(const std::string& event_name); size_t num_base_events(); diff --git a/librecomp/src/mods.cpp b/librecomp/src/mods.cpp index 9b1f80a..2401212 100644 --- a/librecomp/src/mods.cpp +++ b/librecomp/src/mods.cpp @@ -1520,7 +1520,7 @@ std::vector recomp::mods::ModContext::load_mo for (size_t mod_index : loaded_code_mods) { auto& mod = opened_mods[mod_index]; std::string cur_error_param; - CodeModLoadError cur_error = resolve_code_dependencies(mod, base_patched_funcs, cur_error_param); + CodeModLoadError cur_error = resolve_code_dependencies(mod, mod_index, base_patched_funcs, cur_error_param); if (cur_error != CodeModLoadError::Good) { if (cur_error_param.empty()) { ret.emplace_back(mod.manifest.mod_id, ModLoadError::FailedToLoadCode, error_to_string(cur_error)); @@ -2172,7 +2172,7 @@ recomp::mods::CodeModLoadError recomp::mods::ModContext::load_mod_code(uint8_t* return CodeModLoadError::Good; } -recomp::mods::CodeModLoadError recomp::mods::ModContext::resolve_code_dependencies(recomp::mods::ModHandle& mod, const std::unordered_map& base_patched_funcs, std::string& error_param) { +recomp::mods::CodeModLoadError recomp::mods::ModContext::resolve_code_dependencies(recomp::mods::ModHandle& mod, size_t mod_index, const std::unordered_map& base_patched_funcs, std::string& error_param) { // Reference symbols. std::string reference_syms_error_param{}; CodeModLoadError reference_syms_error = mod.code_handle->populate_reference_symbols(*mod.recompiler_context, reference_syms_error_param); @@ -2201,6 +2201,13 @@ recomp::mods::CodeModLoadError recomp::mods::ModContext::resolve_code_dependenci if (dependency_id == N64Recomp::DependencyBaseRecomp) { recomp_func_t* func_ptr = recomp::overlays::get_base_export(imported_func.base.name); did_find_func = func_ptr != nullptr; + if (!did_find_func) { + recomp_func_ext_t* func_ext_ptr = recomp::overlays::get_ext_base_export(imported_func.base.name); + did_find_func = func_ext_ptr != nullptr; + if (did_find_func) { + func_ptr = shim_functions.emplace_back(std::make_unique(func_ext_ptr, mod_index)).get()->get_func(); + } + } func_handle = func_ptr; } else if (dependency_id == N64Recomp::DependencySelf) { @@ -2343,6 +2350,7 @@ void recomp::mods::ModContext::unload_mods() { loaded_mods_by_id.clear(); hook_slots.clear(); processed_hook_slots.clear(); + shim_functions.clear(); recomp::mods::reset_events(); recomp::mods::reset_hooks(); num_events = recomp::overlays::num_base_events(); diff --git a/librecomp/src/overlays.cpp b/librecomp/src/overlays.cpp index e807cfa..8c8e5d1 100644 --- a/librecomp/src/overlays.cpp +++ b/librecomp/src/overlays.cpp @@ -38,6 +38,7 @@ static std::unordered_map patch_code_sections_by_rom{}; static std::vector loaded_sections{}; static std::unordered_map func_map{}; static std::unordered_map base_exports{}; +static std::unordered_map ext_base_exports{}; static std::unordered_map base_events; static std::unordered_map manual_patch_symbols_by_vram; @@ -67,6 +68,10 @@ void recomp::overlays::register_base_export(const std::string& name, recomp_func base_exports.emplace(name, func); } +void recomp::overlays::register_ext_base_export(const std::string& name, recomp_func_ext_t* func) { + ext_base_exports.emplace(name, func); +} + void recomp::overlays::register_base_exports(const FunctionExport* export_list) { std::unordered_map patch_func_vram_map{}; @@ -98,6 +103,14 @@ recomp_func_t* recomp::overlays::get_base_export(const std::string& export_name) return it->second; } +recomp_func_ext_t* recomp::overlays::get_ext_base_export(const std::string& export_name) { + auto it = ext_base_exports.find(export_name); + if (it == ext_base_exports.end()) { + return nullptr; + } + return it->second; +} + void recomp::overlays::register_base_events(char const* const* event_names) { for (size_t event_index = 0; event_names[event_index] != nullptr; event_index++) { base_events.emplace(event_names[event_index], event_index);