Wii IOS FileIO: Fixed bug "NewSeekPosition = 0" to "NewSeekPosition = SeekPosition", now Zelda TP savegames should work as well as other games

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1981 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2009-01-22 12:35:12 +00:00
parent e332e18ce6
commit d7fe42d069
1 changed files with 103 additions and 81 deletions

View File

@ -17,6 +17,7 @@
#include "Common.h" #include "Common.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "StringUtil.h"
#include "WII_IPC_HLE_Device_FileIO.h" #include "WII_IPC_HLE_Device_FileIO.h"
@ -39,19 +40,19 @@ std::string HLE_IPC_BuildFilename(const char* _pFilename, int _size)
} }
CWII_IPC_HLE_Device_FileIO::CWII_IPC_HLE_Device_FileIO(u32 _DeviceID, const std::string& _rDeviceName ) CWII_IPC_HLE_Device_FileIO::CWII_IPC_HLE_Device_FileIO(u32 _DeviceID, const std::string& _rDeviceName )
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
, m_pFileHandle(NULL) , m_pFileHandle(NULL)
, m_FileLength(0) , m_FileLength(0)
{ {
} }
CWII_IPC_HLE_Device_FileIO::~CWII_IPC_HLE_Device_FileIO() CWII_IPC_HLE_Device_FileIO::~CWII_IPC_HLE_Device_FileIO()
{ {
if (m_pFileHandle != NULL) if (m_pFileHandle != NULL)
{ {
fclose(m_pFileHandle); fclose(m_pFileHandle);
m_pFileHandle = NULL; m_pFileHandle = NULL;
} }
} }
bool bool
@ -92,7 +93,7 @@ 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 // 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;
@ -101,19 +102,19 @@ CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode)
} }
u32 ReturnValue = 0; u32 ReturnValue = 0;
if (m_pFileHandle != NULL) if (m_pFileHandle != NULL)
{ {
m_FileLength = File::GetSize(m_Filename.c_str()); m_FileLength = File::GetSize(m_Filename.c_str());
ReturnValue = GetDeviceID(); ReturnValue = GetDeviceID();
} }
else else
{ {
LOG(WII_IPC_FILEIO, " failed - File doesn't exist"); LOG(WII_IPC_FILEIO, " failed - File doesn't exist");
ReturnValue = -106; ReturnValue = -106;
} }
Memory::Write_U32(ReturnValue, _CommandAddress+4); Memory::Write_U32(ReturnValue, _CommandAddress+4);
return true; return true;
} }
bool bool
@ -123,58 +124,79 @@ CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress)
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: Old Seek Pos: %s, Mode: %i (Device=%s, FileSize=%s)", ThS(SeekPosition).c_str(), Mode, GetDeviceName().c_str(), ThS(m_FileLength).c_str());
/* Zelda - TP Fix: It doesn't make much sense but it works in Zelda - TP and
it's probably better than trying to read outside the file (it seeks to 0x6000 instead
of the correct 0x2000 for the second half of the file). Could this be right
or has it misunderstood the filesize somehow? My guess is that the filesize is
hardcoded in to the game, and it never checks the filesize, so I don't know.
Maybe it's wrong to return the seekposition when it's zero? Perhaps it wants
the filesize then? - No, that didn't work either, it seeks to 0x6000 even if I return
0x4000 from the first seek. */
u32 NewSeekPosition = SeekPosition;
if (m_FileLength > 0 && SeekPosition > m_FileLength && Mode == 0)
{
NewSeekPosition = SeekPosition % m_FileLength;
LOG(WII_IPC_FILEIO, "***********************************:");
}
LOG(WII_IPC_FILEIO, "FileIO: New Seek Pos: %s, Mode: %i (Device=%s)", ThS(NewSeekPosition).c_str(), Mode, GetDeviceName().c_str());
// Set seek mode
int seek_mode[3] = {SEEK_SET, SEEK_CUR, SEEK_END}; int seek_mode[3] = {SEEK_SET, SEEK_CUR, SEEK_END};
if (Mode >= 0 && Mode <= 2) { if (Mode >= 0 && Mode <= 2)
if (fseek(m_pFileHandle, SeekPosition, seek_mode[Mode]) == 0) { {
if (fseek(m_pFileHandle, NewSeekPosition, seek_mode[Mode]) == 0)
{
// Seek always return the seek position for success // Seek always return the seek position for success
// Not sure if it's right in all modes though. // Not sure if it's right in all modes though.
ReturnValue = SeekPosition; // What should we return for Zelda, the new correct or old incorrect seek position?
} else { ReturnValue = SeekPosition;
LOG(WII_IPC_FILEIO, "FILEIO: Seek failed"); } else {
} LOG(WII_IPC_FILEIO, "FILEIO: Seek failed");
}
} else { } else {
PanicAlert("CWII_IPC_HLE_Device_FileIO unsupported seek mode %i", Mode); PanicAlert("CWII_IPC_HLE_Device_FileIO unsupported seek mode %i", Mode);
} }
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
return true; return true;
} }
bool bool
CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress) CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress)
{ {
u32 ReturnValue = 0; u32 ReturnValue = 0;
u32 Address = Memory::Read_U32(_CommandAddress +0xC); u32 Address = Memory::Read_U32(_CommandAddress +0xC); // Read to this memory address
u32 Size = Memory::Read_U32(_CommandAddress +0x10); u32 Size = Memory::Read_U32(_CommandAddress +0x10);
if (m_pFileHandle != NULL) if (m_pFileHandle != NULL)
{ {
size_t readItems = fread(Memory::GetPointer(Address), 1, Size, m_pFileHandle); LOG(WII_IPC_FILEIO, "FileIO: Read 0x%x bytes to 0x%08x from %s", Size, Address, GetDeviceName().c_str());
ReturnValue = (u32)readItems; size_t readItems = fread(Memory::GetPointer(Address), 1, Size, m_pFileHandle);
LOG(WII_IPC_FILEIO, "FileIO reads from %s (Addr=0x%08x Size=0x%x)", GetDeviceName().c_str(), Address, Size); ReturnValue = (u32)readItems;
} }
else else
{ {
LOG(WII_IPC_FILEIO, "FileIO failed to read from %s (Addr=0x%08x Size=0x%x) - file not open", GetDeviceName().c_str(), Address, Size); LOG(WII_IPC_FILEIO, "FileIO failed to read from %s (Addr=0x%08x Size=0x%x) - file not open", GetDeviceName().c_str(), Address, Size);
} }
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
return true; return true;
} }
bool bool
CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress) CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress)
{ {
u32 ReturnValue = 0; u32 ReturnValue = 0;
u32 Address = Memory::Read_U32(_CommandAddress +0xC); u32 Address = Memory::Read_U32(_CommandAddress +0xC); // Write data from this memory address
u32 Size = Memory::Read_U32(_CommandAddress +0x10); u32 Size = Memory::Read_U32(_CommandAddress +0x10);
LOG(WII_IPC_FILEIO, "FileIO: Write Addr: 0x%08x Size: %i (Device=%s)", Address, Size, GetDeviceName().c_str()); LOG(WII_IPC_FILEIO, "FileIO: Write 0x%04x bytes to 0x%08x from %s", Size, Address, GetDeviceName().c_str());
if (m_pFileHandle) if (m_pFileHandle)
{ {
@ -184,52 +206,52 @@ CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress)
ReturnValue = Size; ReturnValue = Size;
} }
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
return true; return true;
} }
bool bool
CWII_IPC_HLE_Device_FileIO::IOCtl(u32 _CommandAddress) CWII_IPC_HLE_Device_FileIO::IOCtl(u32 _CommandAddress)
{ {
LOG(WII_IPC_FILEIO, "FileIO: IOCtl (Device=%s)", GetDeviceName().c_str()); LOG(WII_IPC_FILEIO, "FileIO: IOCtl (Device=%s)", GetDeviceName().c_str());
DumpCommands(_CommandAddress); DumpCommands(_CommandAddress);
u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC); u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC);
// u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10); // u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
// u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14); // u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
// 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);
switch(Parameter) switch(Parameter)
{ {
case ISFS_IOCTL_GETFILESTATS: case ISFS_IOCTL_GETFILESTATS:
{ {
u32 Position = (u32)ftell(m_pFileHandle); u32 Position = (u32)ftell(m_pFileHandle);
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
LOG(WII_IPC_FILEIO, "FileIO: ISFS_IOCTL_GETFILESTATS"); LOG(WII_IPC_FILEIO, "FileIO: ISFS_IOCTL_GETFILESTATS");
LOG(WII_IPC_FILEIO, " Length: %i Seek: %i", m_FileLength, Position); LOG(WII_IPC_FILEIO, " Length: %i Seek: %i", m_FileLength, Position);
Memory::Write_U32((u32)m_FileLength, BufferOut); Memory::Write_U32((u32)m_FileLength, BufferOut);
Memory::Write_U32(Position, BufferOut+4); Memory::Write_U32(Position, BufferOut+4);
} }
break; break;
default: default:
{ {
PanicAlert("CWII_IPC_HLE_Device_FileIO: Parameter %i", Parameter); PanicAlert("CWII_IPC_HLE_Device_FileIO: Parameter %i", Parameter);
} }
break; break;
} }
// Return Value // Return Value
u32 ReturnValue = 0; // no error u32 ReturnValue = 0; // no error
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
return true; return true;
} }
bool bool