From 774589aa4fe5e7ef44c6bac0fbc832f9ed8eb8fa Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 2 Aug 2014 11:26:45 -0700 Subject: [PATCH 1/5] Correct the Tlspl TMID value. --- Core/HLE/sceKernel.cpp | 1 + Core/HLE/sceKernel.h | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 31c6584932..22e4abb129 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -620,6 +620,7 @@ KernelObject *KernelObjectPool::CreateByIDType(int type) case SCE_KERNEL_TMID_VTimer: return __KernelVTimerObject(); case SCE_KERNEL_TMID_Tlspl: + case SCE_KERNEL_TMID_Tlspl_v0: return __KernelTlsplObject(); case PPSSPP_KERNEL_TMID_File: return __KernelFileNodeObject(); diff --git a/Core/HLE/sceKernel.h b/Core/HLE/sceKernel.h index 2f8c8f3e39..5cd4739c40 100644 --- a/Core/HLE/sceKernel.h +++ b/Core/HLE/sceKernel.h @@ -327,12 +327,13 @@ enum TMIDPurpose SCE_KERNEL_TMID_VTimer = 11, SCE_KERNEL_TMID_Mutex = 12, SCE_KERNEL_TMID_LwMutex = 13, + SCE_KERNEL_TMID_Tlspl = 14, SCE_KERNEL_TMID_SleepThread = 64, SCE_KERNEL_TMID_DelayThread = 65, SCE_KERNEL_TMID_SuspendThread = 66, SCE_KERNEL_TMID_DormantThread = 67, - // No idea what the correct value is here or how to find out. - SCE_KERNEL_TMID_Tlspl = 0x1001, + // This is kept for old savestates. Not the real value. + SCE_KERNEL_TMID_Tlspl_v0 = 0x1001, // Not official, but need ids for save states. PPSSPP_KERNEL_TMID_Module = 0x100001, From feeb03b5ff7e4618c2825d14fef942dabd7edb53 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 2 Aug 2014 12:01:30 -0700 Subject: [PATCH 2/5] 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 From b8f8707ea17a372c0742818ee988d4493563a2a2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 2 Aug 2014 12:32:40 -0700 Subject: [PATCH 3/5] Allow a bad pts on zero size when listing uids. --- Core/HLE/sceKernelThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 37a2f9cceb..5948be07fd 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1603,7 +1603,7 @@ u32 sceKernelGetThreadmanIdList(u32 type, u32 readBufPtr, u32 readBufSize, u32 i return SCE_KERNEL_ERROR_ILLEGAL_ADDR; } DEBUG_LOG(SCEKERNEL, "sceKernelGetThreadmanIdList(%i, %08x, %i, %08x)", type, readBufPtr, readBufSize, idCountPtr); - if (!Memory::IsValidAddress(readBufPtr)) { + if (!Memory::IsValidAddress(readBufPtr) && readBufSize > 0) { // Crashes on a PSP. return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; } From 6852e32d6bf23024a64a9623e60e68d95f0afb4a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 2 Aug 2014 12:55:02 -0700 Subject: [PATCH 4/5] Support other thread TMIDs in uid listing. --- Core/HLE/sceKernelThread.cpp | 78 ++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 5948be07fd..53bdf72a0b 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -507,9 +507,9 @@ public: void setReturnValue(u32 retval); void setReturnValue(u64 retval); void resumeFromWait(); - bool isWaitingFor(WaitType type, int id); - int getWaitID(WaitType type); - ThreadWaitInfo getWaitInfo(); + bool isWaitingFor(WaitType type, int id) const; + int getWaitID(WaitType type) const; + ThreadWaitInfo getWaitInfo() const; // Utils inline bool isRunning() const { return (nt.status & THREADSTATUS_RUNNING) != 0; } @@ -1592,23 +1592,77 @@ u32 sceKernelGetThreadmanIdType(u32 uid) { } } +bool __ThreadmanIdListIsSleeping(const Thread *t) { + return t->isWaitingFor(WAITTYPE_SLEEP, 0); +} + +bool __ThreadmanIdListIsDelayed(const Thread *t) { + return t->isWaitingFor(WAITTYPE_DELAY, t->GetUID()); +} + +bool __ThreadmanIdListIsSuspended(const Thread *t) { + return t->isSuspended(); +} + +bool __ThreadmanIdListIsDormant(const Thread *t) { + return t->isStopped(); +} + 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) && readBufSize > 0) { // Crashes on a PSP. + ERROR_LOG_REPORT(SCEKERNEL, "sceKernelGetThreadmanIdList(%i, %08x, %i, %08x): invalid pointer", type, readBufPtr, readBufSize, idCountPtr); return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; } - u32 total = kernelObjects.ListIDType(type, PSPPointer::Create(readBufPtr), readBufSize); + u32 total = 0; + auto uids = PSPPointer::Create(readBufPtr); + u32 error; + if (type > 0 && type <= SCE_KERNEL_TMID_Tlspl) { + DEBUG_LOG(SCEKERNEL, "sceKernelGetThreadmanIdList(%i, %08x, %i, %08x)", type, readBufPtr, readBufSize, idCountPtr); + total = kernelObjects.ListIDType(type, uids, readBufSize); + } else if (type >= SCE_KERNEL_TMID_SleepThread && type <= SCE_KERNEL_TMID_DormantThread) { + bool (*checkFunc)(const Thread *t) = NULL; + switch (type) { + case SCE_KERNEL_TMID_SleepThread: + checkFunc = &__ThreadmanIdListIsSleeping; + break; + + case SCE_KERNEL_TMID_DelayThread: + checkFunc = &__ThreadmanIdListIsDelayed; + break; + + case SCE_KERNEL_TMID_SuspendThread: + checkFunc = &__ThreadmanIdListIsSuspended; + break; + + case SCE_KERNEL_TMID_DormantThread: + checkFunc = &__ThreadmanIdListIsDormant; + break; + + default: + _dbg_assert_msg_(SCEKERNEL, false, "Unexpected type %d", type); + } + + for (size_t i = 0; i < threadqueue.size(); i++) { + const Thread *t = kernelObjects.Get(threadqueue[i], error); + if (checkFunc(t)) { + if (total < readBufSize) { + *uids++ = threadqueue[i]; + } + ++total; + } + } + } else { + ERROR_LOG_REPORT(SCEKERNEL, "sceKernelGetThreadmanIdList(%i, %08x, %i, %08x): invalid type", type, readBufPtr, readBufSize, idCountPtr); + return SCE_KERNEL_ERROR_ILLEGAL_TYPE; + } + if (Memory::IsValidAddress(idCountPtr)) { Memory::Write_U32(total, idCountPtr); } @@ -3135,21 +3189,21 @@ void Thread::resumeFromWait() isProcessingCallbacks = false; } -bool Thread::isWaitingFor(WaitType type, int id) +bool Thread::isWaitingFor(WaitType type, int id) const { if (nt.status & THREADSTATUS_WAIT) return nt.waitType == type && nt.waitID == id; return false; } -int Thread::getWaitID(WaitType type) +int Thread::getWaitID(WaitType type) const { if (nt.waitType == type) return nt.waitID; return 0; } -ThreadWaitInfo Thread::getWaitInfo() +ThreadWaitInfo Thread::getWaitInfo() const { return waitInfo; } From 909ac626699c057a03978df11fbcdaafa09dbe8d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 6 Aug 2014 07:52:23 -0700 Subject: [PATCH 5/5] Return a proper error for fake TMIDs. --- Core/HLE/sceKernelThread.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 53bdf72a0b..a2fc29fe56 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1584,8 +1584,14 @@ int sceKernelGetThreadExitStatus(SceUID threadID) u32 sceKernelGetThreadmanIdType(u32 uid) { int type; if (kernelObjects.GetIDType(uid, &type)) { - DEBUG_LOG(SCEKERNEL, "%i=sceKernelGetThreadmanIdType(%i)", type, uid); - return type; + if (type < 0x1000) { + DEBUG_LOG(SCEKERNEL, "%i=sceKernelGetThreadmanIdType(%i)", type, uid); + return type; + } else { + // This means a partition memory block or module, etc. + ERROR_LOG(SCEKERNEL, "sceKernelGetThreadmanIdType(%i): invalid object type %i", uid, type); + return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; + } } else { ERROR_LOG(SCEKERNEL, "sceKernelGetThreadmanIdType(%i) - FAILED", uid); return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT;