diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 1aadd248e8..40feefd0b4 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -638,7 +638,7 @@ void __IoSchedSync(FileNode *f, int fd, int usec) { u64 param = ((u64)__KernelGetCurThread()) << 32 | fd; CoreTiming::ScheduleEvent(usToCycles(usec), syncNotifyEvent, param); - f->pendingAsyncResult = true; + f->pendingAsyncResult = false; f->hasAsyncResult = false; } @@ -742,7 +742,17 @@ bool __IoRead(int &result, int id, u32 data_addr, int size) { if (f->npdrm) { result = npdrmRead(f, data, size); return true; - } else if (__KernelIsDispatchEnabled() && ioManagerThreadEnabled && size > IO_THREAD_MIN_DATA_SIZE) { + } + + bool useThread = __KernelIsDispatchEnabled() && ioManagerThreadEnabled && size > IO_THREAD_MIN_DATA_SIZE; + if (useThread) { + // If there's a pending operation on this file, wait for it to finish and don't overwrite it. + useThread = !ioManager.HasOperation(f->handle); + if (!useThread) { + ioManager.SyncThread(); + } + } + if (useThread) { AsyncIOEvent ev = IO_EVENT_READ; ev.handle = f->handle; ev.buf = data; @@ -754,10 +764,13 @@ bool __IoRead(int &result, int id, u32 data_addr, int size) { return true; } } else { - ERROR_LOG_REPORT(SCEIO, "sceIoRead Reading into bad pointer %08x", data_addr); - // TODO: Returning 0 because it wasn't being sign-extended in async result before. - // What should this do? - result = 0; + if (size != 0) { + // TODO: For some combinations of bad pointer + size, SCE_KERNEL_ERROR_ILLEGAL_ADDR. + // Seems like only for kernel RAM. For most cases, it really is -1. + result = -1; + } else { + result = 0; + } return true; } } else { @@ -854,7 +867,16 @@ bool __IoWrite(int &result, int id, u32 data_addr, int size) { result = ERROR_KERNEL_BAD_FILE_DESCRIPTOR; return true; } - if (__KernelIsDispatchEnabled() && ioManagerThreadEnabled && size > IO_THREAD_MIN_DATA_SIZE) { + + bool useThread = __KernelIsDispatchEnabled() && ioManagerThreadEnabled && size > IO_THREAD_MIN_DATA_SIZE; + if (useThread) { + // If there's a pending operation on this file, wait for it to finish and don't overwrite it. + useThread = !ioManager.HasOperation(f->handle); + if (!useThread) { + ioManager.SyncThread(); + } + } + if (useThread) { AsyncIOEvent ev = IO_EVENT_WRITE; ev.handle = f->handle; ev.buf = (u8 *) data_ptr; @@ -1005,6 +1027,11 @@ u32 npdrmLseek(FileNode *f, s32 where, FileMove whence) s64 __IoLseekDest(FileNode *f, s64 offset, int whence, FileMove &seek) { seek = FILEMOVE_BEGIN; + // Let's make sure this isn't incorrect mid-operation. + if (ioManager.HasOperation(f->handle)) { + ioManager.SyncThread(); + } + s64 newPos = 0; switch (whence) { case 0: diff --git a/Core/HW/AsyncIOManager.cpp b/Core/HW/AsyncIOManager.cpp index 0bf29f1134..3ff26be160 100644 --- a/Core/HW/AsyncIOManager.cpp +++ b/Core/HW/AsyncIOManager.cpp @@ -21,6 +21,16 @@ #include "Core/HW/AsyncIOManager.h" #include "Core/FileSystems/MetaFileSystem.h" +bool AsyncIOManager::HasOperation(u32 handle) { + if (resultsPending_.find(handle) != resultsPending_.end()) { + return true; + } + if (results_.find(handle) != results_.end()) { + return true; + } + return false; +} + void AsyncIOManager::ScheduleOperation(AsyncIOEvent ev) { lock_guard guard(resultsLock_); if (!resultsPending_.insert(ev.handle).second) { diff --git a/Core/HW/AsyncIOManager.h b/Core/HW/AsyncIOManager.h index d2aacfa316..8fb96a16ee 100644 --- a/Core/HW/AsyncIOManager.h +++ b/Core/HW/AsyncIOManager.h @@ -51,6 +51,7 @@ class AsyncIOManager : public IOThreadEventQueue { public: void DoState(PointerWrap &p); + bool HasOperation(u32 handle); void ScheduleOperation(AsyncIOEvent ev); void Shutdown();