diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 4cf1849fa..1d31eca43 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -800,7 +800,7 @@ const HLEFunction ThreadManForUser[] = {0xD979E9BF,WrapI_IUU, "sceKernelAllocateFpl"}, {0xE7282CB6,WrapI_IUU, "sceKernelAllocateFplCB"}, {0x623AE665,WrapI_IU, "sceKernelTryAllocateFpl"}, - {0xF6414A71,sceKernelFreeFpl,"sceKernelFreeFpl"}, + {0xF6414A71,WrapI_IU, "sceKernelFreeFpl"}, {0xA8AA591F,WrapI_IU, "sceKernelCancelFpl"}, {0xD8199E4C,WrapI_IU, "sceKernelReferFplStatus"}, diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index ba1a57c07..c7683f1a2 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -543,21 +543,23 @@ int sceKernelTryAllocateFpl(SceUID uid, u32 blockPtrAddr) } } -void sceKernelFreeFpl() +int sceKernelFreeFpl(SceUID uid, u32 blockPtr) { - SceUID id = PARAM(0); - u32 blockAddr = PARAM(1); + if (blockPtr > PSP_GetUserMemoryEnd()) { + WARN_LOG(HLE, "%08x=sceKernelFreeFpl(%i, %08x): invalid address", SCE_KERNEL_ERROR_ILLEGAL_ADDR, uid, blockPtr); + return SCE_KERNEL_ERROR_ILLEGAL_ADDR; + } - DEBUG_LOG(HLE,"sceKernelFreeFpl(%i, %08x)", id, blockAddr); u32 error; - FPL *fpl = kernelObjects.Get(id, error); + FPL *fpl = kernelObjects.Get(uid, error); if (fpl) { - int blockNum = (blockAddr - fpl->address) / fpl->alignedSize; + int blockNum = (blockPtr - fpl->address) / fpl->alignedSize; if (blockNum < 0 || blockNum >= fpl->nf.numBlocks) { - RETURN(SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCK); + DEBUG_LOG(HLE, "sceKernelFreeFpl(%i, %08x): bad block ptr", uid, blockPtr); + return SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCK; } else { - RETURN(0); if (fpl->freeBlock(blockNum)) { + DEBUG_LOG(HLE, "sceKernelFreeFpl(%i, %08x)", uid, blockPtr); __KernelSortFplThreads(fpl); bool wokeThreads = false; @@ -573,12 +575,17 @@ retry: if (wokeThreads) hleReSchedule("fpl freed"); + return 0; + } else { + DEBUG_LOG(HLE, "sceKernelFreeFpl(%i, %08x): already free", uid, blockPtr); + return SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCK; } } } else { - RETURN(error); + DEBUG_LOG(HLE, "sceKernelFreeFpl(%i, %08x): invalid fpl", uid, blockPtr); + return error; } } diff --git a/Core/HLE/sceKernelMemory.h b/Core/HLE/sceKernelMemory.h index 6499df129..d9ab052f4 100644 --- a/Core/HLE/sceKernelMemory.h +++ b/Core/HLE/sceKernelMemory.h @@ -51,7 +51,7 @@ int sceKernelDeleteFpl(SceUID uid); int sceKernelAllocateFpl(SceUID uid, u32 blockPtrAddr, u32 timeoutPtr); int sceKernelAllocateFplCB(SceUID uid, u32 blockPtrAddr, u32 timeoutPtr); int sceKernelTryAllocateFpl(SceUID uid, u32 blockPtrAddr); -void sceKernelFreeFpl(); +int sceKernelFreeFpl(SceUID uid, u32 blockPtr); int sceKernelCancelFpl(SceUID uid, u32 numWaitThreadsPtr); int sceKernelReferFplStatus(SceUID uid, u32 statusPtr);