From 06e11fb1764a3dd340312a526e28a58c7ade6618 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 25 Sep 2026 20:27:28 -0600 Subject: [PATCH] Savestate: Rehash analyzed functions before writing replacements on load The function list is from before the load, where other code (an overlay module) may have been. Hashing it again from the loaded memory keeps the hooks to code that actually matches. Co-Authored-By: Claude Opus 5.5 (1M context) --- Core/HLE/sceKernelModule.cpp | 3 +++ Core/MIPS/MIPSAnalyst.cpp | 6 ++++++ Core/MIPS/MIPSAnalyst.h | 2 ++ 3 files changed, 11 insertions(+) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 6af14c266c..15eeec6a21 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -503,6 +503,9 @@ void __KernelModuleDoState(PointerWrap &p) { } } } + // The functions were found in memory from before the load, where other code may have been + // (an overlay module, say.) Hash them from what's there now, so a hook only goes where it matches. + MIPSAnalyst::RehashFunctions(); if (g_Config.bFuncReplacements) { MIPSAnalyst::ReplaceFunctions(); } diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index 4a6b05628f..c3d55859f9 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -1279,6 +1279,12 @@ skip: return false; } + void RehashFunctions() { + std::lock_guard guard(functions_lock); + HashFunctions(); + UpdateHashToFunctionMap(); + } + void ReplaceFunctions() { std::lock_guard guard(functions_lock); diff --git a/Core/MIPS/MIPSAnalyst.h b/Core/MIPS/MIPSAnalyst.h index 4baebf39e8..1c1a679a78 100644 --- a/Core/MIPS/MIPSAnalyst.h +++ b/Core/MIPS/MIPSAnalyst.h @@ -115,6 +115,8 @@ namespace MIPSAnalyst { void StoreHashMap(Path filename = Path()); const char *LookupHash(u64 hash, u32 funcSize); + // Hashes the known functions again, from what memory holds now (after a savestate load.) + void RehashFunctions(); void ReplaceFunctions(); void UpdateHashMap();