PPCDebugInterface: Small refactor to ApplyMemoryPatch

Invalidate icache only if target address has a different value. Take separate arguements,
instead of a struct, to allow easier usage elsewhere. Overload with u8,
u16 and u32 values for the same reason.
This commit is contained in:
Martino Fontana
2025-06-19 15:41:02 +02:00
parent 6a55a1bf68
commit aa7b13f353
2 changed files with 33 additions and 18 deletions

View File

@@ -29,55 +29,58 @@
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
#include "Core/System.h" #include "Core/System.h"
void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, Common::Debug::MemoryPatch& patch, void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, std::span<u8> value, const u32 address,
bool store_existing_value) bool store_existing_value)
{ {
if (AchievementManager::GetInstance().IsHardcoreModeActive()) if (AchievementManager::GetInstance().IsHardcoreModeActive())
return; return;
if (patch.value.empty()) if (value.empty())
return; return;
const u32 address = patch.address; const std::size_t size = value.size();
const std::size_t size = patch.value.size();
if (!PowerPC::MMU::HostIsRAMAddress(guard, address)) if (!PowerPC::MMU::HostIsRAMAddress(guard, address))
return; return;
auto& power_pc = guard.GetSystem().GetPowerPC(); auto& power_pc = guard.GetSystem().GetPowerPC();
bool should_invalidate_cache = false;
for (u32 offset = 0; offset < size; ++offset) for (u32 offset = 0; offset < size; ++offset)
{ {
if (store_existing_value) u8 old_value = PowerPC::MMU::HostRead_U8(guard, address + offset);
if (old_value != value[offset])
{ {
const u8 value = PowerPC::MMU::HostRead_U8(guard, address + offset); PowerPC::MMU::HostWrite_U8(guard, value[offset], address + offset);
PowerPC::MMU::HostWrite_U8(guard, patch.value[offset], address + offset); should_invalidate_cache = true;
patch.value[offset] = value; if (store_existing_value)
} value[offset] = old_value;
else
{
PowerPC::MMU::HostWrite_U8(guard, patch.value[offset], address + offset);
} }
if (((address + offset) % 4) == 3) if (((address + offset) % 4) == 3)
power_pc.ScheduleInvalidateCacheThreadSafe(Common::AlignDown(address + offset, 4)); {
if (should_invalidate_cache)
power_pc.ScheduleInvalidateCacheThreadSafe(Common::AlignDown(address + offset, 4));
should_invalidate_cache = false;
}
} }
if (((address + size) % 4) != 0) if (should_invalidate_cache)
{ {
power_pc.ScheduleInvalidateCacheThreadSafe( power_pc.ScheduleInvalidateCacheThreadSafe(
Common::AlignDown(address + static_cast<u32>(size), 4)); Common::AlignDown(address + static_cast<u32>(size) - 1, 4));
} }
} }
void PPCPatches::ApplyExistingPatch(const Core::CPUThreadGuard& guard, std::size_t index) void PPCPatches::ApplyExistingPatch(const Core::CPUThreadGuard& guard, std::size_t index)
{ {
auto& patch = m_patches[index]; auto& patch = m_patches[index];
ApplyMemoryPatch(guard, patch, false); ApplyMemoryPatch(guard, patch.value, patch.address, false);
} }
void PPCPatches::Patch(const Core::CPUThreadGuard& guard, std::size_t index) void PPCPatches::Patch(const Core::CPUThreadGuard& guard, std::size_t index)
{ {
auto& patch = m_patches[index]; auto& patch = m_patches[index];
if (patch.type == Common::Debug::MemoryPatch::ApplyType::Once) if (patch.type == Common::Debug::MemoryPatch::ApplyType::Once)
ApplyMemoryPatch(guard, patch); ApplyMemoryPatch(guard, patch.value, patch.address);
else else
PatchEngine::AddMemoryPatch(index); PatchEngine::AddMemoryPatch(index);
} }

View File

@@ -3,12 +3,15 @@
#pragma once #pragma once
#include <concepts>
#include <cstddef> #include <cstddef>
#include <memory> #include <memory>
#include <span>
#include <string> #include <string>
#include "Common/Debug/MemoryPatches.h" #include "Common/Debug/MemoryPatches.h"
#include "Common/Debug/Watches.h" #include "Common/Debug/Watches.h"
#include "Common/Swap.h"
#include "Core/Debugger/DebugInterface.h" #include "Core/Debugger/DebugInterface.h"
#include "Core/NetworkCaptureLogger.h" #include "Core/NetworkCaptureLogger.h"
@@ -19,9 +22,18 @@ class System;
} // namespace Core } // namespace Core
class PPCSymbolDB; class PPCSymbolDB;
void ApplyMemoryPatch(const Core::CPUThreadGuard&, Common::Debug::MemoryPatch& patch, void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, std::span<u8> value, const u32 address,
bool store_existing_value = true); bool store_existing_value = true);
template <std::unsigned_integral T>
void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, T value, const u32 address)
{
Common::BigEndianValue<T> big_endian{value};
auto data =
std::span<u8, sizeof(T)>{reinterpret_cast<u8*>(std::addressof(big_endian)), sizeof(T)};
ApplyMemoryPatch(guard, data, address);
}
class PPCPatches final : public Common::Debug::MemoryPatches class PPCPatches final : public Common::Debug::MemoryPatches
{ {
public: public: