From feeb03b5ff7e4618c2825d14fef942dabd7edb53 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 2 Aug 2014 12:01:30 -0700 Subject: [PATCH] Fix return values in sceKernelGetThreadmanIdList(). Support other object types as well, but not threads/etc. properly yet. --- Core/HLE/sceKernel.h | 22 ++++++++++++++++++---- Core/HLE/sceKernelThread.cpp | 31 +++++++++++++++++-------------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/Core/HLE/sceKernel.h b/Core/HLE/sceKernel.h index 5cd4739c40..063ee15068 100644 --- a/Core/HLE/sceKernel.h +++ b/Core/HLE/sceKernel.h @@ -489,11 +489,9 @@ public: } template - void Iterate(bool func(T *, ArgT), ArgT arg) - { + void Iterate(bool func(T *, ArgT), ArgT arg) { int type = T::GetStaticIDType(); - for (int i = 0; i < maxCount; i++) - { + for (int i = 0; i < maxCount; i++) { if (!occupied[i]) continue; T *t = static_cast(pool[i]); @@ -504,6 +502,22 @@ public: } } + int ListIDType(int type, SceUID *uids, int count) const { + int total = 0; + for (int i = 0; i < maxCount; i++) { + if (!occupied[i]) { + continue; + } + if (pool[i]->GetIDType() == type) { + if (total < count) { + *uids++ = pool[i]->GetUID(); + } + ++total; + } + } + return total; + } + bool GetIDType(SceUID handle, int *type) const { if (handle < handleOffset || handle >= handleOffset+maxCount || !occupied[handle-handleOffset]) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index c2cb8c0258..37a2f9cceb 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1592,24 +1592,27 @@ u32 sceKernelGetThreadmanIdType(u32 uid) { } } -u32 sceKernelGetThreadmanIdList(u32 type, u32 readBufPtr, u32 readBufSize, u32 idCountPtr) -{ - DEBUG_LOG(SCEKERNEL, "sceKernelGetThreadmanIdList(%i, %08x, %i, %08x)", - type, readBufPtr, readBufSize, idCountPtr); - if (!Memory::IsValidAddress(readBufPtr)) - return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; - - if (type != SCE_KERNEL_TMID_Thread) { - ERROR_LOG_REPORT(SCEKERNEL, "sceKernelGetThreadmanIdList only implemented for threads"); +u32 sceKernelGetThreadmanIdList(u32 type, u32 readBufPtr, u32 readBufSize, u32 idCountPtr) { + if (type == 0 || type > SCE_KERNEL_TMID_DormantThread || (type > SCE_KERNEL_TMID_Tlspl && type < SCE_KERNEL_TMID_SleepThread)) { + ERROR_LOG_REPORT(SCEKERNEL, "sceKernelGetThreadmanIdList(%i, %08x, %i, %08x): invalid type", type, readBufPtr, readBufSize, idCountPtr); + return SCE_KERNEL_ERROR_ILLEGAL_TYPE; + } + if (readBufSize >= 0x8000000) { + // Not exact, it's probably if the sum ends up negative or something. + ERROR_LOG_REPORT(SCEKERNEL, "sceKernelGetThreadmanIdList(%i, %08x, %i, %08x): invalid size", type, readBufPtr, readBufSize, idCountPtr); + return SCE_KERNEL_ERROR_ILLEGAL_ADDR; + } + DEBUG_LOG(SCEKERNEL, "sceKernelGetThreadmanIdList(%i, %08x, %i, %08x)", type, readBufPtr, readBufSize, idCountPtr); + if (!Memory::IsValidAddress(readBufPtr)) { + // Crashes on a PSP. return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; } - for (size_t i = 0; i < std::min((size_t)readBufSize, threadqueue.size()); i++) - { - Memory::Write_U32(threadqueue[i], readBufPtr + (u32)i * 4); + u32 total = kernelObjects.ListIDType(type, PSPPointer::Create(readBufPtr), readBufSize); + if (Memory::IsValidAddress(idCountPtr)) { + Memory::Write_U32(total, idCountPtr); } - Memory::Write_U32((u32)threadqueue.size(), idCountPtr); - return 0; + return total > readBufSize ? readBufSize : total; } // Saves the current CPU context