From c5e0dafa44995b907a433d5cf6e9fbdfa4d59a44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 25 May 2023 10:01:27 +0200 Subject: [PATCH] Fix "double delay" error in sceNpDrmEdataSetupKey --- Core/FileSystems/MetaFileSystem.cpp | 2 +- Core/HLE/HLE.h | 6 ++---- Core/HLE/sceIo.cpp | 23 +++++++++++++---------- Core/HLE/sceIo.h | 5 +++++ Core/HLE/scePspNpDrm_user.cpp | 14 ++++++++++---- 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 395fea433c..c35f0e59ef 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -575,7 +575,7 @@ size_t MetaFileSystem::SeekFile(u32 handle, s32 position, FileMove type) std::lock_guard guard(lock); IFileSystem *sys = GetHandleOwner(handle); if (sys) - return sys->SeekFile(handle,position,type); + return sys->SeekFile(handle, position, type); else return 0; } diff --git a/Core/HLE/HLE.h b/Core/HLE/HLE.h index 0331fb7b9b..0ddba13b6f 100644 --- a/Core/HLE/HLE.h +++ b/Core/HLE/HLE.h @@ -130,13 +130,11 @@ u64 hleDelayResult(u64 result, const char *reason, int usec); void hleEatCycles(int cycles); void hleEatMicro(int usec); -inline int hleDelayResult(int result, const char *reason, int usec) -{ +inline int hleDelayResult(int result, const char *reason, int usec) { return hleDelayResult((u32) result, reason, usec); } -inline s64 hleDelayResult(s64 result, const char *reason, int usec) -{ +inline s64 hleDelayResult(s64 result, const char *reason, int usec) { return hleDelayResult((u64) result, reason, usec); } diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index d1d83ba453..30bc1170e0 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -2533,7 +2533,7 @@ static u32 sceIoDclose(int id) { return kernelObjects.Destroy(id); } -static int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) { +int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) { u32 error; FileNode *f = __IoGetFd(id, error); if (error) { @@ -2546,7 +2546,7 @@ static int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, } // TODO: Move this into each command, probably? - usec = 100; + usec += 100; //KD Hearts: //56:46:434 HLE\sceIo.cpp:886 E[HLE]: UNIMPL 0=sceIoIoctrl id: 0000011f, cmd 04100001, indataPtr 08b313d8, inlen 00000010, outdataPtr 00000000, outLen 0 @@ -2574,25 +2574,28 @@ static int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, pspFileSystem.SeekFile(f->handle, (s32)f->pgd_offset, FILEMOVE_BEGIN); pspFileSystem.ReadFile(f->handle, pgd_header, 0x90); f->pgdInfo = pgd_open(pgd_header, 2, key_ptr); - if(f->pgdInfo==NULL){ - ERROR_LOG(SCEIO, "Not a valid PGD file. Open as normal file."); + if (!f->pgdInfo) { + ERROR_LOG(SCEIO, "Not a valid PGD file. Examining."); f->npdrm = false; pspFileSystem.SeekFile(f->handle, (s32)0, FILEMOVE_BEGIN); - if(memcmp(pgd_header, pgd_magic, 4)==0){ + if (memcmp(pgd_header, pgd_magic, 4) == 0) { + ERROR_LOG(SCEIO, "File is PGD file, but there's likely a key mismatch. Returning error."); // File is PGD file, but key mismatch return ERROR_PGD_INVALID_HEADER; - }else{ + } else { + WARN_LOG(SCEIO, "File is not encrypted, proceeding."); // File is decrypted. return 0; } - }else{ - // Everthing OK. + } else { + // Everything OK. f->npdrm = true; f->pgdInfo->data_offset += f->pgd_offset; return 0; } break; } + // Set PGD offset. Called from sceNpDrmEdataSetupKey case 0x04100002: f->pgd_offset = indataPtr; @@ -2739,7 +2742,7 @@ static int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, // Even if the size is 4, it still actually reads a 16 byte struct, it seems. //if (GetIOTimingMethod() == IOTIMING_REALISTIC) // Need a check for io timing method? - usec = 15000;// Fantasy Golf Pangya Portable(KS) needs a delay over 15000us. + usec += 15000;// Fantasy Golf Pangya Portable(KS) needs a delay over 15000us. if (Memory::IsValidAddress(indataPtr) && inlen >= 4) { struct SeekInfo { @@ -2928,7 +2931,7 @@ static int IoAsyncFinish(int id) { break; case IoAsyncOp::IOCTL: - us = 100; + us = 0; // __IoIoctl will add 100. f->asyncResult = __IoIoctl(id, params.ioctl.cmd, params.ioctl.inAddr, params.ioctl.inSize, params.ioctl.outAddr, params.ioctl.outSize, us); DEBUG_LOG(SCEIO, "ASYNC sceIoIoctlAsync(%08x, %08x, %08x, %08x, %08x, %08x)", id, params.ioctl.cmd, params.ioctl.inAddr, params.ioctl.inSize, params.ioctl.outAddr, params.ioctl.outSize); break; diff --git a/Core/HLE/sceIo.h b/Core/HLE/sceIo.h index 3169efe904..d6a4d6a824 100644 --- a/Core/HLE/sceIo.h +++ b/Core/HLE/sceIo.h @@ -29,6 +29,11 @@ struct tm; u32 sceIoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen); +// Called by sceIoIoctl, which normally applies the delay this function writes to usec. +// If you need to call sceIoIoctl from a HLE function implementation more than once, use +// __IoIoctl directly to avoid double-delays. +int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec); + u32 __IoGetFileHandleFromId(u32 id, u32 &outError); void __IoCopyDate(ScePspDateTime& date_out, const tm& date_in); diff --git a/Core/HLE/scePspNpDrm_user.cpp b/Core/HLE/scePspNpDrm_user.cpp index 6b844a1de0..f35f6b5239 100644 --- a/Core/HLE/scePspNpDrm_user.cpp +++ b/Core/HLE/scePspNpDrm_user.cpp @@ -25,10 +25,16 @@ static int sceNpDrmRenameCheck(const char *filename) static int sceNpDrmEdataSetupKey(u32 edataFd) { INFO_LOG(HLE, "call sceNpDrmEdataSetupKey %x", edataFd); - /* set PGD offset */ - sceIoIoctl(edataFd, 0x04100002, 0x90, 0, 0, 0); - /* call PGD open */ - return sceIoIoctl(edataFd, 0x04100001, 0, 0, 0, 0); + int usec = 0; + // set PGD offset + int retval = __IoIoctl(edataFd, 0x04100002, 0x90, 0, 0, 0, usec); + if (retval != 0) { + return hleDelayResult(retval, "io ctrl command", usec); + } + // call PGD open + // Note that usec accumulates. + retval = __IoIoctl(edataFd, 0x04100001, 0, 0, 0, 0, usec); + return hleDelayResult(retval, "io ctrl command", usec); } static int sceNpDrmEdataGetDataSize(u32 edataFd)