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:
parent
20b8277ee8
commit
4c7d20e555
|
@ -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"
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue