From 5c69d6169f135f945e8d81bdfc4ed6924f24ee18 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 14 Nov 2012 00:13:17 -0800 Subject: [PATCH 1/8] Use WriteStruct() in sceKernelReferSemaStatus(). --- Core/HLE/sceKernelSemaphore.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 600c6e59ab..9959b4ca0c 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -166,8 +166,7 @@ int sceKernelReferSemaStatus(SceUID id, u32 infoPtr) if (s) { DEBUG_LOG(HLE,"sceKernelReferSemaStatus(%i, %08x)", id, infoPtr); - NativeSemaphore *outptr = (NativeSemaphore*)Memory::GetPointer(infoPtr); - memcpy((char*)outptr, (char*)&s->ns, s->ns.size); + Memory::WriteStruct(infoPtr, &s->ns); return 0; } else From 306274ffdf15cb2bc29b3777d913d0fea6c50e15 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 14 Nov 2012 07:42:21 -0800 Subject: [PATCH 2/8] Fix iterator in sceKernelSignalSema(). I'm sure we dont' want to change s. --- Core/HLE/sceKernelSemaphore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 9959b4ca0c..90b8573506 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -200,7 +200,7 @@ void sceKernelSignalSema(SceUID id, int signal) retry: //TODO: check for threads to wake up - wake them std::vector::iterator iter; - for (iter = s->waitingThreads.begin(); iter!=s->waitingThreads.end(); s++) + for (iter = s->waitingThreads.begin(); iter!=s->waitingThreads.end(); iter++) { SceUID threadID = *iter; int wVal = (int)__KernelGetWaitValue(threadID, error); From 4191d401877fe08a35edc7ae5c82422e0bfa2c91 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 15 Nov 2012 23:55:23 -0800 Subject: [PATCH 3/8] Add notes about PRIORITY attribute. Not supported yet. --- Core/HLE/sceKernelSemaphore.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 90b8573506..317777db5a 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -22,6 +22,9 @@ #include "sceKernelThread.h" #include "sceKernelSemaphore.h" +#define PSP_SEMA_ATTR_FIFO 0 +#define PSP_SEMA_ATTR_PRIORITY 0x100 + /** Current state of a semaphore. * @see sceKernelReferSemaStatus. */ @@ -63,6 +66,7 @@ bool __KernelClearSemaThreads(Semaphore *s, int reason) { bool wokeThreads = false; + // TODO: PSP_SEMA_ATTR_PRIORITY std::vector::iterator iter; for (iter = s->waitingThreads.begin(); iter!=s->waitingThreads.end(); iter++) { @@ -198,7 +202,7 @@ void sceKernelSignalSema(SceUID id, int signal) bool wokeThreads = false; retry: - //TODO: check for threads to wake up - wake them + // TODO: PSP_SEMA_ATTR_PRIORITY std::vector::iterator iter; for (iter = s->waitingThreads.begin(); iter!=s->waitingThreads.end(); iter++) { @@ -219,7 +223,6 @@ retry: break; } } - //pop the thread that were released from waiting // I don't think we should reschedule here //if (wokeThreads) From 0ab19c18e50dc7ff21930594f3c5547519878d6b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 16 Nov 2012 00:06:44 -0800 Subject: [PATCH 4/8] Wrap sceKernelCreateSema(). --- Core/HLE/FunctionWrappers.h | 5 +++++ Core/HLE/sceKernel.cpp | 16 ++++++++-------- Core/HLE/sceKernelSemaphore.cpp | 14 ++++++-------- Core/HLE/sceKernelSemaphore.h | 2 +- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index d58a726029..4a21ba13c5 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -118,6 +118,11 @@ template void WrapI_CUUU() { RETURN(retval); } +template void WrapI_CUIIU() { + int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); + RETURN(retval); +} + template void WrapU_CU() { int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1)); RETURN((u32)retval); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 8f160946eb..ebfe5dca37 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -327,14 +327,14 @@ const HLEFunction ThreadManForUser[] = {0xCD203292,&WrapU_V, "sceKernelCancelEventFlag"}, {0xA66B0120,&WrapU_IU, "sceKernelReferEventFlagStatus"}, - {0x8FFDF9A2,&WrapV_IIU, "sceKernelCancelSema"}, - {0xD6DA4BA1,sceKernelCreateSema, "sceKernelCreateSema"}, - {0x28b6489c,&WrapV_I, "sceKernelDeleteSema"}, - {0x58b1f937,&WrapI_II, "sceKernelPollSema"}, - {0xBC6FEBC5,&WrapI_IU, "sceKernelReferSemaStatus"}, - {0x3F53E640,&WrapV_II, "sceKernelSignalSema"}, - {0x4E3A1105,&WrapV_IIU, "sceKernelWaitSema"}, - {0x6d212bac,&WrapV_IIU, "sceKernelWaitSemaCB"}, + {0x8FFDF9A2,&WrapV_IIU, "sceKernelCancelSema"}, + {0xD6DA4BA1,&WrapI_CUIIU, "sceKernelCreateSema"}, + {0x28b6489c,&WrapV_I, "sceKernelDeleteSema"}, + {0x58b1f937,&WrapI_II, "sceKernelPollSema"}, + {0xBC6FEBC5,&WrapI_IU, "sceKernelReferSemaStatus"}, + {0x3F53E640,&WrapV_II, "sceKernelSignalSema"}, + {0x4E3A1105,&WrapV_IIU, "sceKernelWaitSema"}, + {0x6d212bac,&WrapV_IIU, "sceKernelWaitSemaCB"}, {0x60107536,0,"sceKernelDeleteLwMutex"}, {0x19CFF145,0,"sceKernelCreateLwMutex"}, diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 317777db5a..60e57fd951 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -118,24 +118,22 @@ void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) } //SceUID sceKernelCreateSema(const char *name, SceUInt attr, int initVal, int maxVal, SceKernelSemaOptParam *option); -void sceKernelCreateSema() +SceUID sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 optionPtr) { - const char *name = Memory::GetCharPointer(PARAM(0)); - Semaphore *s = new Semaphore; SceUID id = kernelObjects.Create(s); s->ns.size = sizeof(NativeSemaphore); strncpy(s->ns.name, name, 32); - s->ns.attr = PARAM(1); - s->ns.initCount = PARAM(2); + s->ns.attr = attr; + s->ns.initCount = initVal; s->ns.currentCount = s->ns.initCount; - s->ns.maxCount = PARAM(3); + s->ns.maxCount = maxVal; s->ns.numWaitThreads = 0; - DEBUG_LOG(HLE,"%i=sceKernelCreateSema(%s, %08x, %i, %i, %08x)", id, s->ns.name, s->ns.attr, s->ns.initCount, s->ns.maxCount, PARAM(4)); + DEBUG_LOG(HLE,"%i=sceKernelCreateSema(%s, %08x, %i, %i, %08x)", id, s->ns.name, s->ns.attr, s->ns.initCount, s->ns.maxCount, optionPtr); - RETURN(id); + return id; } //int sceKernelDeleteSema(SceUID semaid); diff --git a/Core/HLE/sceKernelSemaphore.h b/Core/HLE/sceKernelSemaphore.h index 185976f788..86d51e1b9b 100644 --- a/Core/HLE/sceKernelSemaphore.h +++ b/Core/HLE/sceKernelSemaphore.h @@ -18,7 +18,7 @@ #pragma once void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr); -void sceKernelCreateSema(); +SceUID sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 optionPtr); void sceKernelDeleteSema(SceUID id); int sceKernelPollSema(SceUID id, int wantedCount); int sceKernelReferSemaStatus(SceUID id, u32 infoPtr); From dd14450424cc0d09ec37f4327c247209d16367f9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 16 Nov 2012 01:26:04 -0800 Subject: [PATCH 5/8] CreateSema: Truncate and validate like the PSP. --- Core/HLE/sceKernelSemaphore.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 60e57fd951..dc8d4d2ec4 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -120,11 +120,15 @@ void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) //SceUID sceKernelCreateSema(const char *name, SceUInt attr, int initVal, int maxVal, SceKernelSemaOptParam *option); SceUID sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 optionPtr) { + if (!name) + return SCE_KERNEL_ERROR_ERROR; + Semaphore *s = new Semaphore; SceUID id = kernelObjects.Create(s); s->ns.size = sizeof(NativeSemaphore); - strncpy(s->ns.name, name, 32); + strncpy(s->ns.name, name, 31); + s->ns.name[31] = 0; s->ns.attr = attr; s->ns.initCount = initVal; s->ns.currentCount = s->ns.initCount; From 71e57043e89a546f1fe4f43a2d3efd3f4f882ef1 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 16 Nov 2012 01:32:00 -0800 Subject: [PATCH 6/8] SignalSema: throw an error on overflow. This is what the PSP does. --- Core/HLE/sceKernelSemaphore.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index dc8d4d2ec4..30c210f0a0 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -191,12 +191,14 @@ void sceKernelSignalSema(SceUID id, int signal) Semaphore *s = kernelObjects.Get(id, error); if (s) { - int oldval = s->ns.currentCount; - if (s->ns.currentCount + signal > s->ns.maxCount) - s->ns.currentCount += s->ns.maxCount; - else - s->ns.currentCount += signal; + { + RETURN(SCE_KERNEL_ERROR_SEMA_OVF); + return; + } + + int oldval = s->ns.currentCount; + s->ns.currentCount += signal; DEBUG_LOG(HLE,"sceKernelSignalSema(%i, %i) (old: %i, new: %i)", id, signal, oldval, s->ns.currentCount); // We need to set the return value BEFORE processing other threads. From 8517fbe761918aa856d3cf330abcc9145e24fe1d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 16 Nov 2012 01:41:54 -0800 Subject: [PATCH 7/8] PollSema: don't allow values <= 0. --- Core/HLE/sceKernelSemaphore.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 30c210f0a0..e287d1b3f9 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -290,6 +290,9 @@ int sceKernelPollSema(SceUID id, int wantedCount) { DEBUG_LOG(HLE,"sceKernelPollSema(%i, %i)", id, wantedCount); + if (wantedCount <= 0) + return SCE_KERNEL_ERROR_ILLEGAL_COUNT; + u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) From 2e9e61dfc618ea8998940c995971ad3f86089a4e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 16 Nov 2012 01:50:26 -0800 Subject: [PATCH 8/8] CancelSema: adjust scheduling to match PSP. --- Core/HLE/sceKernelSemaphore.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index e287d1b3f9..c09109a39d 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -91,6 +91,12 @@ void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) Semaphore *s = kernelObjects.Get(id, error); if (s) { + if (newCount > s->ns.maxCount) + { + RETURN(SCE_KERNEL_ERROR_ILLEGAL_COUNT); + return; + } + if (numWaitThreadsPtr) { u32* numWaitThreads = (u32*)Memory::GetPointer(numWaitThreadsPtr); @@ -106,9 +112,9 @@ void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) // We need to set the return value BEFORE rescheduling threads. RETURN(0); - // TODO: Should this reschedule? - if (__KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_CANCEL)) - __KernelReSchedule("semaphore cancelled"); + // Cancel appears to always reschedule. + __KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_CANCEL); + __KernelReSchedule("semaphore cancelled"); } else {