diff --git a/Core/ELF/PBPReader.cpp b/Core/ELF/PBPReader.cpp index 96f9819352..cdcb9c963f 100644 --- a/Core/ELF/PBPReader.cpp +++ b/Core/ELF/PBPReader.cpp @@ -79,6 +79,17 @@ bool PBPReader::GetSubFile(PBPSubFile file, std::vector *out) const { return true; } +bool PBPReader::ReadSubFile(PBPSubFile file, u32 offset, size_t size, void *out) const { + if (!file_) { + return false; + } + const size_t subFileSize = GetSubFileSize(file); + if (offset > subFileSize || size > subFileSize - offset) { + return false; + } + return file_->ReadAt(header_.offsets[(int)file] + offset, size, out) == size; +} + bool PBPReader::GetSubFileAsString(PBPSubFile file, std::string *out) const { if (!file_) { out->clear(); diff --git a/Core/ELF/PBPReader.h b/Core/ELF/PBPReader.h index 8781aa66a7..b11ff11baa 100644 --- a/Core/ELF/PBPReader.h +++ b/Core/ELF/PBPReader.h @@ -53,6 +53,8 @@ public: bool GetSubFile(PBPSubFile file, std::vector *out) const; bool GetSubFileAsString(PBPSubFile file, std::string *out) const; + // Part of a subfile, for the large ones. False if it doesn't lie within it. + bool ReadSubFile(PBPSubFile file, u32 offset, size_t size, void *out) const; size_t GetSubFileSize(PBPSubFile file) const { const int num = (int)file; diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index b7d8719efa..74b523ae0f 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -2755,14 +2755,17 @@ int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 out f->pgdInfo = pgd_open(kirk, pgd_header, 2, key_ptr); if (!f->pgdInfo) { f->npdrm = false; + const u32 plainOffset = f->pgd_offset; f->pgd_offset = 0; // Reset PGD offset so file can be read as regular file - pspFileSystem.SeekFile(f->handle, (s32)0, FILEMOVE_BEGIN); if (memcmp(pgd_header, pgd_magic, 4) == 0) { + pspFileSystem.SeekFile(f->handle, (s32)0, FILEMOVE_BEGIN); // File is PGD file, but key mismatch ERROR_LOG(Log::sceIo, "%s is PGD file, but there's likely a key mismatch. Returning error.", f->fullpath.c_str()); return SCE_ERROR_PGD_INVALID_HEADER; } else { - // File is not encrypted. + // File is not encrypted. Read from where the PGD would start (0 for an ordinary file): a + // converted PS1 PBP's disc image is plain, and POPS reads it right after this. + pspFileSystem.SeekFile(f->handle, (s32)plainOffset, FILEMOVE_BEGIN); WARN_LOG(Log::sceIo, "%s is not an encrypted PGD file as was expected. Proceeding anyway.", f->fullpath.c_str()); return 0; } @@ -2777,7 +2780,13 @@ int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 out // Set PGD offset. Called from sceNpDrmEdataSetupKey case 0x04100002: - f->pgd_offset = indataPtr; + // The POPS manager passes a pointer to the offset, with inlen 4. Our sceNpDrmEdataSetupKey + // passes the offset itself. + if (inlen == 4 && Memory::IsValidRange(indataPtr, 4)) { + f->pgd_offset = Memory::ReadUnchecked_U32(indataPtr); + } else { + f->pgd_offset = indataPtr; + } break; // Get PGD data size. Called from sceNpDrmEdataGetDataSize diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index a2f0c96f7e..f6c2ce98cf 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -919,6 +919,11 @@ const HLEFunction ThreadManForUser[] = {0x65F54FFB, &WrapI_IUU<_sceKernelAllocateTlspl>, "_sceKernelAllocateTlspl", 'i', "ixp" }, }; +// The type picks one of the kernel's preset stack sizes. This is enough for any of them. +static u32 sceKernelExtendKernelStack(MIPSState *mipsState, int type, u32 cb, u32 arg) { + return sceKernelExtendThreadStack(mipsState, 0x4000, cb, arg); +} + const HLEFunction ThreadManForKernel[] = { {0xCEADEB47, &WrapI_U, "sceKernelDelayThread", 'i', "x", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED | HLE_KERNEL_SYSCALL }, @@ -973,7 +978,7 @@ const HLEFunction ThreadManForKernel[] = {0xB736E9FF, &WrapI_IU, "sceKernelFreeVpl", 'i', "ix", HLE_KERNEL_SYSCALL }, {0x1D371B8A, &WrapI_IU, "sceKernelCancelVpl", 'i', "ix", HLE_KERNEL_SYSCALL }, {0x39810265, &WrapI_IU, "sceKernelReferVplStatus", 'i', "ip", HLE_KERNEL_SYSCALL }, - {0xBC31C1B9, nullptr, "sceKernelExtendKernelStack"}, + {0xBC31C1B9, &WrapU_IUU, "sceKernelExtendKernelStack", 'x', "ixx", HLE_KERNEL_SYSCALL }, // New entries must go here at the end, not inserted earlier in this table - the funcindex // (this array position) gets baked directly into resolved-import syscall opcodes written // into guest RAM (see GetSyscallOp() in HLE.cpp), which savestates capture verbatim. Inserting diff --git a/Core/HLE/sceKernelHeap.cpp b/Core/HLE/sceKernelHeap.cpp index 1402c716df..b1f5f163a1 100644 --- a/Core/HLE/sceKernelHeap.cpp +++ b/Core/HLE/sceKernelHeap.cpp @@ -9,6 +9,7 @@ #include "Core/HLE/sceKernel.h" #include "Core/HLE/sceKernelHeap.h" #include "Core/HLE/sceKernelMemory.h" +#include "Core/MemMapHelpers.h" #include "Core/Reporting.h" #include "Core/Util/BlockAllocator.h" @@ -215,6 +216,19 @@ static int sceKernelSetUmdCacheOn(int on) { return hleLogWarning(Log::sceKernel, 0, "UNIMPL"); } +static u32 sceKernelMemset(u32 addr, int value, u32 size) { + if (Memory::IsValidRange(addr, size)) { + Memory::Memset(addr, (u8)value, size, "KernelMemset"); + } + return hleLogDebug(Log::sceKernel, addr); +} + +// The POPS manager uses it to make a file descriptor it opened usable from user mode. Ours +// aren't access-checked, so report no such UID and it skips that. +static int sceKernelGetUIDcontrolBlock(SceUID uid, u32 controlBlockPtr) { + return hleLogDebug(Log::sceKernel, SCE_KERNEL_ERROR_UNKNOWN_UID, "no control blocks"); +} + const HLEFunction SysMemForKernel[] = { { 0X96A3CE2C, &WrapI_U, "sceKernelSetRebootKernel", 'i', "x", HLE_KERNEL_SYSCALL }, { 0X1404C1AA, &WrapI_I, "sceKernelSetUmdCacheOn", 'i', "i", HLE_KERNEL_SYSCALL }, @@ -243,6 +257,8 @@ const HLEFunction SysMemForKernel[] = { { 0xF91FE6AA, &WrapI_V, "sceKernelSetParamSfo", 'i', "", HLE_KERNEL_SYSCALL }, { 0xC2460DD5, &WrapI_V, "sceKernelSetParamSfo", 'i', "", HLE_KERNEL_SYSCALL }, { 0x807179E7, &WrapI_V, "sceKernelSetParamSfo", 'i', "", HLE_KERNEL_SYSCALL }, + { 0x8AE776AF, &WrapU_UIU, "sceKernelMemset", 'x', "xix", HLE_KERNEL_SYSCALL }, + { 0xC90B0992, &WrapI_IU, "sceKernelGetUIDcontrolBlock", 'i', "ix", HLE_KERNEL_SYSCALL }, }; void Register_SysMemForKernel() { diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 5bf75b07cd..66f60ba855 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -844,6 +844,14 @@ static u32 sysclib_strlen(u32 src) { } } +static u32 sysclib_strnlen(u32 src, u32 maxLen) { + u32 len = 0; + while (len < maxLen && Memory::IsValidAddress(src + len) && Memory::ReadUnchecked_U8(src + len) != 0) { + len++; + } + return hleLogVerbose(Log::sceKernel, len); +} + static int sysclib_memcmp(u32 dst, u32 src, u32 size) { if (Memory::IsValidRange(dst, size) && Memory::IsValidRange(src, size)) { const int retval = memcmp(Memory::GetCharPointerUnchecked(dst), Memory::GetCharPointerUnchecked(src), size); @@ -1015,6 +1023,7 @@ const HLEFunction SysclibForKernel[] = {0x4C0E0274, &WrapU_UI, "strrchr", 'x', "xx", HLE_KERNEL_SYSCALL }, {0xCE2F7487, &WrapU_U, "toupper", 'x', "x", HLE_KERNEL_SYSCALL }, {0XC2145E80, &WrapI_UIU, "snprintf", 'i', "xx", HLE_KERNEL_SYSCALL }, + {0x90C5573D, &WrapU_UU, "strnlen", 'x', "xx", HLE_KERNEL_SYSCALL }, }; void Register_Kernel_Library() diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 1d9673b30b..236312e6d3 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -3721,6 +3721,9 @@ const HLEFunction ModuleMgrForKernel[] = { {0x329C89DB, &WrapU_CUU, "sceKernelLoadModuleVSH", 'x', "sxx", HLE_KERNEL_SYSCALL }, {0x8909A807, &WrapU_CUU, "sceKernelLoadModuleVSH", 'x', "sxx", HLE_KERNEL_SYSCALL }, {0xBDFEEC4F, &WrapU_CUU, "sceKernelLoadModuleVSH", 'x', "sxx", HLE_KERNEL_SYSCALL }, + // 6.60 NIDs. + {0x939E4270, &WrapU_CUU, "sceKernelLoadModuleForKernel", 'x', "sxx", HLE_KERNEL_SYSCALL }, + {0x3FF74DF1, &WrapU_UUUUU, "sceKernelStartModule", 'v', "xxxxx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED | HLE_KERNEL_SYSCALL }, }; void Register_ModuleMgrForUser() { diff --git a/Core/Screenshot.cpp b/Core/Screenshot.cpp index bc12dd37ca..5572fba0d8 100644 --- a/Core/Screenshot.cpp +++ b/Core/Screenshot.cpp @@ -464,7 +464,8 @@ bool Save8888RGBAScreenshot(std::vector &bufferPNG, const u8 *bufferRGB png_alloc_size_t allocSize = bufferPNG.size(); int result = png_image_write_to_memory(&png, allocSize == 0 ? nullptr : bufferPNG.data(), &allocSize, 0, bufferRGBA8888, w * 4, nullptr); - bool success = result != 0 && png.warning_or_error <= 1; + // Without a buffer, that only measured it. + bool success = !bufferPNG.empty() && result != 0 && png.warning_or_error <= 1; if (!success && allocSize != bufferPNG.size()) { bufferPNG.resize(allocSize); png.warning_or_error = 0;