From 87ee0bc650917b622e50d5a52cb0e20a9cd4f1d5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 21 Jun 2014 21:27:58 -0700 Subject: [PATCH] Return error codes in register/release subintr. This checks for duplicate registrations and other thigns that could've been causing wrong behavior. --- Core/HLE/sceKernelInterrupt.cpp | 102 +++++++++++++++++++++----------- Core/HLE/sceKernelInterrupt.h | 4 +- 2 files changed, 71 insertions(+), 35 deletions(-) diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index c6bb3d4f7a..84e069c0cd 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -19,6 +19,7 @@ #include #include +#include "Core/Reporting.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/MIPS/MIPS.h" @@ -36,6 +37,9 @@ void __DisableInterrupts(); void __EnableInterrupts(); bool __InterruptsEnabled(); +// Seems like some > 16 are taken but not available. Probably kernel only? +static const u32 PSP_NUMBER_SUBINTERRUPTS = 32; + // InterruptsManager ////////////////////////////////////////////////////////////////////////// // INTERRUPT MANAGEMENT @@ -441,60 +445,91 @@ void __RegisterIntrHandler(u32 intrNumber, IntrHandler* handler) intrHandlers[intrNumber] = handler; } -SubIntrHandler *__RegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 &error) -{ - SubIntrHandler *subIntrHandler = intrHandlers[intrNumber]->add(subIntrNumber); +SubIntrHandler *__RegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg, u32 &error) { + if (intrNumber >= PSP_NUMBER_INTERRUPTS) { + error = SCE_KERNEL_ERROR_ILLEGAL_INTRCODE; + return NULL; + } + IntrHandler *intr = intrHandlers[intrNumber]; + if (intr->has(subIntrNumber)) { + error = SCE_KERNEL_ERROR_FOUND_HANDLER; + return NULL; + } + if (handler == NULL) { + // Silently ignored. + error = SCE_KERNEL_ERROR_OK; + return NULL; + } + + SubIntrHandler *subIntrHandler = intr->add(subIntrNumber); subIntrHandler->subIntrNumber = subIntrNumber; subIntrHandler->intrNumber = intrNumber; - error = 0; + subIntrHandler->handlerAddress = handler; + subIntrHandler->handlerArg = handlerArg; + error = SCE_KERNEL_ERROR_OK; return subIntrHandler; } -int __ReleaseSubIntrHandler(int intrNumber, int subIntrNumber) -{ - if (intrNumber >= PSP_NUMBER_INTERRUPTS) - return -1; - if (!intrHandlers[intrNumber]->has(subIntrNumber)) - return -1; +int __ReleaseSubIntrHandler(int intrNumber, int subIntrNumber) { + if (intrNumber >= PSP_NUMBER_INTERRUPTS) { + return SCE_KERNEL_ERROR_ILLEGAL_INTRCODE; + } + if (!intrHandlers[intrNumber]->has(subIntrNumber)) { + return SCE_KERNEL_ERROR_NOTFOUND_HANDLER; + } - for (std::list::iterator it = pendingInterrupts.begin(); it != pendingInterrupts.end(); ) - { - if (it->intr == intrNumber && it->subintr == subIntrNumber) + for (auto it = pendingInterrupts.begin(); it != pendingInterrupts.end(); ) { + if (it->intr == intrNumber && it->subintr == subIntrNumber) { pendingInterrupts.erase(it++); - else + } else { ++it; + } } intrHandlers[intrNumber]->remove(subIntrNumber); return 0; } -u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg) -{ - DEBUG_LOG(SCEINTC,"sceKernelRegisterSubIntrHandler(%i, %i, %08x, %08x)", intrNumber, subIntrNumber, handler, handlerArg); - - if (intrNumber >= PSP_NUMBER_INTERRUPTS) - return -1; +u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg) { + if (intrNumber >= PSP_NUMBER_INTERRUPTS) { + ERROR_LOG_REPORT(SCEINTC, "sceKernelRegisterSubIntrHandler(%i, %i, %08x, %08x): invalid interrupt", intrNumber, subIntrNumber, handler, handlerArg); + return SCE_KERNEL_ERROR_ILLEGAL_INTRCODE; + } + if (subIntrNumber >= PSP_NUMBER_SUBINTERRUPTS) { + ERROR_LOG_REPORT(SCEINTC, "sceKernelRegisterSubIntrHandler(%i, %i, %08x, %08x): invalid subinterrupt", intrNumber, subIntrNumber, handler, handlerArg); + return SCE_KERNEL_ERROR_ILLEGAL_INTRCODE; + } u32 error; - SubIntrHandler *subIntrHandler = __RegisterSubIntrHandler(intrNumber, subIntrNumber, error); - if (subIntrHandler) - { + SubIntrHandler *subIntrHandler = __RegisterSubIntrHandler(intrNumber, subIntrNumber, handler, handlerArg, error); + if (subIntrHandler) { + DEBUG_LOG(SCEINTC, "sceKernelRegisterSubIntrHandler(%i, %i, %08x, %08x)", intrNumber, subIntrNumber, handler, handlerArg); subIntrHandler->enabled = false; - subIntrHandler->handlerAddress = handler; - subIntrHandler->handlerArg = handlerArg; + } else if (error == SCE_KERNEL_ERROR_OK) { + WARN_LOG_REPORT(SCEINTC, "sceKernelRegisterSubIntrHandler(%i, %i, %08x, %08x): ignored NULL handler", intrNumber, subIntrNumber, handler, handlerArg); + } else if (error = SCE_KERNEL_ERROR_FOUND_HANDLER) { + ERROR_LOG_REPORT(SCEINTC, "sceKernelRegisterSubIntrHandler(%i, %i, %08x, %08x): duplicate handler", intrNumber, subIntrNumber, handler, handlerArg); + } else { + ERROR_LOG_REPORT(SCEINTC, "sceKernelRegisterSubIntrHandler(%i, %i, %08x, %08x): error %08x", intrNumber, subIntrNumber, handler, handlerArg, error); } return error; } -int sceKernelReleaseSubIntrHandler(int intrNumber, int subIntrNumber) -{ - DEBUG_LOG(SCEINTC, "sceKernelReleaseSubIntrHandler(%i, %i)", intrNumber, subIntrNumber); +u32 sceKernelReleaseSubIntrHandler(u32 intrNumber, u32 subIntrNumber) { + if (intrNumber >= PSP_NUMBER_INTERRUPTS) { + ERROR_LOG_REPORT(SCEINTC, "sceKernelReleaseSubIntrHandler(%i, %i): invalid interrupt", intrNumber, subIntrNumber); + return SCE_KERNEL_ERROR_ILLEGAL_INTRCODE; + } + if (subIntrNumber >= PSP_NUMBER_SUBINTERRUPTS) { + ERROR_LOG_REPORT(SCEINTC, "sceKernelReleaseSubIntrHandler(%i, %i): invalid subinterrupt", intrNumber, subIntrNumber); + return SCE_KERNEL_ERROR_ILLEGAL_INTRCODE; + } - if (intrNumber >= PSP_NUMBER_INTERRUPTS) - return -1; - - return __ReleaseSubIntrHandler(intrNumber, subIntrNumber); + u32 error = __ReleaseSubIntrHandler(intrNumber, subIntrNumber); + if (error != SCE_KERNEL_ERROR_OK) { + ERROR_LOG(SCEINTC, "sceKernelReleaseSubIntrHandler(%i, %i): error %08x", intrNumber, subIntrNumber); + } + return error; } u32 sceKernelEnableSubIntr(u32 intrNumber, u32 subIntrNumber) @@ -545,6 +580,7 @@ struct PspIntrHandlerOptionParam { void QueryIntrHandlerInfo() { + ERROR_LOG_REPORT(SCEINTC, "QueryIntrHandlerInfo()"); RETURN(0); } @@ -692,7 +728,7 @@ void Register_SysclibForKernel() const HLEFunction InterruptManager[] = { {0xCA04A2B9, WrapU_UUUU, "sceKernelRegisterSubIntrHandler"}, - {0xD61E6961, WrapI_II, "sceKernelReleaseSubIntrHandler"}, + {0xD61E6961, WrapU_UU, "sceKernelReleaseSubIntrHandler"}, {0xFB8E22EC, WrapU_UU, "sceKernelEnableSubIntr"}, {0x8A389411, WrapU_UU, "sceKernelDisableSubIntr"}, {0x5CB5A78B, 0, "sceKernelSuspendSubIntr"}, diff --git a/Core/HLE/sceKernelInterrupt.h b/Core/HLE/sceKernelInterrupt.h index 3ad3611e63..013b46585c 100644 --- a/Core/HLE/sceKernelInterrupt.h +++ b/Core/HLE/sceKernelInterrupt.h @@ -139,11 +139,11 @@ bool __RunOnePendingInterrupt(); void __KernelReturnFromInterrupt(); void __RegisterIntrHandler(u32 intrNumber, IntrHandler* handler); -SubIntrHandler *__RegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 &error); +SubIntrHandler *__RegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg, u32 &error); int __ReleaseSubIntrHandler(int intrNumber, int subIntrNumber); u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg); -int sceKernelReleaseSubIntrHandler(int intrNumber, int subIntrNumber); +u32 sceKernelReleaseSubIntrHandler(u32 intrNumber, u32 subIntrNumber); u32 sceKernelEnableSubIntr(u32 intrNumber, u32 subIntrNumber); void Register_Kernel_Library();