diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index e80bfaf6c3..25b342a997 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1845,21 +1845,26 @@ u32 sceKernelUnloadModule(u32 moduleId) return moduleId; } -u32 sceKernelStopUnloadSelfModuleWithStatus(u32 exitCode, u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr) { +u32 hleKernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode, u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr, bool WithStatus) { if (loadedModules.size() > 1) { - ERROR_LOG_REPORT(SCEMODULE, "UNIMPL sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): game may have crashed", exitCode, argSize, argp, statusAddr, optionAddr); - + if (WithStatus) + ERROR_LOG_REPORT(SCEMODULE, "UNIMPL sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): game may have crashed", exitCode, argSize, argp, statusAddr, optionAddr); + else + ERROR_LOG_REPORT(SCEMODULE, "UNIMPL sceKernelStopUnloadSelfModule(%08x, %08x, %08x, %08x): game may have crashed", argSize, argp, statusAddr, optionAddr); SceUID moduleID = __KernelGetCurThreadModuleId(); u32 priority = 0x20; u32 stacksize = 0x40000; u32 attr = 0; - // TODO: In a lot of cases (even for errors), this should resched. Needs testing. u32 error; Module *module = kernelObjects.Get(moduleID, error); if (!module) { - ERROR_LOG(SCEMODULE, "sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): invalid module id", exitCode, argSize, argp, statusAddr, optionAddr); + if (WithStatus) + ERROR_LOG(SCEMODULE, "sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): invalid module id", exitCode, argSize, argp, statusAddr, optionAddr); + else + ERROR_LOG(SCEMODULE, "sceKernelStopUnloadSelfModule(%08x, %08x, %08x, %08x): invalid module id", argSize, argp, statusAddr, optionAddr); + return error; } @@ -1883,7 +1888,7 @@ u32 sceKernelStopUnloadSelfModuleWithStatus(u32 exitCode, u32 argSize, u32 argp, attr = options->attribute; // TODO: Maybe based on size? else if (attr != 0) - WARN_LOG_REPORT(SCEMODULE, "Stopping module with attr=%x, but options specify 0", attr); + WARN_LOG_REPORT(SCEMODULE, "Stopping module with attr=%x, but options specify 0", attr); } if (Memory::IsValidAddress(stopFunc)) { @@ -1896,24 +1901,41 @@ u32 sceKernelStopUnloadSelfModuleWithStatus(u32 exitCode, u32 argSize, u32 argp, module->nm.status = MODULE_STATUS_UNLOADING; module->waitingThreads.push_back(mwt); } else if (stopFunc == 0) { - INFO_LOG(SCEMODULE, "sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): no stop func", exitCode, argSize, argp, statusAddr, optionAddr); + if (WithStatus) + INFO_LOG(SCEMODULE, "sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): no stop func", exitCode, argSize, argp, statusAddr, optionAddr); + else + INFO_LOG(SCEMODULE, "sceKernelStopUnloadSelfModule(%08x, %08x, %08x, %08x): no stop func", argSize, argp, statusAddr, optionAddr); sceKernelExitDeleteThread(exitCode); module->Cleanup(); kernelObjects.Destroy(moduleID); } else { - ERROR_LOG_REPORT(SCEMODULE, "sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): bad stop func address", exitCode, argSize, argp, statusAddr, optionAddr); + if (WithStatus) + ERROR_LOG_REPORT(SCEMODULE, "sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): bad stop func address", exitCode, argSize, argp, statusAddr, optionAddr); + else + ERROR_LOG_REPORT(SCEMODULE, "sceKernelStopUnloadSelfModule(%08x, %08x, %08x, %08x): bad stop func address", argSize, argp, statusAddr, optionAddr); sceKernelExitDeleteThread(exitCode); module->Cleanup(); kernelObjects.Destroy(moduleID); } } else { - ERROR_LOG_REPORT(SCEMODULE, "UNIMPL sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): game has likely crashed", exitCode, argSize, argp, statusAddr, optionAddr); + if (WithStatus) + ERROR_LOG_REPORT(SCEMODULE, "UNIMPL sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): game has likely crashed", exitCode, argSize, argp, statusAddr, optionAddr); + else + ERROR_LOG_REPORT(SCEMODULE, "UNIMPL sceKernelStopUnloadSelfModule(%08x, %08x, %08x, %08x): game has likely crashed", argSize, argp, statusAddr, optionAddr); } - // Probably similar to sceKernelStopModule, but games generally call this when they die. return 0; } +u32 sceKernelStopUnloadSelfModule(u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr) { + // Used in Tom Clancy's Splinter Cell Essentials,Ghost in the Shell Stand Alone Complex + return hleKernelStopUnloadSelfModuleWithOrWithoutStatus(0, argSize, argp, statusAddr, optionAddr, false); +} + +u32 sceKernelStopUnloadSelfModuleWithStatus(u32 exitCode, u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr) { + return hleKernelStopUnloadSelfModuleWithOrWithoutStatus(exitCode, argSize, argp, statusAddr, optionAddr, true); +} + void __KernelReturnFromModuleFunc() { // Return from the thread as normal. @@ -2195,7 +2217,7 @@ const HLEFunction ModuleMgrForUser[] = {0x977DE386,&WrapU_CUU,"sceKernelLoadModule"}, {0xb7f46618,&WrapU_UUU,"sceKernelLoadModuleByID"}, {0x50F0C1EC,&WrapV_UUUUU,"sceKernelStartModule", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED}, - {0xD675EBB8,&sceKernelExitGame,"sceKernelSelfStopUnloadModule"}, //HACK + {0xD675EBB8,WrapU_UUUU, "sceKernelStopUnloadSelfModule"}, {0xd1ff982a,&WrapU_UUUUU,"sceKernelStopModule", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED}, {0x2e0911aa,WrapU_U,"sceKernelUnloadModule"}, {0x710F61B5,0,"sceKernelLoadModuleMs"}, diff --git a/Core/HLE/sceKernelModule.h b/Core/HLE/sceKernelModule.h index 0df80b797d..ff495e6283 100644 --- a/Core/HLE/sceKernelModule.h +++ b/Core/HLE/sceKernelModule.h @@ -29,6 +29,7 @@ void __KernelModuleShutdown(); u32 __KernelGetModuleGP(SceUID module); bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_string); void __KernelReturnFromModuleFunc(); +u32 hleKernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode, u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr, bool WithStatus); void Register_ModuleMgrForUser(); void Register_ModuleMgrForKernel(); \ No newline at end of file