diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp index c0aece3407..7b38639ade 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp @@ -87,6 +87,7 @@ CWII_IPC_HLE_Device_FileIO::CWII_IPC_HLE_Device_FileIO(u32 _DeviceID, const std: , m_pFileHandle(NULL) , m_FileLength(0) , m_Mode(0) + , m_SeekPos(0) { 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); - m_pFileHandle.Close(); + //m_pFileHandle.Close(); m_FileLength = 0; m_Mode = 0; @@ -117,7 +118,7 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode) u32 ReturnValue = 0; // close the file handle if we get a reopen - m_pFileHandle.Close(); + //m_pFileHandle.Close(); static const char* const Modes[] = { @@ -128,31 +129,14 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode) }; m_Filename = std::string(HLE_IPC_BuildFilename(m_Name.c_str(), 64)); - + + // The file must exist before we can open it // It should be created by ISFS_CreateFile, not here if(File::Exists(m_Filename)) { - INFO_LOG(WII_IPC_FILEIO, "FileIO: Open %s (%s)", m_Name.c_str(), Modes[_Mode]); - switch(_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", _Mode); - break; - } + INFO_LOG(WII_IPC_FILEIO, "FileIO: Open %s (%s == %08X)", m_Name.c_str(), Modes[_Mode], _Mode); + ReturnValue = m_DeviceID; } else { @@ -160,70 +144,99 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode) 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) Memory::Write_U32(ReturnValue, _CommandAddress+4); m_Active = 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) { u32 ReturnValue = FS_RESULT_FATAL; const s32 SeekPosition = Memory::Read_U32(_CommandAddress + 0xC); const s32 Mode = Memory::Read_U32(_CommandAddress + 0x10); - if (m_pFileHandle == NULL) - { - 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) + + if(OpenFile()) { + ReturnValue = FS_RESULT_FATAL; + 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); - - // Set seek mode - 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) + switch(Mode){ + case 0: { - ERROR_LOG(WII_IPC_FILEIO, "FILEIO: Seek past EOF - %s", m_Name.c_str()); - m_pFileHandle.Seek(curPos, SEEK_SET); + if(SeekPosition >=0 && SeekPosition <= fileSize) + { + 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 { - PanicAlert("CWII_IPC_HLE_Device_FileIO Unsupported seek mode %i", Mode); + ReturnValue = FS_FILE_NOT_EXIST; } - Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); 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 Size = Memory::Read_U32(_CommandAddress + 0x10); - if (m_pFileHandle != NULL) + + if(OpenFile()) { if (m_Mode == ISFS_OPEN_WRITE) { @@ -244,15 +258,24 @@ bool CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress) else { 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()); if (ReturnValue != Size && ferror(m_pFileHandle.GetHandle())) + { ReturnValue = FS_EACCESS; + } + else + { + m_SeekPos += Size; + } + } + CloseFile(); } 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); @@ -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 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) { @@ -275,9 +297,20 @@ bool CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress) } 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)) + { 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); @@ -296,20 +329,30 @@ bool CWII_IPC_HLE_Device_FileIO::IOCtl(u32 _CommandAddress) //u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14); //u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); //u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C); + + // Return Value + u32 ReturnValue = 0; // no error switch(Parameter) { case ISFS_IOCTL_GETFILESTATS: { - m_FileLength = (u32)m_pFileHandle.GetSize(); - const u32 Position = (u32)m_pFileHandle.Tell(); + if(OpenFile()) + { + m_FileLength = (u32)m_pFileHandle.GetSize(); - const u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); - 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); + const u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); + 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, m_SeekPos); - Memory::Write_U32(m_FileLength, BufferOut); - Memory::Write_U32(Position, BufferOut+4); + Memory::Write_U32(m_FileLength, BufferOut); + Memory::Write_U32(m_SeekPos, BufferOut+4); + CloseFile(); + } + else + { + ReturnValue = FS_FILE_NOT_EXIST; + } } 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); return true; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h index d1f51b7dfc..b7f3de3d62 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h @@ -39,6 +39,9 @@ public: bool IOCtl(u32 _CommandAddress); void DoState(PointerWrap &p); + bool OpenFile(); + void CloseFile(); + private: enum { @@ -77,6 +80,8 @@ private: u32 m_FileLength; u32 m_Mode; + u32 m_SeekPos; + std::string m_Filename; };