Fixes some file handling in IPC_HLE
* change File::GetSize to fetch the size directly from the open file instead of stat'ing it when challed with a FILE* * use changed File::GetSize(FILE *f) instead of calling with file name in two places * remove "seek_pos % file_size" hack for ZTP, so one can seek to the end of file again. Please check Zelda: Twilight Princess for regressions * return error codes when reading or writing from/to a file A lot of those changes are from j4ck.fr0st, so kudos to him. I did not change the file open mode for ISFS_OPEN_WRITE to "wb". While that would probably be more correct, it says in the comment that it might affect Mario Kart Wii. I would prefer somebody with that game try that change locally first. Please check your games for regressions (or even improvement). Some games that may be affected are Zelda - Twilight Princess and Metroid Prime 3. Fixes issue 1749 git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6634 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
6cb78515c6
commit
38e80fe094
|
@ -362,7 +362,19 @@ u64 GetSize(const int fd)
|
||||||
// Overloaded GetSize, accepts FILE*
|
// Overloaded GetSize, accepts FILE*
|
||||||
u64 GetSize(FILE *f)
|
u64 GetSize(FILE *f)
|
||||||
{
|
{
|
||||||
return GetSize(fileno(f));
|
off_t pos = ftello(f);
|
||||||
|
if (fseeko(f, 0, SEEK_END) != 0) {
|
||||||
|
ERROR_LOG(COMMON, "GetSize: seek failed %p: %s",
|
||||||
|
f, GetLastErrorMsg());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
off_t size = ftello(f);
|
||||||
|
if ((size != pos) && (fseeko(f, pos, SEEK_SET) != 0)) {
|
||||||
|
ERROR_LOG(COMMON, "GetSize: seek failed %p: %s",
|
||||||
|
f, GetLastErrorMsg());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// creates an empty file filename, returns true on success
|
// creates an empty file filename, returns true on success
|
||||||
|
|
|
@ -138,8 +138,8 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode)
|
||||||
|
|
||||||
m_Filename = std::string(HLE_IPC_BuildFilename(m_Name.c_str(), 64));
|
m_Filename = std::string(HLE_IPC_BuildFilename(m_Name.c_str(), 64));
|
||||||
|
|
||||||
// AyuanX: I think file must exist before we can open it
|
// The file must exist before we can open it
|
||||||
// otherwise it should be created by FS, not here
|
// It should be created by ISFS_CreateFile, not here
|
||||||
if(File::Exists(m_Filename.c_str()))
|
if(File::Exists(m_Filename.c_str()))
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_FILEIO, "FileIO: Open %s (%s)", m_Name.c_str(), Modes[_Mode]);
|
INFO_LOG(WII_IPC_FILEIO, "FileIO: Open %s (%s)", m_Name.c_str(), Modes[_Mode]);
|
||||||
|
@ -161,7 +161,7 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode)
|
||||||
|
|
||||||
if (m_pFileHandle != NULL)
|
if (m_pFileHandle != NULL)
|
||||||
{
|
{
|
||||||
m_FileLength = (u32)File::GetSize(m_Filename.c_str());
|
m_FileLength = (u32)File::GetSize(m_pFileHandle);
|
||||||
ReturnValue = m_DeviceID;
|
ReturnValue = m_DeviceID;
|
||||||
}
|
}
|
||||||
else if (ReturnValue == 0)
|
else if (ReturnValue == 0)
|
||||||
|
@ -178,35 +178,21 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode)
|
||||||
|
|
||||||
bool CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress)
|
bool CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress)
|
||||||
{
|
{
|
||||||
u32 ReturnValue = 0;
|
u32 ReturnValue = FS_INVALID_ARGUMENT;
|
||||||
s32 SeekPosition = Memory::Read_U32(_CommandAddress + 0xC);
|
s32 SeekPosition = Memory::Read_U32(_CommandAddress + 0xC);
|
||||||
s32 Mode = Memory::Read_U32(_CommandAddress + 0x10);
|
s32 Mode = Memory::Read_U32(_CommandAddress + 0x10);
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_FILEIO, "FileIO: Old Seek Pos: 0x%08x, Mode: %i (%s, Length=0x%08x)", SeekPosition, Mode, m_Name.c_str(), m_FileLength);
|
INFO_LOG(WII_IPC_FILEIO, "FileIO: Seek Pos: 0x%08x, Mode: %i (%s, Length=0x%08x)", SeekPosition, Mode, m_Name.c_str(), m_FileLength);
|
||||||
|
|
||||||
// TODO : The following hack smells bad
|
/* TODO: Check if the new changes and the removed hack
|
||||||
/* Zelda - TP Fix: It doesn't make much sense but it works in Zelda - TP and
|
"magically" fixes Zelda - Twilight Princess as well */
|
||||||
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. */
|
|
||||||
|
|
||||||
s32 NewSeekPosition = SeekPosition;
|
|
||||||
if (m_FileLength > 0 && SeekPosition > (s32)m_FileLength && Mode == 0)
|
|
||||||
{
|
|
||||||
NewSeekPosition = SeekPosition % m_FileLength;
|
|
||||||
}
|
|
||||||
INFO_LOG(WII_IPC_FILEIO, "FileIO: New Seek Pos: 0x%08x, Mode: %i (%s)", NewSeekPosition, Mode, m_Name.c_str());
|
|
||||||
|
|
||||||
// Set seek mode
|
// 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 (fseeko(m_pFileHandle, NewSeekPosition, seek_mode[Mode]) == 0)
|
if (fseeko(m_pFileHandle, SeekPosition, seek_mode[Mode]) == 0)
|
||||||
{
|
{
|
||||||
ReturnValue = (u32)ftello(m_pFileHandle);
|
ReturnValue = (u32)ftello(m_pFileHandle);
|
||||||
}
|
}
|
||||||
|
@ -235,6 +221,7 @@ bool CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress)
|
||||||
{
|
{
|
||||||
INFO_LOG(WII_IPC_FILEIO, "FileIO: Read 0x%x bytes to 0x%08x from %s", Size, Address, m_Name.c_str());
|
INFO_LOG(WII_IPC_FILEIO, "FileIO: Read 0x%x bytes to 0x%08x from %s", Size, Address, m_Name.c_str());
|
||||||
ReturnValue = (u32)fread(Memory::GetPointer(Address), 1, Size, m_pFileHandle);
|
ReturnValue = (u32)fread(Memory::GetPointer(Address), 1, Size, m_pFileHandle);
|
||||||
|
if ((ReturnValue != Size) && ferror(m_pFileHandle)) ReturnValue = FS_EACCESS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -261,7 +248,7 @@ bool CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress)
|
||||||
#else
|
#else
|
||||||
(void)Result;
|
(void)Result;
|
||||||
#endif
|
#endif
|
||||||
ReturnValue = Size;
|
ReturnValue = (Result == 1) ? Size : FS_EACCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
|
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
|
||||||
|
@ -285,7 +272,7 @@ bool CWII_IPC_HLE_Device_FileIO::IOCtl(u32 _CommandAddress)
|
||||||
{
|
{
|
||||||
case ISFS_IOCTL_GETFILESTATS:
|
case ISFS_IOCTL_GETFILESTATS:
|
||||||
{
|
{
|
||||||
m_FileLength = (u32)File::GetSize(m_Filename.c_str());
|
m_FileLength = File::GetSize(m_pFileHandle);
|
||||||
u32 Position = (u32)ftello(m_pFileHandle);
|
u32 Position = (u32)ftello(m_pFileHandle);
|
||||||
|
|
||||||
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
|
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
|
||||||
|
|
Loading…
Reference in New Issue