PINE: Add MsgReadBytes/MsgWriteBytes

This commit is contained in:
Stenzek 2024-07-21 13:34:10 +10:00
parent 79644bfb2a
commit f2e88ce0e5
No known key found for this signature in database
1 changed files with 56 additions and 9 deletions

View File

@ -50,14 +50,14 @@ static constexpr u32 MAX_IPC_RETURN_SIZE = 450000;
*/ */
enum IPCCommand : u8 enum IPCCommand : u8
{ {
MsgRead8 = 0, /**< Read 8 bit value to memory. */ MsgRead8 = 0, /**< Read 8 bit value from memory. */
MsgRead16 = 1, /**< Read 16 bit value to memory. */ MsgRead16 = 1, /**< Read 16 bit value from memory. */
MsgRead32 = 2, /**< Read 32 bit value to memory. */ MsgRead32 = 2, /**< Read 32 bit value from memory. */
MsgRead64 = 3, /**< Read 64 bit value to memory. */ MsgRead64 = 3, /**< Read 64 bit value from memory. */
MsgWrite8 = 4, /**< Write 8 bit value to memory. */ MsgWrite8 = 4, /**< Write 8 bit value from memory. */
MsgWrite16 = 5, /**< Write 16 bit value to memory. */ MsgWrite16 = 5, /**< Write 16 bit value from memory. */
MsgWrite32 = 6, /**< Write 32 bit value to memory. */ MsgWrite32 = 6, /**< Write 32 bit value from memory. */
MsgWrite64 = 7, /**< Write 64 bit value to memory. */ MsgWrite64 = 7, /**< Write 64 bit value from memory. */
MsgVersion = 8, /**< Returns PCSX2 version. */ MsgVersion = 8, /**< Returns PCSX2 version. */
MsgSaveState = 9, /**< Saves a savestate. */ MsgSaveState = 9, /**< Saves a savestate. */
MsgLoadState = 0xA, /**< Loads a savestate. */ MsgLoadState = 0xA, /**< Loads a savestate. */
@ -66,6 +66,8 @@ enum IPCCommand : u8
MsgUUID = 0xD, /**< Returns the game UUID. */ MsgUUID = 0xD, /**< Returns the game UUID. */
MsgGameVersion = 0xE, /**< Returns the game verion. */ MsgGameVersion = 0xE, /**< Returns the game verion. */
MsgStatus = 0xF, /**< Returns the emulator status. */ MsgStatus = 0xF, /**< Returns the emulator status. */
MsgReadBytes = 0x20, /**< Reads range of bytes from memory. */
MsgWriteBytes = 0x21, /**< Writes range of bytes to memory. */
MsgUnimplemented = 0xFF /**< Unimplemented IPC message. */ MsgUnimplemented = 0xFF /**< Unimplemented IPC message. */
}; };
@ -334,6 +336,33 @@ bool PINEServer::PINESocket::HandleCommand(IPCCommand command, BinarySpanReader
return EndReply(reply); return EndReply(reply);
} }
case MsgReadBytes:
{
if (!rdbuf.CheckRemaining(sizeof(PhysicalMemoryAddress) + sizeof(u32)) || !System::IsValid())
return SendErrorReply();
const PhysicalMemoryAddress addr = rdbuf.ReadU32();
const u32 num_bytes = rdbuf.ReadU32();
if (num_bytes == 0) [[unlikely]]
return SendErrorReply();
if (!BeginReply(reply, num_bytes)) [[unlikely]]
return false;
const auto data = reply.GetRemainingSpan(sizeof(IPCStatus) + num_bytes);
if (!CPU::SafeReadMemoryBytes(addr, data.data() + sizeof(IPCStatus), num_bytes)) [[unlikely]]
{
reply << IPC_FAIL;
}
else
{
reply << IPC_OK;
reply.IncrementPosition(num_bytes);
}
return EndReply(reply);
}
case MsgWrite8: case MsgWrite8:
{ {
// Don't do the actual write until we have space for the response, otherwise we might do it twice when we come // Don't do the actual write until we have space for the response, otherwise we might do it twice when we come
@ -377,7 +406,7 @@ bool PINEServer::PINESocket::HandleCommand(IPCCommand command, BinarySpanReader
case MsgWrite64: case MsgWrite64:
{ {
if (!rdbuf.CheckRemaining(sizeof(PhysicalMemoryAddress) + sizeof(u32)) || !System::IsValid()) if (!rdbuf.CheckRemaining(sizeof(PhysicalMemoryAddress) + sizeof(u64)) || !System::IsValid())
return SendErrorReply(); return SendErrorReply();
else if (!BeginReply(reply, 0)) [[unlikely]] else if (!BeginReply(reply, 0)) [[unlikely]]
return false; return false;
@ -391,6 +420,24 @@ bool PINEServer::PINESocket::HandleCommand(IPCCommand command, BinarySpanReader
return EndReply(reply); return EndReply(reply);
} }
case MsgWriteBytes:
{
if (!rdbuf.CheckRemaining(sizeof(PhysicalMemoryAddress) + sizeof(u32)) || !System::IsValid())
return SendErrorReply();
const PhysicalMemoryAddress addr = rdbuf.ReadU32();
const u32 num_bytes = rdbuf.ReadU32();
if (num_bytes == 0 || !rdbuf.CheckRemaining(num_bytes)) [[unlikely]]
return SendErrorReply();
if (!BeginReply(reply, 0)) [[unlikely]]
return false;
const auto data = rdbuf.GetRemainingSpan(num_bytes);
reply << (CPU::SafeWriteMemoryBytes(addr, data.data(), num_bytes) ? IPC_OK : IPC_FAIL);
return EndReply(reply);
}
case MsgVersion: case MsgVersion:
{ {
const TinyString version = TinyString::from_format("DuckStation {}", g_scm_tag_str); const TinyString version = TinyString::from_format("DuckStation {}", g_scm_tag_str);