From 4add0f55e046c4fd2943e96da127b4940543ac84 Mon Sep 17 00:00:00 2001 From: comex Date: Mon, 9 Sep 2013 23:33:42 -0400 Subject: [PATCH] Fix SDIO HLE writing garbage to memory. When servicing a write-register request, it wrote the contents to the register offset plus 0x8d070000, which corresponds to the actual hardware registers, presumably in case the application wanted to read them directly rather than with a read-register request. WriteToHardware doesn't handle cached writes to registers, so it decided the address was RAM, applied RAM_MASK, and happily wrote the register contents to 0x81070000, causing random corruption. Since the PPC does not normally have access to those registers, there is no reason to be doing this in the first place. Use a member to store these values instead. (Also add a proper DoState.) --- .../IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.cpp | 46 ++++++++++++++++--- .../IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.h | 10 ++-- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.cpp index 68b38633ac..c422bd7960 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.cpp @@ -22,6 +22,19 @@ CWII_IPC_HLE_Device_sdio_slot0::CWII_IPC_HLE_Device_sdio_slot0(u32 _DeviceID, co , m_Card(NULL) {} +void CWII_IPC_HLE_Device_sdio_slot0::DoState(PointerWrap& p) +{ + DoStateShared(p); + if (p.GetMode() == PointerWrap::MODE_READ) + { + OpenInternal(); + } + p.Do(m_Status); + p.Do(m_BlockLength); + p.Do(m_BusWidth); + p.Do(m_Registers); +} + void CWII_IPC_HLE_Device_sdio_slot0::EventNotify() { if ((SConfig::GetInstance().m_WiiSDCard && m_event.type == EVENT_INSERT) || @@ -34,10 +47,8 @@ void CWII_IPC_HLE_Device_sdio_slot0::EventNotify() } } -bool CWII_IPC_HLE_Device_sdio_slot0::Open(u32 _CommandAddress, u32 _Mode) +void CWII_IPC_HLE_Device_sdio_slot0::OpenInternal() { - INFO_LOG(WII_IPC_SD, "Open"); - const std::string filename = File::GetUserPath(D_WIIUSER_IDX) + "sd.raw"; m_Card.Open(filename, "r+b"); if (!m_Card) @@ -53,8 +64,16 @@ bool CWII_IPC_HLE_Device_sdio_slot0::Open(u32 _CommandAddress, u32 _Mode) ERROR_LOG(WII_IPC_SD, "Could not open SD Card image or create a new one, are you running from a read-only directory?"); } } +} + +bool CWII_IPC_HLE_Device_sdio_slot0::Open(u32 _CommandAddress, u32 _Mode) +{ + INFO_LOG(WII_IPC_SD, "Open"); + + OpenInternal(); Memory::Write_U32(GetDeviceID(), _CommandAddress + 0x4); + memset(m_Registers, 0, sizeof(m_Registers)); m_Active = true; return true; } @@ -96,20 +115,26 @@ bool CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress) DEBUG_LOG(WII_IPC_SD, "IOCTL_WRITEHCR 0x%08x - 0x%08x", reg, val); + if (reg >= 0x200) + { + DEBUG_LOG(WII_IPC_SD, "IOCTL_WRITEHCR out of range"); + break; + } + if ((reg == HCR_CLOCKCONTROL) && (val & 1)) { // Clock is set to oscillate, enable bit 1 to say it's stable - Memory::Write_U32(val | 2, SDIO_BASE + reg); + m_Registers[reg] = val | 2; } else if ((reg == HCR_SOFTWARERESET) && val) { // When a reset is specified, the register gets cleared - Memory::Write_U32(0, SDIO_BASE + reg); + m_Registers[reg] = 0; } else { // Default to just storing the new value - Memory::Write_U32(val, SDIO_BASE + reg); + m_Registers[reg] = val; } } break; @@ -117,9 +142,16 @@ bool CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress) case IOCTL_READHCR: { u32 reg = Memory::Read_U32(BufferIn); - u32 val = Memory::Read_U32(SDIO_BASE + reg); + if (reg >= 0x200) + { + DEBUG_LOG(WII_IPC_SD, "IOCTL_READHCR out of range"); + break; + } + + u32 val = m_Registers[reg]; DEBUG_LOG(WII_IPC_SD, "IOCTL_READHCR 0x%08x - 0x%08x", reg, val); + // Just reading the register Memory::Write_U32(val, BufferOut); } diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.h index 74ffe13410..e7a323228d 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.h @@ -15,6 +15,8 @@ public: CWII_IPC_HLE_Device_sdio_slot0(u32 _DeviceID, const std::string& _rDeviceName); + virtual void DoState(PointerWrap& p); + bool Open(u32 _CommandAddress, u32 _Mode); bool Close(u32 _CommandAddress, bool _bForce); bool IOCtl(u32 _CommandAddress); @@ -24,11 +26,6 @@ public: private: - enum - { - SDIO_BASE = 0x8d070000, - }; - // SD Host Controller Registers enum { @@ -119,11 +116,14 @@ private: u32 m_BlockLength; u32 m_BusWidth; + u32 m_Registers[0x200/4]; + File::IOFile m_Card; u32 ExecuteCommand(u32 BufferIn, u32 BufferInSize, u32 BufferIn2, u32 BufferInSize2, u32 _BufferOut, u32 BufferOutSize); + void OpenInternal(); }; #endif