Core: add ability to apply memory patches during a frame update in the PatchEngine

This commit is contained in:
iwubcode 2022-12-22 17:35:48 -06:00
parent 4743d74985
commit 1f87bcd202
2 changed files with 31 additions and 0 deletions

View File

@ -11,6 +11,7 @@
#include <array> #include <array>
#include <iterator> #include <iterator>
#include <map> #include <map>
#include <mutex>
#include <optional> #include <optional>
#include <string> #include <string>
#include <vector> #include <vector>
@ -18,6 +19,7 @@
#include <fmt/format.h> #include <fmt/format.h>
#include "Common/Assert.h" #include "Common/Assert.h"
#include "Common/Debug/MemoryPatches.h"
#include "Common/IniFile.h" #include "Common/IniFile.h"
#include "Common/StringUtil.h" #include "Common/StringUtil.h"
@ -25,6 +27,7 @@
#include "Core/CheatCodes.h" #include "Core/CheatCodes.h"
#include "Core/Config/SessionSettings.h" #include "Core/Config/SessionSettings.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "Core/Debugger/PPCDebugInterface.h"
#include "Core/GeckoCode.h" #include "Core/GeckoCode.h"
#include "Core/GeckoCodeConfig.h" #include "Core/GeckoCodeConfig.h"
#include "Core/PowerPC/MMU.h" #include "Core/PowerPC/MMU.h"
@ -39,6 +42,8 @@ constexpr std::array<const char*, 3> s_patch_type_strings{{
}}; }};
static std::vector<Patch> s_on_frame; static std::vector<Patch> s_on_frame;
static std::vector<std::size_t> s_on_frame_memory;
static std::mutex s_on_frame_memory_mutex;
static std::map<u32, int> s_speed_hacks; static std::map<u32, int> s_speed_hacks;
const char* PatchTypeAsString(PatchType type) const char* PatchTypeAsString(PatchType type)
@ -257,6 +262,15 @@ static void ApplyPatches(const std::vector<Patch>& patches)
} }
} }
static void ApplyMemoryPatches(const std::vector<std::size_t>& memory_patch_indices)
{
std::lock_guard lock(s_on_frame_memory_mutex);
for (std::size_t index : memory_patch_indices)
{
PowerPC::debug_interface.ApplyExistingPatch(index);
}
}
// Requires MSR.DR, MSR.IR // Requires MSR.DR, MSR.IR
// There's no perfect way to do this, it's just a heuristic. // There's no perfect way to do this, it's just a heuristic.
// We require at least 2 stack frames, if the stack is shallower than that then it won't work. // We require at least 2 stack frames, if the stack is shallower than that then it won't work.
@ -281,6 +295,19 @@ static bool IsStackSane()
0 != PowerPC::HostRead_Instruction(address); 0 != PowerPC::HostRead_Instruction(address);
} }
void AddMemoryPatch(std::size_t index)
{
std::lock_guard lock(s_on_frame_memory_mutex);
s_on_frame_memory.push_back(index);
}
void RemoveMemoryPatch(std::size_t index)
{
std::lock_guard lock(s_on_frame_memory_mutex);
s_on_frame_memory.erase(std::remove(s_on_frame_memory.begin(), s_on_frame_memory.end(), index),
s_on_frame_memory.end());
}
bool ApplyFramePatches() bool ApplyFramePatches()
{ {
// Because we're using the VI Interrupt to time this instead of patching the game with a // Because we're using the VI Interrupt to time this instead of patching the game with a
@ -297,6 +324,7 @@ bool ApplyFramePatches()
} }
ApplyPatches(s_on_frame); ApplyPatches(s_on_frame);
ApplyMemoryPatches(s_on_frame_memory);
// Run the Gecko code handler // Run the Gecko code handler
Gecko::RunCodeHandler(); Gecko::RunCodeHandler();

View File

@ -51,6 +51,9 @@ void LoadPatchSection(const std::string& section, std::vector<Patch>* patches,
void SavePatchSection(IniFile* local_ini, const std::vector<Patch>& patches); void SavePatchSection(IniFile* local_ini, const std::vector<Patch>& patches);
void LoadPatches(); void LoadPatches();
void AddMemoryPatch(std::size_t index);
void RemoveMemoryPatch(std::size_t index);
bool ApplyFramePatches(); bool ApplyFramePatches();
void Shutdown(); void Shutdown();
void Reload(); void Reload();