diff --git a/Source/Core/Core/HLE/HLE.h b/Source/Core/Core/HLE/HLE.h index a944c6b56c..9f851e0396 100644 --- a/Source/Core/Core/HLE/HLE.h +++ b/Source/Core/Core/HLE/HLE.h @@ -42,4 +42,33 @@ HookType GetFunctionTypeByIndex(u32 index); HookFlag GetFunctionFlagsByIndex(u32 index); bool IsEnabled(HookFlag flag); + +// Performs the backend-independent preliminary checking before calling a +// FunctionObject to do the actual replacing. Typically, this callback will +// be in the backend itself, containing the backend-specific portions +// required in replacing a function. +// +// fn may be any object that satisfies the FunctionObject concept in the C++ +// standard library. That is, any lambda, object with an overloaded function +// call operator, or regular function pointer. +// +// fn must return a bool indicating whether or not function replacing occurred. +// fn must also accept a parameter list of the form: fn(u32 function, HLE::HookType type). +template +bool ReplaceFunctionIfPossible(u32 address, FunctionObject fn) +{ + const u32 function = GetFirstFunctionIndex(address); + if (function == 0) + return false; + + const HookType type = GetFunctionTypeByIndex(function); + if (type != HookType::Start && type != HookType::Replace) + return false; + + const HookFlag flags = GetFunctionFlagsByIndex(function); + if (!IsEnabled(flags)) + return false; + + return fn(function, type); } +} // namespace HLE diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp index d6d85f727d..d2da611cfb 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp @@ -171,6 +171,21 @@ static bool CheckDSI(u32 data) return false; } +bool CachedInterpreter::HandleFunctionHooking(u32 address) +{ + return HLE::ReplaceFunctionIfPossible(address, [&](u32 function, HLE::HookType type) { + m_code.emplace_back(WritePC, address); + m_code.emplace_back(Interpreter::HLEFunction, function); + + if (type != HLE::HookType::Replace) + return false; + + m_code.emplace_back(EndBlock, js.downcountAmount); + m_code.emplace_back(); + return true; + }); +} + void CachedInterpreter::Jit(u32 address) { if (m_code.size() >= CODE_SIZE / sizeof(Instruction) - 0x1000 || @@ -208,26 +223,8 @@ void CachedInterpreter::Jit(u32 address) js.downcountAmount += op.opinfo->numCycles; - u32 function = HLE::GetFirstFunctionIndex(op.address); - if (function != 0) - { - HLE::HookType type = HLE::GetFunctionTypeByIndex(function); - if (type == HLE::HookType::Start || type == HLE::HookType::Replace) - { - HLE::HookFlag flags = HLE::GetFunctionFlagsByIndex(function); - if (HLE::IsEnabled(flags)) - { - m_code.emplace_back(WritePC, op.address); - m_code.emplace_back(Interpreter::HLEFunction, function); - if (type == HLE::HookType::Replace) - { - m_code.emplace_back(EndBlock, js.downcountAmount); - m_code.emplace_back(); - break; - } - } - } - } + if (HandleFunctionHooking(op.address)) + break; if (!op.skip) { diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h index 733072b0f5..b7dbd5cfdd 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h @@ -38,6 +38,8 @@ private: const u8* GetCodePtr() const; void ExecuteOneBlock(); + bool HandleFunctionHooking(u32 address); + BlockCache m_block_cache{*this}; std::vector m_code; PPCAnalyst::CodeBuffer code_buffer;