Fixes issue 2917 and possibly others like 5232

This commit is contained in:
Matthew Parlane 2012-03-06 23:10:04 +13:00
parent fb062c4a0b
commit 095b9de85e
2 changed files with 125 additions and 79 deletions

View File

@ -87,6 +87,7 @@ CWII_IPC_HLE_Device_FileIO::CWII_IPC_HLE_Device_FileIO(u32 _DeviceID, const std:
, m_pFileHandle(NULL) , m_pFileHandle(NULL)
, m_FileLength(0) , m_FileLength(0)
, m_Mode(0) , m_Mode(0)
, m_SeekPos(0)
{ {
Common::ReadReplacements(replacements); Common::ReadReplacements(replacements);
} }
@ -99,7 +100,7 @@ bool CWII_IPC_HLE_Device_FileIO::Close(u32 _CommandAddress, bool _bForce)
{ {
INFO_LOG(WII_IPC_FILEIO, "FileIO: Close %s (DeviceID=%08x)", m_Name.c_str(), m_DeviceID); INFO_LOG(WII_IPC_FILEIO, "FileIO: Close %s (DeviceID=%08x)", m_Name.c_str(), m_DeviceID);
m_pFileHandle.Close(); //m_pFileHandle.Close();
m_FileLength = 0; m_FileLength = 0;
m_Mode = 0; m_Mode = 0;
@ -117,7 +118,7 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode)
u32 ReturnValue = 0; u32 ReturnValue = 0;
// close the file handle if we get a reopen // close the file handle if we get a reopen
m_pFileHandle.Close(); //m_pFileHandle.Close();
static const char* const Modes[] = static const char* const Modes[] =
{ {
@ -129,30 +130,13 @@ 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));
// The file must exist before we can open it // The file must exist before we can open it
// It should be created by ISFS_CreateFile, not here // It should be created by ISFS_CreateFile, not here
if(File::Exists(m_Filename)) if(File::Exists(m_Filename))
{ {
INFO_LOG(WII_IPC_FILEIO, "FileIO: Open %s (%s)", m_Name.c_str(), Modes[_Mode]); INFO_LOG(WII_IPC_FILEIO, "FileIO: Open %s (%s == %08X)", m_Name.c_str(), Modes[_Mode], _Mode);
switch(_Mode) ReturnValue = m_DeviceID;
{
case ISFS_OPEN_READ:
m_pFileHandle.Open(m_Filename, "rb");
break;
// "r+b" is technically wrong, but OPEN_WRITE should not truncate the file as "wb" does.
case ISFS_OPEN_WRITE:
m_pFileHandle.Open(m_Filename, "r+b");
break;
case ISFS_OPEN_RW:
m_pFileHandle.Open(m_Filename, "r+b");
break;
default:
PanicAlertT("FileIO: Unknown open mode : 0x%02x", _Mode);
break;
}
} }
else else
{ {
@ -160,70 +144,99 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode)
ReturnValue = FS_FILE_NOT_EXIST; ReturnValue = FS_FILE_NOT_EXIST;
} }
if (m_pFileHandle != NULL)
{
m_FileLength = (u32)m_pFileHandle.GetSize();
ReturnValue = m_DeviceID;
}
else if (ReturnValue == 0)
{
ERROR_LOG(WII_IPC_FILEIO, " FileIO failed open: %s (%s) - I/O Error", m_Filename.c_str(), Modes[_Mode]);
ReturnValue = FS_RESULT_FATAL;
}
if (_CommandAddress) if (_CommandAddress)
Memory::Write_U32(ReturnValue, _CommandAddress+4); Memory::Write_U32(ReturnValue, _CommandAddress+4);
m_Active = true; m_Active = true;
return true; return true;
} }
bool CWII_IPC_HLE_Device_FileIO::OpenFile()
{
switch(m_Mode)
{
case ISFS_OPEN_READ:
m_pFileHandle.Open(m_Filename, "rb");
break;
// "r+b" is technically wrong, but OPEN_WRITE should not truncate the file as "wb" does.
case ISFS_OPEN_WRITE:
m_pFileHandle.Open(m_Filename, "r+b");
break;
case ISFS_OPEN_RW:
m_pFileHandle.Open(m_Filename, "r+b");
break;
default:
PanicAlertT("FileIO: Unknown open mode : 0x%02x", m_Mode);
break;
}
return m_pFileHandle.IsOpen();
}
void CWII_IPC_HLE_Device_FileIO::CloseFile()
{
m_pFileHandle.Close();
}
bool CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress) bool CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress)
{ {
u32 ReturnValue = FS_RESULT_FATAL; u32 ReturnValue = FS_RESULT_FATAL;
const s32 SeekPosition = Memory::Read_U32(_CommandAddress + 0xC); const s32 SeekPosition = Memory::Read_U32(_CommandAddress + 0xC);
const s32 Mode = Memory::Read_U32(_CommandAddress + 0x10); const s32 Mode = Memory::Read_U32(_CommandAddress + 0x10);
if (m_pFileHandle == NULL)
{ if(OpenFile())
ERROR_LOG(WII_IPC_FILEIO, "FILEIO: Seek failed because of null file handle - %s", m_Name.c_str());
ReturnValue = FS_FILE_NOT_EXIST;
}
else if (Mode >= 0 && Mode <= 2)
{ {
ReturnValue = FS_RESULT_FATAL;
const u64 fileSize = m_pFileHandle.GetSize(); const u64 fileSize = m_pFileHandle.GetSize();
INFO_LOG(WII_IPC_FILEIO, "FileIO: Seek Pos: 0x%08x, Mode: %i (%s, Length=0x%08llx)", SeekPosition, Mode, m_Name.c_str(), fileSize); INFO_LOG(WII_IPC_FILEIO, "FileIO: Seek Pos: 0x%08x, Mode: %i (%s, Length=0x%08llx)", SeekPosition, Mode, m_Name.c_str(), fileSize);
switch(Mode){
// Set seek mode case 0:
int seek_mode[3] = {SEEK_SET, SEEK_CUR, SEEK_END};
// POSIX allows seek past EOF, the Wii does not.
// TODO: Can we check this without tell'ing/seek'ing twice?
const u64 curPos = m_pFileHandle.Tell();
if (m_pFileHandle.Seek(SeekPosition, seek_mode[Mode]))
{
const u64 newPos = m_pFileHandle.Tell();
if (newPos > fileSize)
{ {
ERROR_LOG(WII_IPC_FILEIO, "FILEIO: Seek past EOF - %s", m_Name.c_str()); if(SeekPosition >=0 && SeekPosition <= fileSize)
m_pFileHandle.Seek(curPos, SEEK_SET); {
m_SeekPos = SeekPosition;
ReturnValue = m_SeekPos;
}
break;
}
case 1:
{
s32 wantedPos = SeekPosition+m_SeekPos;
if(wantedPos >=0 && wantedPos <= fileSize)
{
m_SeekPos = wantedPos;
ReturnValue = m_SeekPos;
}
break;
}
case 2:
{
s32 wantedPos = fileSize+m_SeekPos;
if(wantedPos >=0 && wantedPos <= fileSize)
{
m_SeekPos = wantedPos;
ReturnValue = m_SeekPos;
}
break;
}
default:
{
PanicAlert("CWII_IPC_HLE_Device_FileIO Unsupported seek mode %i", Mode);
ReturnValue = FS_RESULT_FATAL;
break;
} }
else
ReturnValue = (u32)newPos;
}
else
{
// Must clear the failbits, since subsequent seeks don't care about
// past failure on Wii
m_pFileHandle.Clear();
ERROR_LOG(WII_IPC_FILEIO, "FILEIO: Seek failed - %s", m_Name.c_str());
} }
CloseFile();
} }
else else
{ {
PanicAlert("CWII_IPC_HLE_Device_FileIO Unsupported seek mode %i", Mode); ReturnValue = FS_FILE_NOT_EXIST;
} }
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
return true; return true;
@ -235,7 +248,8 @@ bool CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress)
const u32 Address = Memory::Read_U32(_CommandAddress + 0xC); // Read to this memory address const u32 Address = Memory::Read_U32(_CommandAddress + 0xC); // Read to this memory address
const u32 Size = Memory::Read_U32(_CommandAddress + 0x10); const u32 Size = Memory::Read_U32(_CommandAddress + 0x10);
if (m_pFileHandle != NULL)
if(OpenFile())
{ {
if (m_Mode == ISFS_OPEN_WRITE) if (m_Mode == ISFS_OPEN_WRITE)
{ {
@ -244,15 +258,24 @@ bool CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress)
else else
{ {
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());
m_pFileHandle.Seek(m_SeekPos, SEEK_SET);
ReturnValue = (u32)fread(Memory::GetPointer(Address), 1, Size, m_pFileHandle.GetHandle()); ReturnValue = (u32)fread(Memory::GetPointer(Address), 1, Size, m_pFileHandle.GetHandle());
if (ReturnValue != Size && ferror(m_pFileHandle.GetHandle())) if (ReturnValue != Size && ferror(m_pFileHandle.GetHandle()))
{
ReturnValue = FS_EACCESS; ReturnValue = FS_EACCESS;
}
else
{
m_SeekPos += Size;
}
} }
CloseFile();
} }
else else
{ {
ERROR_LOG(WII_IPC_FILEIO, "FileIO: Failed to read from %s (Addr=0x%08x Size=0x%x) - file not open", m_Name.c_str(), Address, Size); ERROR_LOG(WII_IPC_FILEIO, "FileIO: Failed to read from %s (Addr=0x%08x Size=0x%x) - file could not be opened or does not exist", m_Name.c_str(), Address, Size);
ReturnValue = FS_FILE_NOT_EXIST;
} }
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
@ -265,9 +288,8 @@ bool CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress)
const u32 Address = Memory::Read_U32(_CommandAddress + 0xC); // Write data from this memory address const u32 Address = Memory::Read_U32(_CommandAddress + 0xC); // Write data from this memory address
const u32 Size = Memory::Read_U32(_CommandAddress + 0x10); const u32 Size = Memory::Read_U32(_CommandAddress + 0x10);
INFO_LOG(WII_IPC_FILEIO, "FileIO: Write 0x%04x bytes from 0x%08x to %s", Size, Address, m_Name.c_str());
if (m_pFileHandle) if(OpenFile())
{ {
if (m_Mode == ISFS_OPEN_READ) if (m_Mode == ISFS_OPEN_READ)
{ {
@ -275,9 +297,20 @@ bool CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress)
} }
else else
{ {
INFO_LOG(WII_IPC_FILEIO, "FileIO: Write 0x%04x bytes from 0x%08x to %s", Size, Address, m_Name.c_str());
m_pFileHandle.Seek(m_SeekPos, SEEK_SET);
if (m_pFileHandle.WriteBytes(Memory::GetPointer(Address), Size)) if (m_pFileHandle.WriteBytes(Memory::GetPointer(Address), Size))
{
ReturnValue = Size; ReturnValue = Size;
m_SeekPos += Size;
}
} }
CloseFile();
}
else
{
ERROR_LOG(WII_IPC_FILEIO, "FileIO: Failed to read from %s (Addr=0x%08x Size=0x%x) - file could not be opened or does not exist", m_Name.c_str(), Address, Size);
ReturnValue = FS_FILE_NOT_EXIST;
} }
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
@ -297,19 +330,29 @@ bool CWII_IPC_HLE_Device_FileIO::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);
// Return Value
u32 ReturnValue = 0; // no error
switch(Parameter) switch(Parameter)
{ {
case ISFS_IOCTL_GETFILESTATS: case ISFS_IOCTL_GETFILESTATS:
{ {
m_FileLength = (u32)m_pFileHandle.GetSize(); if(OpenFile())
const u32 Position = (u32)m_pFileHandle.Tell(); {
m_FileLength = (u32)m_pFileHandle.GetSize();
const u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); const u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
INFO_LOG(WII_IPC_FILEIO, "FileIO: ISFS_IOCTL_GETFILESTATS"); INFO_LOG(WII_IPC_FILEIO, "FileIO: ISFS_IOCTL_GETFILESTATS");
INFO_LOG(WII_IPC_FILEIO, " File: %s, Length: %i, Pos: %i", m_Name.c_str(), m_FileLength, Position); INFO_LOG(WII_IPC_FILEIO, " File: %s, Length: %i, Pos: %i", m_Name.c_str(), m_FileLength, m_SeekPos);
Memory::Write_U32(m_FileLength, BufferOut); Memory::Write_U32(m_FileLength, BufferOut);
Memory::Write_U32(Position, BufferOut+4); Memory::Write_U32(m_SeekPos, BufferOut+4);
CloseFile();
}
else
{
ReturnValue = FS_FILE_NOT_EXIST;
}
} }
break; break;
@ -321,8 +364,6 @@ bool CWII_IPC_HLE_Device_FileIO::IOCtl(u32 _CommandAddress)
} }
// Return Value
const u32 ReturnValue = 0; // no error
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
return true; return true;

View File

@ -39,6 +39,9 @@ public:
bool IOCtl(u32 _CommandAddress); bool IOCtl(u32 _CommandAddress);
void DoState(PointerWrap &p); void DoState(PointerWrap &p);
bool OpenFile();
void CloseFile();
private: private:
enum enum
{ {
@ -77,6 +80,8 @@ private:
u32 m_FileLength; u32 m_FileLength;
u32 m_Mode; u32 m_Mode;
u32 m_SeekPos;
std::string m_Filename; std::string m_Filename;
}; };