diff --git a/Source/Core/Core/HLE/HLE.cpp b/Source/Core/Core/HLE/HLE.cpp index 8e220ef526..7b35637c7e 100644 --- a/Source/Core/Core/HLE/HLE.cpp +++ b/Source/Core/Core/HLE/HLE.cpp @@ -21,23 +21,12 @@ namespace HLE { -using namespace PowerPC; - -typedef void (*TPatchFunction)(); - -static std::map s_original_instructions; - -struct SPatch -{ - char m_szPatchName[128]; - TPatchFunction PatchFunction; - HookType type; - HookFlag flags; -}; +// Map addresses to the HLE hook index +static std::map s_hooked_addresses; // clang-format off -constexpr std::array OSPatches{{ - // Placeholder, OSPatches[0] is the "non-existent function" index +constexpr std::array os_patches{{ + // Placeholder, os_patches[0] is the "non-existent function" index {"FAKE_TO_SKIP_0", HLE_Misc::UnimplementedFunction, HookType::Replace, HookFlag::Generic}, // Name doesn't matter, installed in CBoot::BootUp() @@ -70,19 +59,15 @@ constexpr std::array OSPatches{{ {"GeckoHandlerReturnTrampoline", HLE_Misc::GeckoReturnTrampoline, HookType::Replace, HookFlag::Fixed}, {"AppLoaderReport", HLE_OS::HLE_GeneralDebugPrint, HookType::Replace, HookFlag::Fixed} // apploader needs OSReport-like function }}; - -constexpr std::array OSBreakPoints{{ - {"FAKE_TO_SKIP_0", HLE_Misc::UnimplementedFunction, HookType::Start, HookFlag::Generic}, -}}; // clang-format on void Patch(u32 addr, std::string_view func_name) { - for (u32 i = 1; i < OSPatches.size(); ++i) + for (u32 i = 1; i < os_patches.size(); ++i) { - if (OSPatches[i].m_szPatchName == func_name) + if (os_patches[i].name == func_name) { - s_original_instructions[addr] = i; + s_hooked_addresses[addr] = i; PowerPC::ppcState.iCache.Invalidate(addr); return; } @@ -110,12 +95,12 @@ void PatchFixedFunctions() void PatchFunctions() { // Remove all hooks that aren't fixed address hooks - for (auto i = s_original_instructions.begin(); i != s_original_instructions.end();) + for (auto i = s_hooked_addresses.begin(); i != s_hooked_addresses.end();) { - if (OSPatches[i->second].flags != HookFlag::Fixed) + if (os_patches[i->second].flags != HookFlag::Fixed) { PowerPC::ppcState.iCache.Invalidate(i->first); - i = s_original_instructions.erase(i); + i = s_hooked_addresses.erase(i); } else { @@ -123,41 +108,27 @@ void PatchFunctions() } } - for (u32 i = 1; i < OSPatches.size(); ++i) + for (u32 i = 1; i < os_patches.size(); ++i) { // Fixed hooks don't map to symbols - if (OSPatches[i].flags == HookFlag::Fixed) + if (os_patches[i].flags == HookFlag::Fixed) continue; - for (const auto& symbol : g_symbolDB.GetSymbolsFromName(OSPatches[i].m_szPatchName)) + for (const auto& symbol : g_symbolDB.GetSymbolsFromName(os_patches[i].name)) { for (u32 addr = symbol->address; addr < symbol->address + symbol->size; addr += 4) { - s_original_instructions[addr] = i; + s_hooked_addresses[addr] = i; PowerPC::ppcState.iCache.Invalidate(addr); } - INFO_LOG(OSHLE, "Patching %s %08x", OSPatches[i].m_szPatchName, symbol->address); + INFO_LOG(OSHLE, "Patching %s %08x", os_patches[i].name, symbol->address); } } - - if (SConfig::GetInstance().bEnableDebugging) - { - for (size_t i = 1; i < OSBreakPoints.size(); ++i) - { - for (const auto& symbol : g_symbolDB.GetSymbolsFromName(OSBreakPoints[i].m_szPatchName)) - { - PowerPC::breakpoints.Add(symbol->address, false); - INFO_LOG(OSHLE, "Adding BP to %s %08x", OSBreakPoints[i].m_szPatchName, symbol->address); - } - } - } - - // CBreakPoints::AddBreakPoint(0x8000D3D0, false); } void Clear() { - s_original_instructions.clear(); + s_hooked_addresses.clear(); } void Reload() @@ -167,44 +138,44 @@ void Reload() PatchFunctions(); } -void Execute(u32 _CurrentPC, u32 _Instruction) +void Execute(u32 current_pc, u32 hook_index) { - unsigned int FunctionIndex = _Instruction & 0xFFFFF; - if (FunctionIndex > 0 && FunctionIndex < OSPatches.size()) + hook_index &= 0xFFFFF; + if (hook_index > 0 && hook_index < os_patches.size()) { - OSPatches[FunctionIndex].PatchFunction(); + os_patches[hook_index].function(); } else { - PanicAlert("HLE system tried to call an undefined HLE function %i.", FunctionIndex); + PanicAlert("HLE system tried to call an undefined HLE function %i.", hook_index); } } -u32 GetFunctionIndex(u32 address) +u32 GetHookByAddress(u32 address) { - auto iter = s_original_instructions.find(address); - return (iter != s_original_instructions.end()) ? iter->second : 0; + auto iter = s_hooked_addresses.find(address); + return (iter != s_hooked_addresses.end()) ? iter->second : 0; } -u32 GetFirstFunctionIndex(u32 address) +u32 GetHookByFunctionAddress(u32 address) { - const u32 index = GetFunctionIndex(address); + const u32 index = GetHookByAddress(address); // Fixed hooks use a fixed address and don't patch the whole function - if (index == 0 || OSPatches[index].flags == HookFlag::Fixed) + if (index == 0 || os_patches[index].flags == HookFlag::Fixed) return index; const auto symbol = g_symbolDB.GetSymbolFromAddr(address); return (symbol && symbol->address == address) ? index : 0; } -HookType GetFunctionTypeByIndex(u32 index) +HookType GetHookTypeByIndex(u32 index) { - return OSPatches[index].type; + return os_patches[index].type; } -HookFlag GetFunctionFlagsByIndex(u32 index) +HookFlag GetHookFlagsByIndex(u32 index) { - return OSPatches[index].flags; + return os_patches[index].flags; } bool IsEnabled(HookFlag flag) @@ -215,23 +186,23 @@ bool IsEnabled(HookFlag flag) u32 UnPatch(std::string_view patch_name) { - const auto patch = std::find_if(std::begin(OSPatches), std::end(OSPatches), - [&](const SPatch& p) { return patch_name == p.m_szPatchName; }); - if (patch == std::end(OSPatches)) + const auto patch = std::find_if(std::begin(os_patches), std::end(os_patches), + [&](const Hook& p) { return patch_name == p.name; }); + if (patch == std::end(os_patches)) return 0; if (patch->flags == HookFlag::Fixed) { - const u32 patch_idx = static_cast(std::distance(OSPatches.begin(), patch)); + const u32 patch_idx = static_cast(std::distance(os_patches.begin(), patch)); u32 addr = 0; // Reverse search by OSPatch key instead of address - for (auto i = s_original_instructions.begin(); i != s_original_instructions.end();) + for (auto i = s_hooked_addresses.begin(); i != s_hooked_addresses.end();) { if (i->second == patch_idx) { addr = i->first; PowerPC::ppcState.iCache.Invalidate(i->first); - i = s_original_instructions.erase(i); + i = s_hooked_addresses.erase(i); } else { @@ -247,7 +218,7 @@ u32 UnPatch(std::string_view patch_name) const auto& symbol = symbols[0]; for (u32 addr = symbol->address; addr < symbol->address + symbol->size; addr += 4) { - s_original_instructions.erase(addr); + s_hooked_addresses.erase(addr); PowerPC::ppcState.iCache.Invalidate(addr); } return symbol->address; @@ -255,19 +226,4 @@ u32 UnPatch(std::string_view patch_name) return 0; } - -bool UnPatch(u32 addr, std::string_view name) -{ - auto itr = s_original_instructions.find(addr); - if (itr == s_original_instructions.end()) - return false; - - if (!name.empty() && name != OSPatches[itr->second].m_szPatchName) - return false; - - s_original_instructions.erase(itr); - PowerPC::ppcState.iCache.Invalidate(addr); - return true; -} - } // end of namespace HLE diff --git a/Source/Core/Core/HLE/HLE.h b/Source/Core/Core/HLE/HLE.h index 6e07b832a7..a59e4a7a2b 100644 --- a/Source/Core/Core/HLE/HLE.h +++ b/Source/Core/Core/HLE/HLE.h @@ -10,6 +10,8 @@ namespace HLE { +using HookFunction = void (*)(); + enum class HookType { Start, // Hook the beginning of the function and execute the function afterwards @@ -24,6 +26,14 @@ enum class HookFlag Fixed, // An arbitrary hook mapped to a fixed address instead of a symbol }; +struct Hook +{ + char name[128]; + HookFunction function; + HookType type; + HookFlag flags; +}; + void PatchFixedFunctions(); void PatchFunctions(); void Clear(); @@ -31,15 +41,14 @@ void Reload(); void Patch(u32 pc, std::string_view func_name); u32 UnPatch(std::string_view patch_name); -bool UnPatch(u32 addr, std::string_view name = {}); -void Execute(u32 _CurrentPC, u32 _Instruction); +void Execute(u32 current_pc, u32 hook_index); -// Returns the HLE function index if the address is located in the function -u32 GetFunctionIndex(u32 address); -// Returns the HLE function index if the address matches the function start -u32 GetFirstFunctionIndex(u32 address); -HookType GetFunctionTypeByIndex(u32 index); -HookFlag GetFunctionFlagsByIndex(u32 index); +// Returns the HLE hook index of the address +u32 GetHookByAddress(u32 address); +// Returns the HLE hook index if the address matches the function start +u32 GetHookByFunctionAddress(u32 address); +HookType GetHookTypeByIndex(u32 index); +HookFlag GetHookFlagsByIndex(u32 index); bool IsEnabled(HookFlag flag); @@ -57,18 +66,18 @@ bool IsEnabled(HookFlag flag); template bool ReplaceFunctionIfPossible(u32 address, FunctionObject fn) { - const u32 function = GetFirstFunctionIndex(address); - if (function == 0) + const u32 hook_index = GetHookByFunctionAddress(address); + if (hook_index == 0) return false; - const HookType type = GetFunctionTypeByIndex(function); + const HookType type = GetHookTypeByIndex(hook_index); if (type != HookType::Start && type != HookType::Replace) return false; - const HookFlag flags = GetFunctionFlagsByIndex(function); + const HookFlag flags = GetHookFlagsByIndex(hook_index); if (!IsEnabled(flags)) return false; - return fn(function, type); + return fn(hook_index, type); } } // namespace HLE diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp index e2e4dd5a75..5d5036755d 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp @@ -192,9 +192,9 @@ static bool CheckIdle(u32 idle_pc) bool CachedInterpreter::HandleFunctionHooking(u32 address) { - return HLE::ReplaceFunctionIfPossible(address, [&](u32 function, HLE::HookType type) { + return HLE::ReplaceFunctionIfPossible(address, [&](u32 hook_index, HLE::HookType type) { m_code.emplace_back(WritePC, address); - m_code.emplace_back(Interpreter::HLEFunction, function); + m_code.emplace_back(Interpreter::HLEFunction, hook_index); if (type != HLE::HookType::Replace) return false; diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp index 2ab5ce1027..adb7055ab4 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp @@ -141,8 +141,8 @@ static void Trace(UGeckoInstruction& inst) bool Interpreter::HandleFunctionHooking(u32 address) { - return HLE::ReplaceFunctionIfPossible(address, [](u32 function, HLE::HookType type) { - HLEFunction(function); + return HLE::ReplaceFunctionIfPossible(address, [](u32 hook_index, HLE::HookType type) { + HLEFunction(hook_index); return type != HLE::HookType::Start; }); } diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 827c56dea5..36cbb946b0 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -433,12 +433,12 @@ void Jit64::FallBackToInterpreter(UGeckoInstruction inst) } } -void Jit64::HLEFunction(UGeckoInstruction _inst) +void Jit64::HLEFunction(u32 hook_index) { gpr.Flush(); fpr.Flush(); ABI_PushRegistersAndAdjustStack({}, 0); - ABI_CallFunctionCC(HLE::Execute, js.compilerPC, _inst.hex); + ABI_CallFunctionCC(HLE::Execute, js.compilerPC, hook_index); ABI_PopRegistersAndAdjustStack({}, 0); } @@ -1165,8 +1165,8 @@ void Jit64::IntializeSpeculativeConstants() bool Jit64::HandleFunctionHooking(u32 address) { - return HLE::ReplaceFunctionIfPossible(address, [&](u32 function, HLE::HookType type) { - HLEFunction(function); + return HLE::ReplaceFunctionIfPossible(address, [&](u32 hook_index, HLE::HookType type) { + HLEFunction(hook_index); if (type != HLE::HookType::Replace) return false; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h index 33263547da..35d3df8947 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/PowerPC/Jit64/Jit.h @@ -129,7 +129,7 @@ public: using Instruction = void (Jit64::*)(UGeckoInstruction instCode); void FallBackToInterpreter(UGeckoInstruction _inst); void DoNothing(UGeckoInstruction _inst); - void HLEFunction(UGeckoInstruction _inst); + void HLEFunction(u32 hook_index); void DynaRunTable4(UGeckoInstruction inst); void DynaRunTable19(UGeckoInstruction inst);