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.)
This commit is contained in:
comex 2013-09-09 23:33:42 -04:00
parent a3ef35a1bf
commit 4add0f55e0
2 changed files with 44 additions and 12 deletions

View File

@ -22,6 +22,19 @@ CWII_IPC_HLE_Device_sdio_slot0::CWII_IPC_HLE_Device_sdio_slot0(u32 _DeviceID, co
, m_Card(NULL) , 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() void CWII_IPC_HLE_Device_sdio_slot0::EventNotify()
{ {
if ((SConfig::GetInstance().m_WiiSDCard && m_event.type == EVENT_INSERT) || 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"; const std::string filename = File::GetUserPath(D_WIIUSER_IDX) + "sd.raw";
m_Card.Open(filename, "r+b"); m_Card.Open(filename, "r+b");
if (!m_Card) 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?"); 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); Memory::Write_U32(GetDeviceID(), _CommandAddress + 0x4);
memset(m_Registers, 0, sizeof(m_Registers));
m_Active = true; m_Active = true;
return 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); 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)) if ((reg == HCR_CLOCKCONTROL) && (val & 1))
{ {
// Clock is set to oscillate, enable bit 1 to say it's stable // 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) else if ((reg == HCR_SOFTWARERESET) && val)
{ {
// When a reset is specified, the register gets cleared // When a reset is specified, the register gets cleared
Memory::Write_U32(0, SDIO_BASE + reg); m_Registers[reg] = 0;
} }
else else
{ {
// Default to just storing the new value // Default to just storing the new value
Memory::Write_U32(val, SDIO_BASE + reg); m_Registers[reg] = val;
} }
} }
break; break;
@ -117,9 +142,16 @@ bool CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
case IOCTL_READHCR: case IOCTL_READHCR:
{ {
u32 reg = Memory::Read_U32(BufferIn); 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); DEBUG_LOG(WII_IPC_SD, "IOCTL_READHCR 0x%08x - 0x%08x", reg, val);
// Just reading the register // Just reading the register
Memory::Write_U32(val, BufferOut); Memory::Write_U32(val, BufferOut);
} }

View File

@ -15,6 +15,8 @@ public:
CWII_IPC_HLE_Device_sdio_slot0(u32 _DeviceID, const std::string& _rDeviceName); CWII_IPC_HLE_Device_sdio_slot0(u32 _DeviceID, const std::string& _rDeviceName);
virtual void DoState(PointerWrap& p);
bool Open(u32 _CommandAddress, u32 _Mode); bool Open(u32 _CommandAddress, u32 _Mode);
bool Close(u32 _CommandAddress, bool _bForce); bool Close(u32 _CommandAddress, bool _bForce);
bool IOCtl(u32 _CommandAddress); bool IOCtl(u32 _CommandAddress);
@ -24,11 +26,6 @@ public:
private: private:
enum
{
SDIO_BASE = 0x8d070000,
};
// SD Host Controller Registers // SD Host Controller Registers
enum enum
{ {
@ -119,11 +116,14 @@ private:
u32 m_BlockLength; u32 m_BlockLength;
u32 m_BusWidth; u32 m_BusWidth;
u32 m_Registers[0x200/4];
File::IOFile m_Card; File::IOFile m_Card;
u32 ExecuteCommand(u32 BufferIn, u32 BufferInSize, u32 ExecuteCommand(u32 BufferIn, u32 BufferInSize,
u32 BufferIn2, u32 BufferInSize2, u32 BufferIn2, u32 BufferInSize2,
u32 _BufferOut, u32 BufferOutSize); u32 _BufferOut, u32 BufferOutSize);
void OpenInternal();
}; };
#endif #endif