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
{
LOGV(WII_IPC_FILEIO, 0, "FS: New pDevice %s", _rDeviceName.c_str());
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 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
// 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());
Memory::Write_U32(0, _CommandAddress+4);
// Close always return 0 for success
Memory::Write_U32(0, _CommandAddress + 4);
return true;
}
bool
CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode)
{
LOG(WII_IPC_FILEIO, "FileIO::Open=======================================================");
LOG(WII_IPC_FILEIO, "===================================================================");
u32 ReturnValue = 0;
@ -88,8 +90,9 @@ CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _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 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;
default: PanicAlert("CWII_IPC_HLE_Device_FileIO: unknown open mode"); break;
}
@ -118,16 +121,17 @@ bool
CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress)
{
u32 ReturnValue = 0;
u32 SeekPosition = Memory::Read_U32(_CommandAddress +0xC);
u32 SeekPosition = Memory::Read_U32(_CommandAddress + 0xC);
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)
{
case 0:
fseek(m_pFileHandle, SeekPosition, SEEK_SET);
ReturnValue = 0;
// Seek always return the seek position for success
ReturnValue = SeekPosition;
break;
case 1: // cur
@ -177,6 +181,8 @@ CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress)
if (m_pFileHandle)
{
fwrite(Memory::GetPointer(Address), Size, 1, m_pFileHandle);
// Write always return the written bytes for success
ReturnValue = Size;
}

View File

@ -74,9 +74,34 @@ public:
virtual bool IOCtlV(u32 _CommandAddress)
{
LOG(WII_IPC_HLE, "%s", GetDeviceName().c_str());
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)
{
case IOCTL_ES_GETTITLEDIR: // ES_GetDataDir in DevKitPro
@ -94,7 +119,7 @@ public:
}
break;
case IOCTL_ES_GETTITLEID:
case IOCTL_ES_GETTITLEID: // ES_GetTitleID in DevKitPro
{
u32 OutBuffer = Memory::Read_U32(Buffer.PayloadBuffer[0].m_Address);
@ -102,6 +127,7 @@ public:
if (TitleID == 0)
TitleID = 0xF00DBEEF;
// Write the Title ID to 0x00000000
Memory::Write_U32(TitleID, OutBuffer);
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);
// Should we write something here?
//Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address);
Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address);
}
break;
@ -129,7 +155,7 @@ public:
u32 InBuffer = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
// Should we write something here?
//Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address);
Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address);
}
break;
@ -161,31 +187,7 @@ public:
break;
}
/* 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);
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
// Write return value (0 means OK)
Memory::Write_U32(0, _CommandAddress + 0x4);
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());
// check if this is really a directory
if (!File::IsDirectory(Filename.c_str()))
/* Check if this is really a directory. Or a file, because it seems like Mario Kart
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;
break;
}
@ -127,8 +130,6 @@ bool CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
}
else
{
memset(Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address), 0, CommandBuffer.PayloadBuffer[0].m_Size);
size_t numFile = FileSearch.GetFileNames().size();
@ -167,7 +168,7 @@ bool CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
u32 fsBlock = 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()))
{
// make a file search
@ -190,14 +191,14 @@ bool CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
ReturnValue = 0;
LOG(WII_IPC_FILEIO, " fsBlock: %i, iNodes: %i", fsBlock, iNodes);
LOGV(WII_IPC_FILEIO, 1, " fsBlock: %i, iNodes: %i", fsBlock, iNodes);
}
else
{
fsBlock = 0;
iNodes = 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);

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)
{
// Requests are made in this order by these games
// Mario Kart: 2, 1, f, 3
// SSBB: 2, 3
// -----------------------
/* Requests are made in this order by these games
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
//if(_Parameter == 2 || _Parameter == 3)
if(true)
{
u32 OutBuffer = Memory::Read_U32(_BufferOut);
if(_BufferInSize > 0)
{
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,
_BufferIn, InBuffer, _BufferInSize,
_BufferOut, OutBuffer, _BufferOutSize);
}
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,
_BufferOut, OutBuffer, _BufferOutSize);
}
@ -86,17 +91,21 @@ s32 CWII_IPC_HLE_Device_net_kd_request::ExecuteCommand(u32 _Parameter, u32 _Buff
switch(_Parameter)
{
case 1: // SuspendScheduler (Input: none, Output: 32 bytes)
Memory::Write_U32(0, _BufferOut);
//Memory::Write_U32(0, _BufferOut);
return -1;
break;
case 2: /* ExecTrySuspendScheduler (Input: 32 bytes, Output: 32 bytes). Sounds like it will check
if it should suspend the updates scheduler or not. */
Memory::Write_U32(1, _BufferOut);
//Memory::Write_U32(0, _BufferOut);
return -1;
break;
case 3: // ?
Memory::Write_U32(0, _BufferOut);
//Memory::Write_U32(0, _BufferOut);
return -1;
break;
case 0xf: // NWC24iRequestGenerateUserId (Input: none, Output: 32 bytes)
Memory::Write_U32(0, _BufferOut);
//Memory::Write_U32(0, _BufferOut);
return -1;
break;
default:
_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;
}
// Should we always return 0?
// We return a success for any potential unknown requests
return 0;
}
@ -135,8 +144,8 @@ bool CWII_IPC_HLE_Device_net_ncd_manage::IOCtlV(u32 _CommandAddress)
switch(CommandBuffer.Parameter)
{
default:
LOG(WII_IPC_NET, "CWII_IPC_HLE_Device_fs::IOCtlV: %i", CommandBuffer.Parameter);
_dbg_assert_msg_(WII_IPC_NET, 0, "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, "NET_NCD_MANAGE IOCtlV: %i", CommandBuffer.Parameter);
break;
}

View File

@ -301,6 +301,10 @@ void LogManager::Log(LogTypes::LOG_TYPE _type, const char *_fmt, ...)
&& m_LogSettings->bWriteMaster)
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
// 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)
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
// this limits the memory space used for the memory logs to MAX_MESSAGES rows