Wii memory bug: added debugging function to Memmap.cpp to trace the bug, uncomment the CheckForBadAddresses() calls to enable it

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1354 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2008-12-01 03:32:18 +00:00
parent 20b8277ee8
commit 4c7d20e555
5 changed files with 154 additions and 12 deletions

View File

@ -297,6 +297,139 @@ writeFn32 GetHWWriteFun32(const u32 _Address)
} }
// =======================================================
/* Functions to detect and trace memory read/write errors. Turn of JIT LoadStore to
make it work, and add a return 0 at the beginning of CheckDTLB to avoid closing
Dolphin just as it starts to get interesting. You can also try to change
the TitleID write in IOCTL_ES_GETTITLEID to 0x00000000, otherwise it will never even
get to making the bad dev/di request.
I'm currently at (---, 8021347c) : Write32: Program wrote [0x7fd5d340] to [0x933e00f8],
0x8021347c seems to write the out buffer to a 0x933e.... address before it is copies
to the 0x133e.... address for the Ioctlv. But why does it generate this bad address
when it made a good one 120 milliseconds earlier?
*/
// -------------
bool ValidMemory(const u32 _Address)
{
switch (_Address >> 24)
{
case 0x00:
case 0x01:
case 0x80:
case 0x81:
case 0xC0:
case 0xC1:
return true;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
if (Core::GetStartupParameter().bWii)
return true;
else
return false;
case 0xE0:
if (_Address < (0xE0000000 + L1_CACHE_SIZE))
return true;
case 0xCC:
case 0xCD:
case 0xC8:
return true;
}
return false;
}
void CheckForBadAddresses(u32 Address, u32 Data, bool Read, int Bits)
{
if (!ValidMemory(Address))
{
if(Read)
{
LOG(CONSOLE, "Read%i: Program tried to read [%08x] from [%08x]", Bits, Address);
//PanicAlert("Write_U32: Program tried to write [%08x] to [%08x]", _Address);
}
else
{
LOGV(CONSOLE, 0, "Write%i: Program tried to write [%08x] to [%08x]", Bits, Data, Address);
//PanicAlert("Read: Program tried to write [%08x] to [%08x]", Data, Address);
}
}
if (Address == 0)
{
if(Read)
{
LOGV(CONSOLE, 1, "Read%i: Program read [0x%08x] from [0x%08x] * * * 0 * * *", Bits, Data, Address);
//PanicAlert("Read: Program read [%08x] from [%08x]", Data, Address);
}
else
{
LOGV(CONSOLE, 1, "Write%i: Program wrote [0x%08x] to [0x%08x] * * * 0 * * *", Bits, Data, Address);
//PanicAlert("Read: Program wrote [%08x] to [%08x]", Data, Address);
}
}
/* Try to figure out where the dev/di Ioctl arguments are stored (including buffer out), so we can
find the bad one */
if(
Data == 0x1090f4c0 // good out buffer right before it, for sound/smashbros_sound.brsar
|| Data == 0x10913b00 // second one
|| Data == 0x7fd5d340 // first bad out buffer
|| Data == 0x133e00f8 // the address that store the bad 0x7fd5d340, this changes every time
|| Data == 0x2a24aa // menu2\sc_title_en.pac byte size
|| (
(PC == 0x8021347c || PC == 0x801f6a20 || PC == 0x800202d0 || PC == 0x80229964
|| PC == 0x801d88bc) /* this could be interesting, because the bad out buffer 0x7fd5d340
is 0x80000000 - size = 0x7fd5d340 perhaps some function read 0x80000000, I dunno */
&& Data == 0x80000000)
)
{
if(Read)
{
LOGV(CONSOLE, 0, "Read%i: Program read [0x%08x] from [0x%08x] * * * * * * * * * * * *", Bits, Data, Address);
//PanicAlert("Read%i: Program read [%08x] from [%08x]", Bits, Data, Address);
}
else
{
LOGV(CONSOLE, 0, "Write%i: Program wrote [0x%08x] to [0x%08x] * * * * * * * * * * * *", Bits,Data, Address);
//PanicAlert("Write%i: Program wrote [0x%08x] to [0x%08x]", Bits, Data, Address);
}
}
}
void CheckForBadAddresses8(u32 Address, u8 Data, bool Read)
{CheckForBadAddresses(Address, (u32)Data, Read, 8);}
void CheckForBadAddresses16(u32 Address, u16 Data, bool Read)
{CheckForBadAddresses(Address, (u32)Data, Read, 16);}
void CheckForBadAddresses32(u32 Address, u32 Data, bool Read)
{CheckForBadAddresses(Address, (u32)Data, Read, 32);}
void CheckForBadAddresses64(u32 Address, u64 Data, bool Read)
{CheckForBadAddresses(Address, (u32)Data, Read, 64);}
// =============
#define ReadFromHardware2(_var, _type, _Address, EffectiveAddress, flag) \ #define ReadFromHardware2(_var, _type, _Address, EffectiveAddress, flag) \
{ \ { \
if ((_Address & 0xC8000000) == 0xC8000000) \ if ((_Address & 0xC8000000) == 0xC8000000) \
@ -347,11 +480,13 @@ writeFn32 GetHWWriteFun32(const u32 _Address)
_var = bswap((*(u##_type*)&m_pRAM[tmpAddress & RAM_MASK])); \ _var = bswap((*(u##_type*)&m_pRAM[tmpAddress & RAM_MASK])); \
} \ } \
} \ } \
/* Uncomment this: CheckForBadAddresses##_type(_Address, _var, true);*/ \
} }
#define WriteToHardware2(_type, _Address, _Data, EffectiveAddress, flag) \ #define WriteToHardware2(_type, _Address, _Data, EffectiveAddress, flag) \
{ \ { \
/* Uncomment this: CheckForBadAddresses##_type(_Address, _Data, false);*/ \
if ((_Address & 0xC8000000) == 0xC8000000) \ if ((_Address & 0xC8000000) == 0xC8000000) \
{ \ { \
if (_Address < 0xcc000000) \ if (_Address < 0xcc000000) \
@ -666,8 +801,8 @@ u32 Read_U32(const u32 _Address)
#ifdef LOGGING #ifdef LOGGING
if (_Address == 0x00000000) if (_Address == 0x00000000)
{ {
PanicAlert("Program tried to read from [00000000]"); //PanicAlert("Program tried to read from [00000000]");
return 0x00000000; //return 0x00000000;
} }
#endif #endif
@ -1101,6 +1236,7 @@ void SDRUpdated()
u32 CheckDTLB(u32 _Address, XCheckTLBFlag _Flag) u32 CheckDTLB(u32 _Address, XCheckTLBFlag _Flag)
{ {
return 0;
if (Core::GetStartupParameter().bWii) { if (Core::GetStartupParameter().bWii) {
// TLB is never used on Wii (except linux and stuff, but we don't care about that) // TLB is never used on Wii (except linux and stuff, but we don't care about that)
PanicAlert("%s invalid memory region (0x%08x)\n\n" PanicAlert("%s invalid memory region (0x%08x)\n\n"

View File

@ -214,11 +214,15 @@ void ExecuteCommand(u32 _Address);
// =================================================== // ===================================================
/* This generates some kind of acknowledgment. This function is called from? */ /* This generates an acknowledgment to IPC calls. This function is called from
IPC_CONTROL_REGISTER requests in WII_IPC.cpp. The acknowledgment _Address will
start with 0x033e...., it will be for the _CommandAddress 0x133e...., from
debugging I also noticed that the Ioctl arguments are stored temporarily in
0x933e.... with the same .... as in the _CommandAddress. */
// ---------------- // ----------------
bool AckCommand(u32 _Address) bool AckCommand(u32 _Address)
{ {
Debugger::PrintCallstack(LogTypes::WII_IPC_HLE); //Debugger::PrintCallstack(LogTypes::WII_IPC_HLE);
LOG(WII_IPC_HLE, "AckCommand: 0%08x", _Address); LOG(WII_IPC_HLE, "AckCommand: 0%08x", _Address);
std::list<u32>::iterator itr = m_Ack.begin(); std::list<u32>::iterator itr = m_Ack.begin();

View File

@ -53,9 +53,9 @@ bool CWII_IPC_HLE_Device_di::Open(u32 _CommandAddress, u32 _Mode)
bool CWII_IPC_HLE_Device_di::IOCtl(u32 _CommandAddress) bool CWII_IPC_HLE_Device_di::IOCtl(u32 _CommandAddress)
{ {
LOG(WII_IPC_DVD, "*******************************"); LOGV(WII_IPC_DVD, 1, "*******************************");
LOG(WII_IPC_DVD, "CWII_IPC_DVD_Device_di::IOCtl"); LOGV(WII_IPC_DVD, 1, "CWII_IPC_DVD_Device_di::IOCtl");
LOG(WII_IPC_DVD, "*******************************"); LOGV(WII_IPC_DVD, 1, "*******************************");
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10); u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
@ -63,7 +63,7 @@ bool CWII_IPC_HLE_Device_di::IOCtl(u32 _CommandAddress)
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C); u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
LOG(WII_IPC_DVD, "%s - BufferIn(0x%08x, 0x%x) BufferOut(0x%08x, 0x%x)", GetDeviceName().c_str(), BufferIn, BufferInSize, BufferOut, BufferOutSize); LOG(WII_IPC_DVD, "%s - CommandAddress(0x%08x) BufferIn(0x%08x, 0x%x) BufferOut(0x%08x, 0x%x)", GetDeviceName().c_str(), _CommandAddress, BufferIn, BufferInSize, BufferOut, BufferOutSize);
u32 ReturnValue = ExecuteCommand(BufferIn, BufferInSize, BufferOut, BufferOutSize); u32 ReturnValue = ExecuteCommand(BufferIn, BufferInSize, BufferOut, BufferOutSize);
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
@ -191,7 +191,7 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32
case 0x86: case 0x86:
{ {
Memory::Memset(_BufferOut, 0, _BufferOutSize); Memory::Memset(_BufferOut, 0, _BufferOutSize);
LOG(WII_IPC_DVD, "%s executes DVDLowClearCoverInterrupt (Buffer 0x%08x, 0x%x)", GetDeviceName().c_str(), _BufferOut, _BufferOutSize); LOGV(WII_IPC_DVD, 1, "%s executes DVDLowClearCoverInterrupt (Buffer 0x%08x, 0x%x)", GetDeviceName().c_str(), _BufferOut, _BufferOutSize);
} }
break; break;

View File

@ -129,6 +129,7 @@ public:
// Write the Title ID to 0x00000000 // Write the Title ID to 0x00000000
Memory::Write_U32(TitleID, OutBuffer); Memory::Write_U32(TitleID, OutBuffer);
//Memory::Write_U32(0x00000000, OutBuffer);
LOG(WII_IPC_ES, "ES: IOCTL_ES_GETTITLEID: 0x%x", TitleID); LOG(WII_IPC_ES, "ES: IOCTL_ES_GETTITLEID: 0x%x", TitleID);
} }
@ -143,7 +144,7 @@ public:
u32 InBuffer = Memory::Read_U32(Buffer.InBuffer[0].m_Address); u32 InBuffer = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
// Should we write something here? // Should we write something here?
Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address); //Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address);
} }
break; break;
@ -155,7 +156,7 @@ public:
u32 InBuffer = Memory::Read_U32(Buffer.InBuffer[0].m_Address); u32 InBuffer = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
// Should we write something here? // Should we write something here?
Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address); //Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address);
} }
break; break;

View File

@ -301,7 +301,8 @@ void LogManager::Log(LogTypes::LOG_TYPE _type, const char *_fmt, ...)
&& m_LogSettings->bWriteMaster) && m_LogSettings->bWriteMaster)
fprintf(m_Log[ver*100 + LogTypes::MASTER_LOG]->m_pFile, "%s", Msg2); fprintf(m_Log[ver*100 + LogTypes::MASTER_LOG]->m_pFile, "%s", Msg2);
// Write now. Is this slower than caching it? /* In case it crashes write now to make sure you get the last messages.
Is this slower than caching it? */
//fflush(m_Log[id]->m_pFile); //fflush(m_Log[id]->m_pFile);
//fflush(m_Log[ver*100 + LogTypes::MASTER_LOG]->m_pFile); //fflush(m_Log[ver*100 + LogTypes::MASTER_LOG]->m_pFile);