Misc: Add MemoryInterface classes

This commit is contained in:
chaoticgd
2026-01-15 22:48:59 +00:00
committed by Ty
parent d4cf5a998c
commit e52d8f70ba
9 changed files with 403 additions and 0 deletions
+2
View File
@@ -19,6 +19,7 @@ target_sources(common PRIVATE
HostSys.cpp
Image.cpp
HTTPDownloader.cpp
MemoryInterface.cpp
MemorySettingsInterface.cpp
MD5Digest.cpp
PrecompiledHeader.cpp
@@ -58,6 +59,7 @@ target_sources(common PRIVATE
LRUCache.h
HeapArray.h
HTTPDownloader.h
MemoryInterface.h
MemorySettingsInterface.h
MD5Digest.h
MRCHelpers.h
+138
View File
@@ -0,0 +1,138 @@
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
// SPDX-License-Identifier: GPL-3.0+
#include "MemoryInterface.h"
template <MemoryAccessType Value>
Value MemoryInterface::Read(u32 address, bool* valid)
{
if constexpr (std::is_same_v<Value, u8> || std::is_same_v<Value, s8>)
return static_cast<Value>(Read8(address, valid));
else if constexpr (std::is_same_v<Value, u16> || std::is_same_v<Value, s16>)
return static_cast<Value>(Read16(address, valid));
else if constexpr (std::is_same_v<Value, u32> || std::is_same_v<Value, s32>)
return static_cast<Value>(Read32(address, valid));
else if constexpr (std::is_same_v<Value, u64> || std::is_same_v<Value, s64>)
return static_cast<Value>(Read64(address, valid));
else if constexpr (std::is_same_v<Value, u128>)
return Read128(address, valid);
else if constexpr (std::is_same_v<Value, s128>)
{
u128 value = Read128(address, valid);
return s128{
.lo = static_cast<s64>(value.lo),
.hi = static_cast<s64>(value.hi),
};
}
else
return Value(0);
}
template <MemoryAccessType Value>
bool MemoryInterface::Write(u32 address, Value value)
{
if constexpr (std::is_same_v<Value, u8> || std::is_same_v<Value, s8>)
return Write8(address, static_cast<u8>(value));
else if constexpr (std::is_same_v<Value, u16> || std::is_same_v<Value, s16>)
return Write16(address, static_cast<u16>(value));
else if constexpr (std::is_same_v<Value, u32> || std::is_same_v<Value, s32>)
return Write32(address, static_cast<u32>(value));
else if constexpr (std::is_same_v<Value, u64> || std::is_same_v<Value, s64>)
return Write64(address, static_cast<u64>(value));
else if constexpr (std::is_same_v<Value, u128>)
return Write128(address, value);
else if constexpr (std::is_same_v<Value, s128>)
{
u128 unsigned_value;
unsigned_value.lo = static_cast<u64>(value.lo);
unsigned_value.hi = static_cast<u64>(value.hi);
return Write128(address, unsigned_value);
}
else
return false;
}
bool MemoryInterface::IdempotentWrite8(u32 address, u8 value)
{
bool valid;
u8 existing_value = Read8(address, &valid);
if (!valid || existing_value == value)
return valid;
return Write8(address, value);
}
bool MemoryInterface::IdempotentWrite16(u32 address, u16 value)
{
bool valid;
u16 existing_value = Read16(address, &valid);
if (!valid || existing_value == value)
return valid;
return Write16(address, value);
}
bool MemoryInterface::IdempotentWrite32(u32 address, u32 value)
{
bool valid;
u32 existing_value = Read32(address, &valid);
if (!valid || existing_value == value)
return valid;
return Write32(address, value);
}
bool MemoryInterface::IdempotentWrite64(u32 address, u64 value)
{
bool valid;
u64 existing_value = Read64(address, &valid);
if (!valid || existing_value == value)
return valid;
return Write64(address, value);
}
bool MemoryInterface::IdempotentWrite128(u32 address, u128 value)
{
bool valid;
u128 existing_value = Read128(address, &valid);
if (!valid || existing_value == value)
return valid;
return Write128(address, value);
}
bool MemoryInterface::IdempotentWriteBytes(u32 address, void* src, u32 size)
{
if (CompareBytes(address, src, size))
return true;
return WriteBytes(address, src, size);
}
template <MemoryAccessType Value>
bool MemoryInterface::IdempotentWrite(u32 address, Value value)
{
bool valid;
Value existing_value = Read<Value>(address, &valid);
if (!valid || existing_value == value)
return valid;
return Write<Value>(address, value);
}
#define EXPLICITLY_INSTANTIATE_TEMPLATES(type) \
template type MemoryInterface::Read<type>(u32 addres, bool* valid); \
template bool MemoryInterface::Write<type>(u32 address, type value); \
template bool MemoryInterface::IdempotentWrite<type>(u32 address, type value);
EXPLICITLY_INSTANTIATE_TEMPLATES(u8)
EXPLICITLY_INSTANTIATE_TEMPLATES(s8)
EXPLICITLY_INSTANTIATE_TEMPLATES(u16)
EXPLICITLY_INSTANTIATE_TEMPLATES(s16)
EXPLICITLY_INSTANTIATE_TEMPLATES(u32)
EXPLICITLY_INSTANTIATE_TEMPLATES(s32)
EXPLICITLY_INSTANTIATE_TEMPLATES(u64)
EXPLICITLY_INSTANTIATE_TEMPLATES(s64)
EXPLICITLY_INSTANTIATE_TEMPLATES(u128)
EXPLICITLY_INSTANTIATE_TEMPLATES(s128)
#undef EXPLICITLY_INSTANTIATE_TEMPLATES
+52
View File
@@ -0,0 +1,52 @@
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
// SPDX-License-Identifier: GPL-3.0+
#pragma once
#include "Pcsx2Types.h"
#include <type_traits>
template <typename Value>
concept MemoryAccessType = std::is_same_v<Value, u8> || std::is_same_v<Value, s8> ||
std::is_same_v<Value, u16> || std::is_same_v<Value, s16> ||
std::is_same_v<Value, u32> || std::is_same_v<Value, s32> ||
std::is_same_v<Value, u64> || std::is_same_v<Value, s64> ||
std::is_same_v<Value, u128> || std::is_same_v<Value, s128>;
/// Interface for reading/writing guest memory.
class MemoryInterface
{
public:
virtual u8 Read8(u32 address, bool* valid = nullptr) = 0;
virtual u16 Read16(u32 address, bool* valid = nullptr) = 0;
virtual u32 Read32(u32 address, bool* valid = nullptr) = 0;
virtual u64 Read64(u32 address, bool* valid = nullptr) = 0;
virtual u128 Read128(u32 address, bool* valid = nullptr) = 0;
virtual bool ReadBytes(u32 address, void* dest, u32 size) = 0;
template <MemoryAccessType Value>
Value Read(u32 address, bool* valid = nullptr);
virtual bool Write8(u32 address, u8 value) = 0;
virtual bool Write16(u32 address, u16 value) = 0;
virtual bool Write32(u32 address, u32 value) = 0;
virtual bool Write64(u32 address, u64 value) = 0;
virtual bool Write128(u32 address, u128 value) = 0;
virtual bool WriteBytes(u32 address, void* src, u32 size) = 0;
template <MemoryAccessType Value>
bool Write(u32 address, Value value);
bool IdempotentWrite8(u32 address, u8 value);
bool IdempotentWrite16(u32 address, u16 value);
bool IdempotentWrite32(u32 address, u32 value);
bool IdempotentWrite64(u32 address, u64 value);
bool IdempotentWrite128(u32 address, u128 value);
bool IdempotentWriteBytes(u32 address, void* src, u32 size);
template <MemoryAccessType Value>
bool IdempotentWrite(u32 address, Value value);
virtual bool CompareBytes(u32 address, void* src, u32 size) = 0;
};
+2
View File
@@ -62,6 +62,7 @@
</ClCompile>
<ClCompile Include="HTTPDownloaderWinHTTP.cpp" />
<ClCompile Include="MD5Digest.cpp" />
<ClCompile Include="MemoryInterface.cpp" />
<ClCompile Include="MemorySettingsInterface.cpp" />
<ClCompile Include="ProgressCallback.cpp" />
<ClCompile Include="ReadbackSpinManager.cpp" />
@@ -141,6 +142,7 @@
</ClInclude>
<ClInclude Include="HTTPDownloaderWinHTTP.h" />
<ClInclude Include="MD5Digest.h" />
<ClInclude Include="MemoryInterface.h" />
<ClInclude Include="MemorySettingsInterface.h" />
<ClInclude Include="ProgressCallback.h" />
<ClInclude Include="ScopedGuard.h" />
+6
View File
@@ -103,6 +103,9 @@
<ClCompile Include="HTTPDownloaderWinHTTP.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MemoryInterface.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MemorySettingsInterface.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -303,6 +306,9 @@
<ClInclude Include="HeterogeneousContainers.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MemoryInterface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MemorySettingsInterface.h">
<Filter>Header Files</Filter>
</ClInclude>
+78
View File
@@ -538,3 +538,81 @@ std::string iopMemReadString(u32 mem, int maxlen)
return ret;
}
u8 IOPMemoryInterface::Read8(u32 address, bool* valid)
{
if (valid)
*valid = true;
return iopMemRead8(address);
}
u16 IOPMemoryInterface::Read16(u32 address, bool* valid)
{
if (valid)
*valid = true;
return iopMemRead16(address);
}
u32 IOPMemoryInterface::Read32(u32 address, bool* valid)
{
if (valid)
*valid = true;
return iopMemRead32(address);
}
u64 IOPMemoryInterface::Read64(u32 address, bool* valid)
{
if (valid)
*valid = false;
return 0;
}
u128 IOPMemoryInterface::Read128(u32 address, bool* valid)
{
if (valid)
*valid = false;
return u128::From64(0);
}
bool IOPMemoryInterface::ReadBytes(u32 address, void* dest, u32 size)
{
return iopMemSafeReadBytes(address, dest, size);
}
bool IOPMemoryInterface::Write8(u32 address, u8 value)
{
iopMemWrite8(address, value);
return true;
}
bool IOPMemoryInterface::Write16(u32 address, u16 value)
{
iopMemWrite16(address, value);
return true;
}
bool IOPMemoryInterface::Write32(u32 address, u32 value)
{
iopMemWrite32(address, value);
return true;
}
bool IOPMemoryInterface::Write64(u32 address, u64 value)
{
return false;
}
bool IOPMemoryInterface::Write128(u32 address, u128 value)
{
return false;
}
bool IOPMemoryInterface::WriteBytes(u32 address, void* src, u32 size)
{
return iopMemSafeWriteBytes(address, src, size);
}
bool IOPMemoryInterface::CompareBytes(u32 address, void* src, u32 size)
{
return iopMemSafeCmpBytes(address, src, size) != 0;
}
+22
View File
@@ -5,6 +5,8 @@
#include "MemoryTypes.h"
#include "common/MemoryInterface.h"
#include <string>
extern uptr *psxMemWLUT;
@@ -118,3 +120,23 @@ namespace IopMemory
extern void iopHwWrite32_Page3( u32 iopaddr, mem32_t data );
extern void iopHwWrite32_Page8( u32 iopaddr, mem32_t data );
}
class IOPMemoryInterface final : public MemoryInterface
{
public:
u8 Read8(u32 address, bool* valid = nullptr) override;
u16 Read16(u32 address, bool* valid = nullptr) override;
u32 Read32(u32 address, bool* valid = nullptr) override;
u64 Read64(u32 address, bool* valid = nullptr) override;
u128 Read128(u32 address, bool* valid = nullptr) override;
bool ReadBytes(u32 address, void* dest, u32 size) override;
bool Write8(u32 address, u8 value) override;
bool Write16(u32 address, u16 value) override;
bool Write32(u32 address, u32 value) override;
bool Write64(u32 address, u64 value) override;
bool Write128(u32 address, u128 value) override;
bool WriteBytes(u32 address, void* src, u32 size) override;
bool CompareBytes(u32 address, void* src, u32 size) override;
};
+82
View File
@@ -1253,3 +1253,85 @@ bool SaveStateBase::memFreeze(Error* error)
return IsOkay();
}
u8 EEMemoryInterface::Read8(u32 address, bool* valid)
{
if (valid)
*valid = true;
return memRead8(address);
}
u16 EEMemoryInterface::Read16(u32 address, bool* valid)
{
if (valid)
*valid = true;
return memRead16(address);
}
u32 EEMemoryInterface::Read32(u32 address, bool* valid)
{
if (valid)
*valid = true;
return memRead32(address);
}
u64 EEMemoryInterface::Read64(u32 address, bool* valid)
{
if (valid)
*valid = true;
return memRead64(address);
}
u128 EEMemoryInterface::Read128(u32 address, bool* valid)
{
u128 value;
memRead128(address, value);
if (valid)
*valid = true;
return value;
}
bool EEMemoryInterface::ReadBytes(u32 address, void* dest, u32 size)
{
return vtlb_memSafeReadBytes(address, dest, size);
}
bool EEMemoryInterface::Write8(u32 address, u8 value)
{
memWrite8(address, value);
return true;
}
bool EEMemoryInterface::Write16(u32 address, u16 value)
{
memWrite16(address, value);
return true;
}
bool EEMemoryInterface::Write32(u32 address, u32 value)
{
memWrite32(address, value);
return true;
}
bool EEMemoryInterface::Write64(u32 address, u64 value)
{
memWrite64(address, value);
return true;
}
bool EEMemoryInterface::Write128(u32 address, u128 value)
{
memWrite128(address, value);
return true;
}
bool EEMemoryInterface::WriteBytes(u32 address, void* src, u32 size)
{
return vtlb_memSafeWriteBytes(address, src, size);
}
bool EEMemoryInterface::CompareBytes(u32 address, void* src, u32 size)
{
return vtlb_memSafeCmpBytes(address, src, size) != 0;
}
+21
View File
@@ -6,6 +6,7 @@
#include "vtlb.h"
#include "MemoryTypes.h"
#include "common/BitUtils.h"
#include "common/MemoryInterface.h"
// This is a table of default virtual map addresses for ps2vm components. These locations
// are provided and used to assist in debugging and possibly hacking; as it makes it possible
@@ -191,3 +192,23 @@ static __fi void memWrite128(u32 mem, const mem128_t& val) { vtlb_memWrite128(me
extern void ba0W16(u32 mem, u16 value);
extern u16 ba0R16(u32 mem);
class EEMemoryInterface final : public MemoryInterface
{
public:
u8 Read8(u32 address, bool* valid = nullptr) override;
u16 Read16(u32 address, bool* valid = nullptr) override;
u32 Read32(u32 address, bool* valid = nullptr) override;
u64 Read64(u32 address, bool* valid = nullptr) override;
u128 Read128(u32 address, bool* valid = nullptr) override;
bool ReadBytes(u32 address, void* dest, u32 size) override;
bool Write8(u32 address, u8 value) override;
bool Write16(u32 address, u16 value) override;
bool Write32(u32 address, u32 value) override;
bool Write64(u32 address, u64 value) override;
bool Write128(u32 address, u128 value) override;
bool WriteBytes(u32 address, void* src, u32 size) override;
bool CompareBytes(u32 address, void* src, u32 size) override;
};