From e51119c4ce467e2d425625cfc398385d147469ee Mon Sep 17 00:00:00 2001 From: Sepalani Date: Sun, 31 Oct 2021 12:53:00 +0400 Subject: [PATCH] HLE: Fix hooks overlapping Riivolution patches --- Source/Core/Core/HLE/HLE.cpp | 17 +++++++++++++++++ Source/Core/Core/HLE/HLE.h | 1 + Source/Core/DiscIO/RiivolutionPatcher.cpp | 15 ++++++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/HLE/HLE.cpp b/Source/Core/Core/HLE/HLE.cpp index 6b5bad6a7e..7660d0bef7 100644 --- a/Source/Core/Core/HLE/HLE.cpp +++ b/Source/Core/Core/HLE/HLE.cpp @@ -235,4 +235,21 @@ u32 UnPatch(std::string_view patch_name) return 0; } + +u32 UnpatchRange(u32 start_addr, u32 end_addr) +{ + u32 count = 0; + + auto i = s_hooked_addresses.lower_bound(start_addr); + while (i != s_hooked_addresses.end() && i->first < end_addr) + { + INFO_LOG_FMT(OSHLE, "Unpatch HLE hooks [{:08x};{:08x}): {} at {:08x}", start_addr, end_addr, + os_patches[i->second].name, i->first); + PowerPC::ppcState.iCache.Invalidate(i->first); + i = s_hooked_addresses.erase(i); + count += 1; + } + + return count; +} } // namespace HLE diff --git a/Source/Core/Core/HLE/HLE.h b/Source/Core/Core/HLE/HLE.h index b058de68d8..75ee8a7607 100644 --- a/Source/Core/Core/HLE/HLE.h +++ b/Source/Core/Core/HLE/HLE.h @@ -40,6 +40,7 @@ void Reload(); void Patch(u32 pc, std::string_view func_name); u32 UnPatch(std::string_view patch_name); +u32 UnpatchRange(u32 start_addr, u32 end_addr); void Execute(u32 current_pc, u32 hook_index); // Returns the HLE hook index of the address diff --git a/Source/Core/DiscIO/RiivolutionPatcher.cpp b/Source/Core/DiscIO/RiivolutionPatcher.cpp index eb8f55f45a..7eec9e2d55 100644 --- a/Source/Core/DiscIO/RiivolutionPatcher.cpp +++ b/Source/Core/DiscIO/RiivolutionPatcher.cpp @@ -13,6 +13,7 @@ #include "Common/FileUtil.h" #include "Common/IOFile.h" #include "Common/StringUtil.h" +#include "Core/HLE/HLE.h" #include "Core/HW/Memmap.h" #include "Core/IOS/FS/FileSystem.h" #include "Core/PowerPC/MMU.h" @@ -529,8 +530,15 @@ static void ApplyMemoryPatch(u32 offset, const std::vector& value, if (!original.empty() && !MemoryMatchesAt(offset, original)) return; - for (u32 i = 0; i < value.size(); ++i) + const u32 size = static_cast(value.size()); + for (u32 i = 0; i < size; ++i) PowerPC::HostTryWriteU8(value[i], offset + i); + const u32 overlapping_hook_count = HLE::UnpatchRange(offset, offset + size); + if (overlapping_hook_count != 0) + { + WARN_LOG_FMT(OSHLE, "Riivolution memory patch overlaps {} HLE hook(s) at {:08x} (size: {})", + overlapping_hook_count, offset, value.size()); + } } static std::vector GetMemoryPatchValue(const Patch& patch, const Memory& memory_patch) @@ -593,6 +601,11 @@ static void ApplyOcarinaMemoryPatch(const Patch& patch, const Memory& memory_pat const u32 target = memory_patch.m_offset | 0x80000000; const u32 jmp = ((target - blr_address) & 0x03fffffc) | 0x48000000; PowerPC::HostTryWriteU32(jmp, blr_address); + const u32 overlapping_hook_count = HLE::UnpatchRange(blr_address, blr_address + 4); + if (overlapping_hook_count != 0) + { + WARN_LOG_FMT(OSHLE, "Riivolution ocarina patch overlaps HLE hook at {}", blr_address); + } return; } }