diff --git a/Source/Core/Core/ActionReplay.cpp b/Source/Core/Core/ActionReplay.cpp index 4b309fd5a6..7642de40ac 100644 --- a/Source/Core/Core/ActionReplay.cpp +++ b/Source/Core/Core/ActionReplay.cpp @@ -42,6 +42,7 @@ #include "Core/AchievementManager.h" #include "Core/CheatCodes.h" #include "Core/Config/MainSettings.h" +#include "Core/Debugger/PPCDebugInterface.h" #include "Core/PowerPC/MMU.h" namespace ActionReplay @@ -379,7 +380,7 @@ static bool Subtype_RamWriteAndFill(const Core::CPUThreadGuard& guard, const ARA const u32 repeat = data >> 8; for (u32 i = 0; i <= repeat; ++i) { - PowerPC::MMU::HostWrite_U8(guard, data & 0xFF, new_addr + i); + ApplyMemoryPatch(guard, static_cast(data), new_addr + i); LogInfo("Wrote {:08x} to address {:08x}", data & 0xFF, new_addr + i); } LogInfo("--------"); @@ -393,7 +394,7 @@ static bool Subtype_RamWriteAndFill(const Core::CPUThreadGuard& guard, const ARA const u32 repeat = data >> 16; for (u32 i = 0; i <= repeat; ++i) { - PowerPC::MMU::HostWrite_U16(guard, data & 0xFFFF, new_addr + i * 2); + ApplyMemoryPatch(guard, static_cast(data), new_addr + i * 2); LogInfo("Wrote {:08x} to address {:08x}", data & 0xFFFF, new_addr + i * 2); } LogInfo("--------"); @@ -404,7 +405,7 @@ static bool Subtype_RamWriteAndFill(const Core::CPUThreadGuard& guard, const ARA case DATATYPE_32BIT: // Dword write LogInfo("32-bit Write"); LogInfo("--------"); - PowerPC::MMU::HostWrite_U32(guard, data, new_addr); + ApplyMemoryPatch(guard, data, new_addr); LogInfo("Wrote {:08x} to address {:08x}", data, new_addr); LogInfo("--------"); break; @@ -435,12 +436,12 @@ static bool Subtype_WriteToPointer(const Core::CPUThreadGuard& guard, const ARAd { LogInfo("Write 8-bit to pointer"); LogInfo("--------"); - const u8 thebyte = data & 0xFF; + const u8 thebyte = static_cast(data); const u32 offset = data >> 8; LogInfo("Pointer: {:08x}", ptr); LogInfo("Byte: {:08x}", thebyte); LogInfo("Offset: {:08x}", offset); - PowerPC::MMU::HostWrite_U8(guard, thebyte, ptr + offset); + ApplyMemoryPatch(guard, thebyte, ptr + offset); LogInfo("Wrote {:08x} to address {:08x}", thebyte, ptr + offset); LogInfo("--------"); break; @@ -450,12 +451,12 @@ static bool Subtype_WriteToPointer(const Core::CPUThreadGuard& guard, const ARAd { LogInfo("Write 16-bit to pointer"); LogInfo("--------"); - const u16 theshort = data & 0xFFFF; + const u16 theshort = static_cast(data); const u32 offset = (data >> 16) << 1; LogInfo("Pointer: {:08x}", ptr); LogInfo("Byte: {:08x}", theshort); LogInfo("Offset: {:08x}", offset); - PowerPC::MMU::HostWrite_U16(guard, theshort, ptr + offset); + ApplyMemoryPatch(guard, theshort, ptr + offset); LogInfo("Wrote {:08x} to address {:08x}", theshort, ptr + offset); LogInfo("--------"); break; @@ -465,7 +466,7 @@ static bool Subtype_WriteToPointer(const Core::CPUThreadGuard& guard, const ARAd case DATATYPE_32BIT: LogInfo("Write 32-bit to pointer"); LogInfo("--------"); - PowerPC::MMU::HostWrite_U32(guard, data, ptr); + ApplyMemoryPatch(guard, data, ptr); LogInfo("Wrote {:08x} to address {:08x}", data, ptr); LogInfo("--------"); break; @@ -493,7 +494,7 @@ static bool Subtype_AddCode(const Core::CPUThreadGuard& guard, const ARAddr& add case DATATYPE_8BIT: LogInfo("8-bit Add"); LogInfo("--------"); - PowerPC::MMU::HostWrite_U8(guard, PowerPC::MMU::HostRead_U8(guard, new_addr) + data, new_addr); + ApplyMemoryPatch(guard, PowerPC::MMU::HostRead_U8(guard, new_addr) + data, new_addr); LogInfo("Wrote {:02x} to address {:08x}", PowerPC::MMU::HostRead_U8(guard, new_addr), new_addr); LogInfo("--------"); break; @@ -501,8 +502,7 @@ static bool Subtype_AddCode(const Core::CPUThreadGuard& guard, const ARAddr& add case DATATYPE_16BIT: LogInfo("16-bit Add"); LogInfo("--------"); - PowerPC::MMU::HostWrite_U16(guard, PowerPC::MMU::HostRead_U16(guard, new_addr) + data, - new_addr); + ApplyMemoryPatch(guard, PowerPC::MMU::HostRead_U16(guard, new_addr) + data, new_addr); LogInfo("Wrote {:04x} to address {:08x}", PowerPC::MMU::HostRead_U16(guard, new_addr), new_addr); LogInfo("--------"); @@ -511,8 +511,7 @@ static bool Subtype_AddCode(const Core::CPUThreadGuard& guard, const ARAddr& add case DATATYPE_32BIT: LogInfo("32-bit Add"); LogInfo("--------"); - PowerPC::MMU::HostWrite_U32(guard, PowerPC::MMU::HostRead_U32(guard, new_addr) + data, - new_addr); + ApplyMemoryPatch(guard, PowerPC::MMU::HostRead_U32(guard, new_addr) + data, new_addr); LogInfo("Wrote {:08x} to address {:08x}", PowerPC::MMU::HostRead_U32(guard, new_addr), new_addr); LogInfo("--------"); @@ -528,7 +527,7 @@ static bool Subtype_AddCode(const Core::CPUThreadGuard& guard, const ARAddr& add // data contains an (unsigned?) integer value const float fread = read_float + static_cast(data); const u32 newval = std::bit_cast(fread); - PowerPC::MMU::HostWrite_U32(guard, newval, new_addr); + ApplyMemoryPatch(guard, newval, new_addr); LogInfo("Old Value {:08x}", read); LogInfo("Increment {:08x}", data); LogInfo("New value {:08x}", newval); @@ -586,7 +585,7 @@ static bool ZeroCode_FillAndSlide(const Core::CPUThreadGuard& guard, const u32 v LogInfo("--------"); for (int i = 0; i < write_num; ++i) { - PowerPC::MMU::HostWrite_U8(guard, val & 0xFF, curr_addr); + ApplyMemoryPatch(guard, static_cast(val), curr_addr); curr_addr += addr_incr; val += val_incr; LogInfo("Write {:08x} to address {:08x}", val & 0xFF, curr_addr); @@ -602,7 +601,7 @@ static bool ZeroCode_FillAndSlide(const Core::CPUThreadGuard& guard, const u32 v LogInfo("--------"); for (int i = 0; i < write_num; ++i) { - PowerPC::MMU::HostWrite_U16(guard, val & 0xFFFF, curr_addr); + ApplyMemoryPatch(guard, static_cast(val), curr_addr); LogInfo("Write {:08x} to address {:08x}", val & 0xFFFF, curr_addr); curr_addr += addr_incr * 2; val += val_incr; @@ -617,7 +616,7 @@ static bool ZeroCode_FillAndSlide(const Core::CPUThreadGuard& guard, const u32 v LogInfo("--------"); for (int i = 0; i < write_num; ++i) { - PowerPC::MMU::HostWrite_U32(guard, val, curr_addr); + ApplyMemoryPatch(guard, val, curr_addr); LogInfo("Write {:08x} to address {:08x}", val, curr_addr); curr_addr += addr_incr * 4; val += val_incr; @@ -664,8 +663,7 @@ static bool ZeroCode_MemoryCopy(const Core::CPUThreadGuard& guard, const u32 val LogInfo("Resolved Src Address to: {:08x}", ptr_src); for (int i = 0; i < num_bytes; ++i) { - PowerPC::MMU::HostWrite_U8(guard, PowerPC::MMU::HostRead_U8(guard, ptr_src + i), - ptr_dest + i); + ApplyMemoryPatch(guard, PowerPC::MMU::HostRead_U8(guard, ptr_src + i), ptr_dest + i); LogInfo("Wrote {:08x} to address {:08x}", PowerPC::MMU::HostRead_U8(guard, ptr_src + i), ptr_dest + i); } @@ -677,8 +675,7 @@ static bool ZeroCode_MemoryCopy(const Core::CPUThreadGuard& guard, const u32 val LogInfo("--------"); for (int i = 0; i < num_bytes; ++i) { - PowerPC::MMU::HostWrite_U8(guard, PowerPC::MMU::HostRead_U8(guard, addr_src + i), - addr_dest + i); + ApplyMemoryPatch(guard, PowerPC::MMU::HostRead_U8(guard, addr_src + i), addr_dest + i); LogInfo("Wrote {:08x} to address {:08x}", PowerPC::MMU::HostRead_U8(guard, addr_src + i), addr_dest + i); } diff --git a/Source/Core/Core/Debugger/PPCDebugInterface.cpp b/Source/Core/Core/Debugger/PPCDebugInterface.cpp index dea3aa25a9..bf4225ba66 100644 --- a/Source/Core/Core/Debugger/PPCDebugInterface.cpp +++ b/Source/Core/Core/Debugger/PPCDebugInterface.cpp @@ -29,55 +29,58 @@ #include "Core/PowerPC/PowerPC.h" #include "Core/System.h" -void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, Common::Debug::MemoryPatch& patch, +void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, std::span value, const u32 address, bool store_existing_value) { if (AchievementManager::GetInstance().IsHardcoreModeActive()) return; - if (patch.value.empty()) + if (value.empty()) return; - const u32 address = patch.address; - const std::size_t size = patch.value.size(); + const std::size_t size = value.size(); if (!PowerPC::MMU::HostIsRAMAddress(guard, address)) return; auto& power_pc = guard.GetSystem().GetPowerPC(); + + bool should_invalidate_cache = false; 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, patch.value[offset], address + offset); - patch.value[offset] = value; - } - else - { - PowerPC::MMU::HostWrite_U8(guard, patch.value[offset], address + offset); + PowerPC::MMU::HostWrite_U8(guard, value[offset], address + offset); + should_invalidate_cache = true; + if (store_existing_value) + value[offset] = old_value; } 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( - Common::AlignDown(address + static_cast(size), 4)); + Common::AlignDown(address + static_cast(size) - 1, 4)); } } void PPCPatches::ApplyExistingPatch(const Core::CPUThreadGuard& guard, std::size_t 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) { auto& patch = m_patches[index]; if (patch.type == Common::Debug::MemoryPatch::ApplyType::Once) - ApplyMemoryPatch(guard, patch); + ApplyMemoryPatch(guard, patch.value, patch.address); else PatchEngine::AddMemoryPatch(index); } diff --git a/Source/Core/Core/Debugger/PPCDebugInterface.h b/Source/Core/Core/Debugger/PPCDebugInterface.h index 456b987ab9..61f0dedfb3 100644 --- a/Source/Core/Core/Debugger/PPCDebugInterface.h +++ b/Source/Core/Core/Debugger/PPCDebugInterface.h @@ -3,12 +3,15 @@ #pragma once +#include #include #include +#include #include #include "Common/Debug/MemoryPatches.h" #include "Common/Debug/Watches.h" +#include "Common/Swap.h" #include "Core/Debugger/DebugInterface.h" #include "Core/NetworkCaptureLogger.h" @@ -19,9 +22,18 @@ class System; } // namespace Core class PPCSymbolDB; -void ApplyMemoryPatch(const Core::CPUThreadGuard&, Common::Debug::MemoryPatch& patch, +void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, std::span value, const u32 address, bool store_existing_value = true); +template +void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, T value, const u32 address) +{ + Common::BigEndianValue big_endian{value}; + auto data = + std::span{reinterpret_cast(std::addressof(big_endian)), sizeof(T)}; + ApplyMemoryPatch(guard, data, address); +} + class PPCPatches final : public Common::Debug::MemoryPatches { public: diff --git a/Source/Core/Core/PatchEngine.cpp b/Source/Core/Core/PatchEngine.cpp index 65765c44e0..44e5ecedc8 100644 --- a/Source/Core/Core/PatchEngine.cpp +++ b/Source/Core/Core/PatchEngine.cpp @@ -219,19 +219,19 @@ static void ApplyPatches(const Core::CPUThreadGuard& guard, const std::vector(comparand)) { - PowerPC::MMU::HostWrite_U8(guard, static_cast(value), addr); + ApplyMemoryPatch(guard, static_cast(value), addr); } break; case PatchType::Patch16Bit: if (!entry.conditional || PowerPC::MMU::HostRead_U16(guard, addr) == static_cast(comparand)) { - PowerPC::MMU::HostWrite_U16(guard, static_cast(value), addr); + ApplyMemoryPatch(guard, static_cast(value), addr); } break; case PatchType::Patch32Bit: if (!entry.conditional || PowerPC::MMU::HostRead_U32(guard, addr) == comparand) - PowerPC::MMU::HostWrite_U32(guard, value, addr); + ApplyMemoryPatch(guard, value, addr); break; default: // unknown patchtype