From 3825e2e5ffe882aa4fa59fe88644613d1bf250d1 Mon Sep 17 00:00:00 2001 From: booto Date: Wed, 15 Aug 2018 22:33:16 -0400 Subject: [PATCH] SI: Add 16bit accessors for SI IO buffer Dolphin has traditionally treated the SI IO buffer (128 bytes) as a set of 32 little endian u32s. This works out fine if you only ever read/write using aligned 32bit accesses. Different sized accesses or misaligned reads will mess it up. Byte swapping reads/writes will fix this up, but all the SI devices that use the SI IO buffer need to be adjusted. --- Source/Core/Core/HW/SI/SI.cpp | 30 +++++++++++++++++-- Source/Core/Core/HW/SI/SI_Device.cpp | 2 +- Source/Core/Core/HW/SI/SI_DeviceDanceMat.cpp | 5 ++-- Source/Core/Core/HW/SI/SI_DeviceGBA.cpp | 21 ++++++------- .../Core/Core/HW/SI/SI_DeviceGCController.cpp | 15 +++++----- .../Core/HW/SI/SI_DeviceGCSteeringWheel.cpp | 5 ++-- Source/Core/Core/HW/SI/SI_DeviceKeyboard.cpp | 9 +++--- Source/Core/Core/HW/SI/SI_DeviceNull.cpp | 3 +- 8 files changed, 60 insertions(+), 30 deletions(-) diff --git a/Source/Core/Core/HW/SI/SI.cpp b/Source/Core/Core/HW/SI/SI.cpp index ff06a4cfc1..6cfe63ad4c 100644 --- a/Source/Core/Core/HW/SI/SI.cpp +++ b/Source/Core/Core/HW/SI/SI.cpp @@ -11,6 +11,7 @@ #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" +#include "Common/Swap.h" #include "Core/ConfigManager.h" #include "Core/CoreTiming.h" #include "Core/HW/MMIO.h" @@ -50,6 +51,7 @@ enum SI_COM_CSR = 0x34, SI_STATUS_REG = 0x38, SI_EXI_CLOCK_COUNT = 0x3C, + SI_IO_BUFFER = 0x80, }; // SI Channel Output @@ -414,12 +416,34 @@ void Shutdown() void RegisterMMIO(MMIO::Mapping* mmio, u32 base) { // Register SI buffer direct accesses. + const u32 io_buffer_base = base | SI_IO_BUFFER; for (size_t i = 0; i < s_si_buffer.size(); i += sizeof(u32)) { - const u32 address = base | static_cast(s_si_buffer.size() + i); + const u32 address = base | static_cast(io_buffer_base + i); - mmio->Register(address, MMIO::DirectRead((u32*)&s_si_buffer[i]), - MMIO::DirectWrite((u32*)&s_si_buffer[i])); + mmio->Register(address, MMIO::ComplexRead([i](u32) { + u32 val; + std::memcpy(&val, &s_si_buffer[i], sizeof(val)); + return Common::swap32(val); + }), + MMIO::ComplexWrite([i](u32, u32 val) { + val = Common::swap32(val); + std::memcpy(&s_si_buffer[i], &val, sizeof(val)); + })); + } + for (size_t i = 0; i < s_si_buffer.size(); i += sizeof(u16)) + { + const u32 address = base | static_cast(io_buffer_base + i); + + mmio->Register(address, MMIO::ComplexRead([i](u32) { + u16 val; + std::memcpy(&val, &s_si_buffer[i], sizeof(val)); + return Common::swap16(val); + }), + MMIO::ComplexWrite([i](u32, u16 val) { + val = Common::swap16(val); + std::memcpy(&s_si_buffer[i], &val, sizeof(val)); + })); } // In and out for the 4 SI channels. diff --git a/Source/Core/Core/HW/SI/SI_Device.cpp b/Source/Core/Core/HW/SI/SI_Device.cpp index 968d3e2235..bd63f0ad76 100644 --- a/Source/Core/Core/HW/SI/SI_Device.cpp +++ b/Source/Core/Core/HW/SI/SI_Device.cpp @@ -47,7 +47,7 @@ int ISIDevice::RunBuffer(u8* buffer, int length) while (num < length) { - temp += StringFromFormat("0x%02x ", buffer[num ^ 3]); + temp += StringFromFormat("0x%02x ", buffer[num]); num++; if ((num % 8) == 0) diff --git a/Source/Core/Core/HW/SI/SI_DeviceDanceMat.cpp b/Source/Core/Core/HW/SI/SI_DeviceDanceMat.cpp index 7a940cc755..e9c8fe4c48 100644 --- a/Source/Core/Core/HW/SI/SI_DeviceDanceMat.cpp +++ b/Source/Core/Core/HW/SI/SI_DeviceDanceMat.cpp @@ -7,6 +7,7 @@ #include #include "Common/CommonTypes.h" +#include "Common/Swap.h" #include "InputCommon/GCPadStatus.h" namespace SerialInterface @@ -19,13 +20,13 @@ CSIDevice_DanceMat::CSIDevice_DanceMat(SIDevices device, int device_number) int CSIDevice_DanceMat::RunBuffer(u8* buffer, int length) { // Read the command - EBufferCommands command = static_cast(buffer[3]); + EBufferCommands command = static_cast(buffer[0]); if (command == CMD_RESET) { ISIDevice::RunBuffer(buffer, length); - constexpr u32 id = SI_DANCEMAT; + u32 id = Common::swap32(SI_DANCEMAT); std::memcpy(buffer, &id, sizeof(id)); } else diff --git a/Source/Core/Core/HW/SI/SI_DeviceGBA.cpp b/Source/Core/Core/HW/SI/SI_DeviceGBA.cpp index e7e20a9fc2..37a1b0f7e9 100644 --- a/Source/Core/Core/HW/SI/SI_DeviceGBA.cpp +++ b/Source/Core/Core/HW/SI/SI_DeviceGBA.cpp @@ -16,6 +16,7 @@ #include "Common/CommonTypes.h" #include "Common/Flag.h" #include "Common/Logging/Log.h" +#include "Common/Swap.h" #include "Common/Thread.h" #include "Core/CoreTiming.h" #include "Core/HW/SI/SI_Device.h" @@ -32,7 +33,7 @@ std::mutex s_cs_gba; std::mutex s_cs_gba_clk; int s_num_connected; Common::Flag s_server_running; -} +} // namespace enum EJoybusCmds { @@ -235,7 +236,7 @@ void GBASockServer::Send(const u8* si_buffer) std::array send_data; for (size_t i = 0; i < send_data.size(); i++) - send_data[i] = si_buffer[i ^ 3]; + send_data[i] = si_buffer[i]; u8 cmd = send_data[0]; if (cmd != CMD_STATUS) @@ -281,7 +282,7 @@ int GBASockServer::Receive(u8* si_buffer) } for (size_t i = 0; i < recv_data.size(); i++) - si_buffer[i ^ 3] = recv_data[i]; + si_buffer[i] = recv_data[i]; return static_cast(std::min(num_received, recv_data.size())); } @@ -299,23 +300,23 @@ int CSIDevice_GBA::RunBuffer(u8* buffer, int length) if (m_sock_server.Connect()) { #ifdef _DEBUG - NOTICE_LOG(SERIALINTERFACE, "%01d cmd %02x [> %02x%02x%02x%02x]", m_device_number, buffer[3], - buffer[2], buffer[1], buffer[0], buffer[7]); + NOTICE_LOG(SERIALINTERFACE, "%01d cmd %02x [> %02x%02x%02x%02x]", m_device_number, buffer[0], + buffer[1], buffer[2], buffer[3], buffer[4]); #endif m_sock_server.Send(buffer); } else { - constexpr u32 reply = SI_ERROR_NO_RESPONSE; + u32 reply = Common::swap32(SI_ERROR_NO_RESPONSE); std::memcpy(buffer, &reply, sizeof(reply)); return sizeof(reply); } - m_last_cmd = buffer[3]; + m_last_cmd = buffer[0]; m_timestamp_sent = CoreTiming::GetTicks(); m_next_action = NextAction::WaitTransferTime; } - // [[fallthrough]] + // [[fallthrough]]b case NextAction::WaitTransferTime: { int elapsed_time = static_cast(CoreTiming::GetTicks() - m_timestamp_sent); @@ -332,7 +333,7 @@ int CSIDevice_GBA::RunBuffer(u8* buffer, int length) m_next_action = NextAction::SendCommand; if (num_data_received == 0) { - constexpr u32 reply = SI_ERROR_NO_RESPONSE; + u32 reply = Common::swap32(SI_ERROR_NO_RESPONSE); std::memcpy(buffer, &reply, sizeof(reply)); return sizeof(reply); } @@ -342,7 +343,7 @@ int CSIDevice_GBA::RunBuffer(u8* buffer, int length) LogTypes::LWARNING; GENERIC_LOG(LogTypes::SERIALINTERFACE, log_level, "%01d [< %02x%02x%02x%02x%02x] (%i)", m_device_number, - buffer[3], buffer[2], buffer[1], buffer[0], buffer[7], num_data_received); + buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], num_data_received); #endif return num_data_received; } diff --git a/Source/Core/Core/HW/SI/SI_DeviceGCController.cpp b/Source/Core/Core/HW/SI/SI_DeviceGCController.cpp index a7903343c0..e9adac7e5b 100644 --- a/Source/Core/Core/HW/SI/SI_DeviceGCController.cpp +++ b/Source/Core/Core/HW/SI/SI_DeviceGCController.cpp @@ -10,6 +10,7 @@ #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" #include "Common/MsgHandler.h" +#include "Common/Swap.h" #include "Core/CoreTiming.h" #include "Core/HW/GCPad.h" #include "Core/HW/ProcessorInterface.h" @@ -50,13 +51,13 @@ int CSIDevice_GCController::RunBuffer(u8* buffer, int length) GCPadStatus pad_status = GetPadStatus(); if (!pad_status.isConnected) { - constexpr u32 reply = SI_ERROR_NO_RESPONSE; + u32 reply = Common::swap32(SI_ERROR_NO_RESPONSE); std::memcpy(buffer, &reply, sizeof(reply)); return 4; } // Read the command - EBufferCommands command = static_cast(buffer[3]); + EBufferCommands command = static_cast(buffer[0]); // Handle it switch (command) @@ -64,7 +65,7 @@ int CSIDevice_GCController::RunBuffer(u8* buffer, int length) case CMD_RESET: case CMD_ID: { - constexpr u32 id = SI_GC_CONTROLLER; + u32 id = Common::swap32(SI_GC_CONTROLLER); std::memcpy(buffer, &id, sizeof(id)); break; } @@ -76,8 +77,8 @@ int CSIDevice_GCController::RunBuffer(u8* buffer, int length) GetData(high, low); for (int i = 0; i < (length - 1) / 2; i++) { - buffer[i + 0] = (high >> (i * 8)) & 0xff; - buffer[i + 4] = (low >> (i * 8)) & 0xff; + buffer[i + 0] = (high >> (24 - (i * 8))) & 0xff; + buffer[i + 4] = (low >> (24 - (i * 8))) & 0xff; } } break; @@ -92,7 +93,7 @@ int CSIDevice_GCController::RunBuffer(u8* buffer, int length) u8* calibration = reinterpret_cast(&m_origin); for (int i = 0; i < (int)sizeof(SOrigin); i++) { - buffer[i ^ 3] = *calibration++; + buffer[i] = *calibration++; } } break; @@ -108,7 +109,7 @@ int CSIDevice_GCController::RunBuffer(u8* buffer, int length) u8* calibration = reinterpret_cast(&m_origin); for (int i = 0; i < (int)sizeof(SOrigin); i++) { - buffer[i ^ 3] = *calibration++; + buffer[i] = *calibration++; } } break; diff --git a/Source/Core/Core/HW/SI/SI_DeviceGCSteeringWheel.cpp b/Source/Core/Core/HW/SI/SI_DeviceGCSteeringWheel.cpp index b21551315d..42f583e94e 100644 --- a/Source/Core/Core/HW/SI/SI_DeviceGCSteeringWheel.cpp +++ b/Source/Core/Core/HW/SI/SI_DeviceGCSteeringWheel.cpp @@ -8,6 +8,7 @@ #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" +#include "Common/Swap.h" #include "Core/HW/GCPad.h" namespace SerialInterface @@ -23,7 +24,7 @@ int CSIDevice_GCSteeringWheel::RunBuffer(u8* buffer, int length) ISIDevice::RunBuffer(buffer, length); // Read the command - EBufferCommands command = static_cast(buffer[3]); + EBufferCommands command = static_cast(buffer[0]); // Handle it switch (command) @@ -31,7 +32,7 @@ int CSIDevice_GCSteeringWheel::RunBuffer(u8* buffer, int length) case CMD_RESET: case CMD_ID: { - constexpr u32 id = SI_GC_STEERING; + u32 id = Common::swap32(SI_GC_STEERING); std::memcpy(buffer, &id, sizeof(id)); break; } diff --git a/Source/Core/Core/HW/SI/SI_DeviceKeyboard.cpp b/Source/Core/Core/HW/SI/SI_DeviceKeyboard.cpp index fc29ff7da6..6e3cc00ce6 100644 --- a/Source/Core/Core/HW/SI/SI_DeviceKeyboard.cpp +++ b/Source/Core/Core/HW/SI/SI_DeviceKeyboard.cpp @@ -9,6 +9,7 @@ #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" +#include "Common/Swap.h" #include "Core/HW/GCKeyboard.h" #include "InputCommon/KeyboardStatus.h" @@ -26,7 +27,7 @@ int CSIDevice_Keyboard::RunBuffer(u8* buffer, int length) ISIDevice::RunBuffer(buffer, length); // Read the command - EBufferCommands command = static_cast(buffer[3]); + EBufferCommands command = static_cast(buffer[0]); // Handle it switch (command) @@ -34,7 +35,7 @@ int CSIDevice_Keyboard::RunBuffer(u8* buffer, int length) case CMD_RESET: case CMD_ID: { - constexpr u32 id = SI_GC_KEYBOARD; + u32 id = Common::swap32(SI_GC_KEYBOARD); std::memcpy(buffer, &id, sizeof(id)); break; } @@ -46,8 +47,8 @@ int CSIDevice_Keyboard::RunBuffer(u8* buffer, int length) GetData(high, low); for (int i = 0; i < (length - 1) / 2; i++) { - buffer[i + 0] = (high >> (i * 8)) & 0xff; - buffer[i + 4] = (low >> (i * 8)) & 0xff; + buffer[i + 0] = (high >> (24 - (i * 8))) & 0xff; + buffer[i + 4] = (low >> (24 - (i * 8))) & 0xff; } } break; diff --git a/Source/Core/Core/HW/SI/SI_DeviceNull.cpp b/Source/Core/Core/HW/SI/SI_DeviceNull.cpp index d2a94af45d..ee4a39c253 100644 --- a/Source/Core/Core/HW/SI/SI_DeviceNull.cpp +++ b/Source/Core/Core/HW/SI/SI_DeviceNull.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "Core/HW/SI/SI_DeviceNull.h" +#include "Common/Swap.h" #include @@ -15,7 +16,7 @@ CSIDevice_Null::CSIDevice_Null(SIDevices device, int device_number) int CSIDevice_Null::RunBuffer(u8* buffer, int length) { - constexpr u32 reply = SI_ERROR_NO_RESPONSE; + u32 reply = Common::swap32(SI_ERROR_NO_RESPONSE); std::memcpy(buffer, &reply, sizeof(reply)); return 4; }