Fixes issue 2917 and possibly others like 5232
This commit is contained in:
parent
e8e2c241d7
commit
53d2d9718f
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue