Mario Kart Wii now works if you use an old save file

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1318 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2008-11-28 11:50:55 +00:00
parent ca68a6f168
commit 1bc53f87dc
6 changed files with 96 additions and 61 deletions

View File

@ -163,6 +163,7 @@ IWII_IPC_HLE_Device* CreateDevice(u32 _DeviceID, const std::string& _rDeviceName
} }
else else
{ {
LOGV(WII_IPC_FILEIO, 0, "FS: New pDevice %s", _rDeviceName.c_str());
pDevice = new CWII_IPC_HLE_Device_FileIO(_DeviceID, _rDeviceName); pDevice = new CWII_IPC_HLE_Device_FileIO(_DeviceID, _rDeviceName);
} }
@ -228,7 +229,15 @@ void ExecuteCommand(u32 _Address)
u32 Mode = Memory::Read_U32(_Address+0x10); u32 Mode = Memory::Read_U32(_Address+0x10);
u32 DeviceID = GetDeviceIDByName(DeviceName); u32 DeviceID = GetDeviceIDByName(DeviceName);
if (DeviceID == 0)
/* TEMPORARY SOLUTION: For some reason no file was written after a ReOpen in
Mario Galaxy and Mario Kart Wii so I had to do a Open instead */
if (DeviceID == 0
|| DeviceName.find(".bin") != std::string::npos // Do Open instead for common
|| DeviceName.find(".dat") != std::string::npos // save game file types
|| DeviceName.find(".vff") != std::string::npos
|| DeviceName.find(".mod") != std::string::npos
)
{ {
// create the new device // create the new device
// alternatively we could pre create all devices and put them in a directory tree structure // alternatively we could pre create all devices and put them in a directory tree structure

View File

@ -61,14 +61,16 @@ CWII_IPC_HLE_Device_FileIO::Close(u32 _CommandAddress)
{ {
LOG(WII_IPC_FILEIO, "FileIO: Close %s", GetDeviceName().c_str()); LOG(WII_IPC_FILEIO, "FileIO: Close %s", GetDeviceName().c_str());
Memory::Write_U32(0, _CommandAddress+4); // Close always return 0 for success
Memory::Write_U32(0, _CommandAddress + 4);
return true; return true;
} }
bool bool
CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode) CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode)
{ {
LOG(WII_IPC_FILEIO, "FileIO::Open======================================================="); LOG(WII_IPC_FILEIO, "===================================================================");
u32 ReturnValue = 0; u32 ReturnValue = 0;
@ -88,8 +90,9 @@ CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode)
{ {
switch(_Mode) switch(_Mode)
{ {
// Do "r+b" for all writing to avoid truncating the file
case 0x01: m_pFileHandle = fopen(m_Filename.c_str(), "rb"); break; case 0x01: m_pFileHandle = fopen(m_Filename.c_str(), "rb"); break;
case 0x02: m_pFileHandle = fopen(m_Filename.c_str(), "wb"); break; case 0x02: //m_pFileHandle = fopen(m_Filename.c_str(), "wb"); break;
case 0x03: m_pFileHandle = fopen(m_Filename.c_str(), "r+b"); break; case 0x03: m_pFileHandle = fopen(m_Filename.c_str(), "r+b"); break;
default: PanicAlert("CWII_IPC_HLE_Device_FileIO: unknown open mode"); break; default: PanicAlert("CWII_IPC_HLE_Device_FileIO: unknown open mode"); break;
} }
@ -118,16 +121,17 @@ bool
CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress) CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress)
{ {
u32 ReturnValue = 0; u32 ReturnValue = 0;
u32 SeekPosition = Memory::Read_U32(_CommandAddress +0xC); u32 SeekPosition = Memory::Read_U32(_CommandAddress + 0xC);
u32 Mode = Memory::Read_U32(_CommandAddress +0x10); u32 Mode = Memory::Read_U32(_CommandAddress +0x10);
LOG(WII_IPC_FILEIO, "FileIO: Seek Pos: %i, Mode: %i(Device=%s)", SeekPosition, Mode, GetDeviceName().c_str()); LOG(WII_IPC_FILEIO, "FileIO: Seek Pos: %i, Mode: %i (Device=%s)", SeekPosition, Mode, GetDeviceName().c_str());
switch(Mode) switch(Mode)
{ {
case 0: case 0:
fseek(m_pFileHandle, SeekPosition, SEEK_SET); fseek(m_pFileHandle, SeekPosition, SEEK_SET);
ReturnValue = 0; // Seek always return the seek position for success
ReturnValue = SeekPosition;
break; break;
case 1: // cur case 1: // cur
@ -177,6 +181,8 @@ CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress)
if (m_pFileHandle) if (m_pFileHandle)
{ {
fwrite(Memory::GetPointer(Address), Size, 1, m_pFileHandle); fwrite(Memory::GetPointer(Address), Size, 1, m_pFileHandle);
// Write always return the written bytes for success
ReturnValue = Size; ReturnValue = Size;
} }

View File

@ -74,9 +74,34 @@ public:
virtual bool IOCtlV(u32 _CommandAddress) virtual bool IOCtlV(u32 _CommandAddress)
{ {
LOG(WII_IPC_HLE, "%s", GetDeviceName().c_str());
SIOCtlVBuffer Buffer(_CommandAddress); SIOCtlVBuffer Buffer(_CommandAddress);
LOG(WII_IPC_ES, "%s (0x%x)", GetDeviceName().c_str(), Buffer.Parameter);
/* Extended logs
//if(Buffer.Parameter == IOCTL_ES_GETTITLEDIR || Buffer.Parameter == IOCTL_ES_GETTITLEID ||
// Buffer.Parameter == IOCTL_ES_GETVIEWCNT || Buffer.Parameter == IOCTL_ES_GETTMDVIEWCNT)
{
u32 OutBuffer = Memory::Read_U32(Buffer.PayloadBuffer[0].m_Address | 0x80000000);
if(Buffer.NumberInBuffer > 0)
{
u32 InBuffer = Memory::Read_U32(Buffer.InBuffer[0].m_Address | 0x80000000);
LOG(WII_IPC_ES, "ES Parameter: 0x%x (In: %i, Out:%i) (In 0x%08x = 0x%08x %i) (Out 0x%08x = 0x%08x %i)",
Buffer.Parameter,
Buffer.NumberInBuffer, Buffer.NumberPayloadBuffer,
Buffer.InBuffer[0].m_Address, InBuffer, Buffer.InBuffer[0].m_Size,
Buffer.PayloadBuffer[0].m_Address, OutBuffer, Buffer.PayloadBuffer[0].m_Size);
}
else
{
LOG(WII_IPC_ES, "ES Parameter: 0x%x (In: %i, Out:%i) (Out 0x%08x = 0x%08x %i)",
Buffer.Parameter,
Buffer.NumberInBuffer, Buffer.NumberPayloadBuffer,
Buffer.PayloadBuffer[0].m_Address, OutBuffer, Buffer.PayloadBuffer[0].m_Size);
}
//DumpCommands(_CommandAddress, 8);
}*/
switch(Buffer.Parameter) switch(Buffer.Parameter)
{ {
case IOCTL_ES_GETTITLEDIR: // ES_GetDataDir in DevKitPro case IOCTL_ES_GETTITLEDIR: // ES_GetDataDir in DevKitPro
@ -94,7 +119,7 @@ public:
} }
break; break;
case IOCTL_ES_GETTITLEID: case IOCTL_ES_GETTITLEID: // ES_GetTitleID in DevKitPro
{ {
u32 OutBuffer = Memory::Read_U32(Buffer.PayloadBuffer[0].m_Address); u32 OutBuffer = Memory::Read_U32(Buffer.PayloadBuffer[0].m_Address);
@ -102,6 +127,7 @@ public:
if (TitleID == 0) if (TitleID == 0)
TitleID = 0xF00DBEEF; TitleID = 0xF00DBEEF;
// Write the Title ID to 0x00000000
Memory::Write_U32(TitleID, OutBuffer); Memory::Write_U32(TitleID, OutBuffer);
LOG(WII_IPC_ES, "ES: IOCTL_ES_GETTITLEID: 0x%x", TitleID); LOG(WII_IPC_ES, "ES: IOCTL_ES_GETTITLEID: 0x%x", TitleID);
@ -117,7 +143,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;
@ -129,7 +155,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;
@ -161,31 +187,7 @@ public:
break; break;
} }
/* Extended logs // Write return value (0 means OK)
//if(Buffer.Parameter == IOCTL_ES_GETTITLEDIR || Buffer.Parameter == IOCTL_ES_GETTITLEID ||
// Buffer.Parameter == IOCTL_ES_GETVIEWCNT || Buffer.Parameter == IOCTL_ES_GETTMDVIEWCNT)
{
u32 OutBuffer = Memory::Read_U32(Buffer.PayloadBuffer[0].m_Address);
if(Buffer.NumberInBuffer > 0)
{
u32 InBuffer = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
LOG(WII_IPC_ES, "ES Parameter: 0x%x (In: %i, Out:%i) (In 0x%08x = 0x%08x %i) (Out 0x%08x = 0x%08x %i)",
Buffer.Parameter,
Buffer.NumberInBuffer, Buffer.NumberPayloadBuffer,
Buffer.InBuffer[0].m_Address, InBuffer, Buffer.InBuffer[0].m_Size,
Buffer.PayloadBuffer[0].m_Address, OutBuffer, Buffer.PayloadBuffer[0].m_Size);
}
else
{
LOG(WII_IPC_ES, "ES Parameter: 0x%x (In: %i, Out:%i) (Out 0x%08x = 0x%08x %i)",
Buffer.Parameter,
Buffer.NumberInBuffer, Buffer.NumberPayloadBuffer,
Buffer.PayloadBuffer[0].m_Address, OutBuffer, Buffer.PayloadBuffer[0].m_Size);
}
//DumpCommands(_CommandAddress, 8);
} */
// write return value
Memory::Write_U32(0, _CommandAddress + 0x4); Memory::Write_U32(0, _CommandAddress + 0x4);
return true; return true;

View File

@ -100,10 +100,13 @@ bool CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
LOG(WII_IPC_FILEIO, "FS: IOCTL_READ_DIR %s", Filename.c_str()); LOG(WII_IPC_FILEIO, "FS: IOCTL_READ_DIR %s", Filename.c_str());
// check if this is really a directory /* Check if this is really a directory. Or a file, because it seems like Mario Kart
if (!File::IsDirectory(Filename.c_str())) did a IOCTL_READ_DIR on the save file to check if it existed before deleting it,
and if I returned a -something it never deleted the file presumably because it
thought it didn't exist. So this solution worked for Mario Kart. */
if (!File::Exists(Filename.c_str()) && !File::IsDirectory(Filename.c_str()))
{ {
LOG(WII_IPC_FILEIO, " Not a directory - return -6 (dunno if this is a correct return value)", Filename.c_str()); LOG(WII_IPC_FILEIO, " No file and not a directory - return -6 (dunno if this is a correct return value)", Filename.c_str());
ReturnValue = -6; ReturnValue = -6;
break; break;
} }
@ -127,8 +130,6 @@ bool CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
} }
else else
{ {
memset(Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address), 0, CommandBuffer.PayloadBuffer[0].m_Size); memset(Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address), 0, CommandBuffer.PayloadBuffer[0].m_Size);
size_t numFile = FileSearch.GetFileNames().size(); size_t numFile = FileSearch.GetFileNames().size();
@ -167,7 +168,7 @@ bool CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
u32 fsBlock = 0; u32 fsBlock = 0;
u32 iNodes = 0; u32 iNodes = 0;
LOG(WII_IPC_FILEIO, "FS: IOCTL_GETUSAGE %s", Filename.c_str()); LOGV(WII_IPC_FILEIO, 1, "FS: IOCTL_GETUSAGE %s", Filename.c_str());
if (File::IsDirectory(Filename.c_str())) if (File::IsDirectory(Filename.c_str()))
{ {
// make a file search // make a file search
@ -190,14 +191,14 @@ bool CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
ReturnValue = 0; ReturnValue = 0;
LOG(WII_IPC_FILEIO, " fsBlock: %i, iNodes: %i", fsBlock, iNodes); LOGV(WII_IPC_FILEIO, 1, " fsBlock: %i, iNodes: %i", fsBlock, iNodes);
} }
else else
{ {
fsBlock = 0; fsBlock = 0;
iNodes = 0; iNodes = 0;
ReturnValue = 0; ReturnValue = 0;
LOG(WII_IPC_FILEIO, " error: not executed on a valid directoy: %s", Filename.c_str()); LOGV(WII_IPC_FILEIO, 1, " error: not executed on a valid directoy: %s", Filename.c_str());
} }
Memory::Write_U32(fsBlock, CommandBuffer.PayloadBuffer[0].m_Address); Memory::Write_U32(fsBlock, CommandBuffer.PayloadBuffer[0].m_Address);

View File

@ -58,26 +58,31 @@ bool CWII_IPC_HLE_Device_net_kd_request::IOCtl(u32 _CommandAddress)
s32 CWII_IPC_HLE_Device_net_kd_request::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _BufferInSize, u32 _BufferOut, u32 _BufferOutSize) s32 CWII_IPC_HLE_Device_net_kd_request::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _BufferInSize, u32 _BufferOut, u32 _BufferOutSize)
{ {
// Requests are made in this order by these games // -----------------------
// Mario Kart: 2, 1, f, 3 /* Requests are made in this order by these games
// SSBB: 2, 3 Mario Kart: 2, 1, f, 3
SSBB: 2, 3
For Mario Kart I had to return -1 from at least 2, f and 3 to convince it that the network
was unavaliable and prevent if from looking for shared2/wc24 files (and do a PPCHalt when
it failed) */
// -------
/* Extended logs /* Extended logs
//if(_Parameter == 2 || _Parameter == 3) //if(_Parameter == 2 || _Parameter == 3)
if(true)
{ {
u32 OutBuffer = Memory::Read_U32(_BufferOut); u32 OutBuffer = Memory::Read_U32(_BufferOut);
if(_BufferInSize > 0) if(_BufferInSize > 0)
{ {
u32 InBuffer = Memory::Read_U32(_BufferIn); u32 InBuffer = Memory::Read_U32(_BufferIn);
LOG(WII_IPC_ES, "NET_KD_REQ: IOCtl Parameter: 0x%x (In 0x%08x = 0x%08x %i) (Out 0x%08x = 0x%08x %i)", LOG(WII_IPC_NET, "NET_KD_REQ: IOCtl Parameter: 0x%x (In 0x%08x = 0x%08x %i) (Out 0x%08x = 0x%08x %i)",
_Parameter, _Parameter,
_BufferIn, InBuffer, _BufferInSize, _BufferIn, InBuffer, _BufferInSize,
_BufferOut, OutBuffer, _BufferOutSize); _BufferOut, OutBuffer, _BufferOutSize);
} }
else else
{ {
LOG(WII_IPC_ES, "NET_KD_REQ: IOCtl Parameter: 0x%x (Out 0x%08x = 0x%08x %i)", LOG(WII_IPC_NET, "NET_KD_REQ: IOCtl Parameter: 0x%x (Out 0x%08x = 0x%08x %i)",
_Parameter, _Parameter,
_BufferOut, OutBuffer, _BufferOutSize); _BufferOut, OutBuffer, _BufferOutSize);
} }
@ -86,17 +91,21 @@ s32 CWII_IPC_HLE_Device_net_kd_request::ExecuteCommand(u32 _Parameter, u32 _Buff
switch(_Parameter) switch(_Parameter)
{ {
case 1: // SuspendScheduler (Input: none, Output: 32 bytes) case 1: // SuspendScheduler (Input: none, Output: 32 bytes)
Memory::Write_U32(0, _BufferOut); //Memory::Write_U32(0, _BufferOut);
return -1;
break; break;
case 2: /* ExecTrySuspendScheduler (Input: 32 bytes, Output: 32 bytes). Sounds like it will check case 2: /* ExecTrySuspendScheduler (Input: 32 bytes, Output: 32 bytes). Sounds like it will check
if it should suspend the updates scheduler or not. */ if it should suspend the updates scheduler or not. */
Memory::Write_U32(1, _BufferOut); //Memory::Write_U32(0, _BufferOut);
return -1;
break; break;
case 3: // ? case 3: // ?
Memory::Write_U32(0, _BufferOut); //Memory::Write_U32(0, _BufferOut);
return -1;
break; break;
case 0xf: // NWC24iRequestGenerateUserId (Input: none, Output: 32 bytes) case 0xf: // NWC24iRequestGenerateUserId (Input: none, Output: 32 bytes)
Memory::Write_U32(0, _BufferOut); //Memory::Write_U32(0, _BufferOut);
return -1;
break; break;
default: default:
_dbg_assert_msg_(WII_IPC_NET, 0, "/dev/net/kd/request::IOCtl request 0x%x (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", _dbg_assert_msg_(WII_IPC_NET, 0, "/dev/net/kd/request::IOCtl request 0x%x (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
@ -104,7 +113,7 @@ s32 CWII_IPC_HLE_Device_net_kd_request::ExecuteCommand(u32 _Parameter, u32 _Buff
break; break;
} }
// Should we always return 0? // We return a success for any potential unknown requests
return 0; return 0;
} }
@ -135,8 +144,8 @@ bool CWII_IPC_HLE_Device_net_ncd_manage::IOCtlV(u32 _CommandAddress)
switch(CommandBuffer.Parameter) switch(CommandBuffer.Parameter)
{ {
default: default:
LOG(WII_IPC_NET, "CWII_IPC_HLE_Device_fs::IOCtlV: %i", CommandBuffer.Parameter); LOG(WII_IPC_NET, "NET_NCD_MANAGE IOCtlV: %i", CommandBuffer.Parameter);
_dbg_assert_msg_(WII_IPC_NET, 0, "CWII_IPC_HLE_Device_fs::IOCtlV: %i", CommandBuffer.Parameter); _dbg_assert_msg_(WII_IPC_NET, 0, "NET_NCD_MANAGE IOCtlV: %i", CommandBuffer.Parameter);
break; break;
} }

View File

@ -301,6 +301,10 @@ 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?
//fflush(m_Log[id]->m_pFile);
//fflush(m_Log[ver*100 + LogTypes::MASTER_LOG]->m_pFile);
printf("%s", Msg2); // write to console screen printf("%s", Msg2); // write to console screen
// this limits the memory space used for the memory logs to MAX_MESSAGES rows // this limits the memory space used for the memory logs to MAX_MESSAGES rows
@ -329,6 +333,10 @@ void LogManager::Log(LogTypes::LOG_TYPE _type, const char *_fmt, ...)
&& m_LogSettings->bWriteMaster) && m_LogSettings->bWriteMaster)
fprintf(m_Log[i*100 + LogTypes::MASTER_LOG]->m_pFile, "%s", Msg2); fprintf(m_Log[i*100 + LogTypes::MASTER_LOG]->m_pFile, "%s", Msg2);
// Write now. Is this slower than caching it?
//fflush(m_Log[id]->m_pFile);
//fflush(m_Log[i*100 + LogTypes::MASTER_LOG]->m_pFile);
printf("%s", Msg2); // write to console screen printf("%s", Msg2); // write to console screen
// this limits the memory space used for the memory logs to MAX_MESSAGES rows // this limits the memory space used for the memory logs to MAX_MESSAGES rows