diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index cb858c0e90..48a07d7c22 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -840,7 +840,7 @@ const HLEFunction ThreadManForUser[] = {0X1D371B8A, &WrapI_IU, "sceKernelCancelVpl", 'i', "ix" }, {0X39810265, &WrapI_IU, "sceKernelReferVplStatus", 'i', "ip" }, - {0XC07BB470, &WrapI_CUUUUU, "sceKernelCreateFpl", 'i', "sxxxxx" }, + {0XC07BB470, &WrapI_CUUUUU, "sceKernelCreateFpl", 'i', "sixxxp" }, {0XED1410E0, &WrapI_I, "sceKernelDeleteFpl", 'i', "i" }, {0XD979E9BF, &WrapI_IUU, "sceKernelAllocateFpl", 'i', "ixx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED }, {0XE7282CB6, &WrapI_IUU, "sceKernelAllocateFplCB", 'i', "ixx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED }, @@ -908,7 +908,7 @@ const HLEFunction ThreadManForKernel[] = {0x1fb15a32, &WrapU_IU, "sceKernelSetEventFlag", 'x', "ix", HLE_KERNEL_SYSCALL }, {0x812346e4, &WrapU_IU, "sceKernelClearEventFlag", 'x', "ix", HLE_KERNEL_SYSCALL }, {0x402fcf22, &WrapI_IUUUU, "sceKernelWaitEventFlag", 'i', "ixxpp", HLE_NOT_IN_INTERRUPT | HLE_KERNEL_SYSCALL}, - {0xc07bb470, &WrapI_CUUUUU, "sceKernelCreateFpl", 'i', "sxxxxx" ,HLE_KERNEL_SYSCALL }, + {0xc07bb470, &WrapI_CUUUUU, "sceKernelCreateFpl", 'i', "sixxxp" ,HLE_KERNEL_SYSCALL }, {0xed1410e0, &WrapI_I, "sceKernelDeleteFpl", 'i', "i" ,HLE_KERNEL_SYSCALL }, {0x623ae665, &WrapI_IU, "sceKernelTryAllocateFpl", 'i', "ix" ,HLE_KERNEL_SYSCALL }, {0x616403ba, &WrapI_I, "sceKernelTerminateThread", 'i', "i" ,HLE_KERNEL_SYSCALL }, diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 1a6e16c0fa..5575bb97d5 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -539,6 +539,17 @@ static int BlockAllocatorToID(const BlockAllocator *alloc) { return 0; } +static BlockAllocator *BlockAllocatorFromAddr(u32 addr) { + addr &= 0x3FFFFFFF; + if (Memory::IsKernelAndNotVolatileAddress(addr)) + return &kernelMemory; + if (Memory::IsKernelAddress(addr)) + return &volatileMemory; + if (Memory::IsRAMAddress(addr)) + return &userMemory; + return nullptr; +} + enum SceKernelFplAttr { PSP_FPL_ATTR_FIFO = 0x0000, @@ -624,29 +635,18 @@ static void __KernelSortFplThreads(FPL *fpl) std::stable_sort(fpl->waitingThreads.begin(), fpl->waitingThreads.end(), __FplThreadSortPriority); } -int sceKernelCreateFpl(const char *name, u32 mpid, u32 attr, u32 blockSize, u32 numBlocks, u32 optPtr) -{ +int sceKernelCreateFpl(const char *name, u32 mpid, u32 attr, u32 blockSize, u32 numBlocks, u32 optPtr) { if (!name) - { - WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateFpl(): invalid name", SCE_KERNEL_ERROR_NO_MEMORY); - return SCE_KERNEL_ERROR_NO_MEMORY; - } + return hleLogWarning(SCEKERNEL, SCE_KERNEL_ERROR_NO_MEMORY, "invalid name"); if (mpid < 1 || mpid > 9 || mpid == 7) - { - WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateFpl(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, mpid); - return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; - } - // We only support user right now. - if (mpid != 2 && mpid != 6) - { - WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateFpl(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_PERM, mpid); - return SCE_KERNEL_ERROR_ILLEGAL_PERM; - } + return hleLogWarning(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, "invalid partition %d", mpid); + + BlockAllocator *allocator = BlockAllocatorFromID(mpid); + if (allocator == nullptr) + return hleLogWarning(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_PERM, "invalid partition %d", mpid); if (((attr & ~PSP_FPL_ATTR_KNOWN) & ~0xFF) != 0) - { - WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateFpl(): invalid attr parameter: %08x", SCE_KERNEL_ERROR_ILLEGAL_ATTR, attr); - return SCE_KERNEL_ERROR_ILLEGAL_ATTR; - } + return hleLogWarning(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_ATTR, "invalid attr parameter: %08x", attr); + // There's probably a simpler way to get this same basic formula... // This is based on results from a PSP. bool illegalMemSize = blockSize == 0 || numBlocks == 0; @@ -655,25 +655,16 @@ int sceKernelCreateFpl(const char *name, u32 mpid, u32 attr, u32 blockSize, u32 if (!illegalMemSize && (u64) numBlocks >= 0x100000000ULL / (((u64) blockSize + 3ULL) & ~3ULL)) illegalMemSize = true; if (illegalMemSize) - { - WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateFpl(): invalid blockSize/count", SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE); - return SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE; - } + return hleReportWarning(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE, "invalid blockSize/count"); int alignment = 4; - if (optPtr != 0) - { - u32 size = Memory::Read_U32(optPtr); - if (size > 8) - WARN_LOG_REPORT(SCEKERNEL, "sceKernelCreateFpl(): unsupported extra options, size = %d", size); + if (Memory::IsValidRange(optPtr, 4)) { + u32 size = Memory::ReadUnchecked_U32(optPtr); if (size >= 4) alignment = Memory::Read_U32(optPtr + 4); // Must be a power of 2 to be valid. if ((alignment & (alignment - 1)) != 0) - { - WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateFpl(): invalid alignment %d", SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, alignment); - return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; - } + return hleLogWarning(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, "invalid alignment %d", alignment); } if (alignment < 4) @@ -682,9 +673,8 @@ int sceKernelCreateFpl(const char *name, u32 mpid, u32 attr, u32 blockSize, u32 int alignedSize = ((int)blockSize + alignment - 1) & ~(alignment - 1); u32 totalSize = alignedSize * numBlocks; bool atEnd = (attr & PSP_FPL_ATTR_HIGHMEM) != 0; - u32 address = userMemory.Alloc(totalSize, atEnd, "FPL"); - if (address == (u32)-1) - { + u32 address = allocator->Alloc(totalSize, atEnd, "FPL"); + if (address == (u32)-1) { DEBUG_LOG(SCEKERNEL, "sceKernelCreateFpl(\"%s\", partition=%i, attr=%08x, bsize=%i, nb=%i) FAILED - out of ram", name, mpid, attr, blockSize, numBlocks); return SCE_KERNEL_ERROR_NO_MEMORY; @@ -726,7 +716,10 @@ int sceKernelDeleteFpl(SceUID uid) if (wokeThreads) hleReSchedule("fpl deleted"); - userMemory.Free(fpl->address); + BlockAllocator *alloc = BlockAllocatorFromAddr(fpl->address); + _assert_msg_(alloc != nullptr, "Should always have a valid allocator/address"); + if (alloc) + alloc->Free(fpl->address); return kernelObjects.Destroy(uid); } else