Correct sceKernelSelfStopUnloadModule

Fix #4237
This commit is contained in:
sum2012
2014-07-02 07:25:49 +08:00
parent e505655c2b
commit bc4a9149d3
+73 -1
View File
@@ -1845,6 +1845,78 @@ u32 sceKernelUnloadModule(u32 moduleId)
return moduleId;
}
u32 sceKernelStopUnloadSelfModule(u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr) {
// used in Tom Clancy's Splinter Cell Essentials
if (loadedModules.size() > 1) {
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;
int exitCode;
// TODO: In a lot of cases (even for errors), this should resched. Needs testing.
u32 error;
Module *module = kernelObjects.Get<Module>(moduleID, error);
if (!module) {
ERROR_LOG(SCEMODULE, "sceKernelStopUnloadSelfModule(%08x, %08x, %08x, %08x): invalid module id",argSize, argp, statusAddr, optionAddr);
return error;
}
u32 stopFunc = module->nm.module_stop_func;
if (module->nm.module_stop_thread_priority != 0)
priority = module->nm.module_stop_thread_priority;
if (module->nm.module_stop_thread_stacksize != 0)
stacksize = module->nm.module_stop_thread_stacksize;
if (module->nm.module_stop_thread_attr != 0)
attr = module->nm.module_stop_thread_attr;
// TODO: Need to test how this really works. Let's assume it's an override.
if (Memory::IsValidAddress(optionAddr)) {
auto options = PSPPointer<SceKernelSMOption>::Create(optionAddr);
// TODO: Check how size handling actually works.
if (options->size != 0 && options->priority != 0)
priority = options->priority;
if (options->size != 0 && options->stacksize != 0)
stacksize = options->stacksize;
if (options->size != 0 && options->attribute != 0)
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);
}
if (Memory::IsValidAddress(stopFunc)) {
SceUID threadID = __KernelCreateThread(module->nm.name, moduleID, stopFunc, priority, stacksize, attr, 0);
sceKernelStartThread(threadID, argSize, argp);
__KernelSetThreadRA(threadID, NID_MODULERETURN);
__KernelWaitCurThread(WAITTYPE_MODULE, moduleID, 1, 0, false, "unloadstopped module");
const ModuleWaitingThread mwt = { __KernelGetCurThread(), statusAddr };
module->nm.status = MODULE_STATUS_UNLOADING;
module->waitingThreads.push_back(mwt);
}
else if (stopFunc == 0) {
INFO_LOG(SCEMODULE, "sceKernelStopUnloadSelfModule(%08x, %08x, %08x, %08x): no stop func", argSize, argp, statusAddr, optionAddr);
sceKernelExitDeleteThread(exitCode);
module->Cleanup();
kernelObjects.Destroy<Module>(moduleID);
}
else {
ERROR_LOG_REPORT(SCEMODULE, "sceKernelStopUnloadSelfModule(%08x, %08x, %08x, %08x): bad stop func address", argSize, argp, statusAddr, optionAddr);
sceKernelExitDeleteThread(exitCode);
module->Cleanup();
kernelObjects.Destroy<Module>(moduleID);
}
}
else {
ERROR_LOG_REPORT(SCEMODULE, "UNIMPL sceKernelStopUnloadSelfModule(%08x, %08x, %08x, %08x): game has likely crashed", argSize, argp, statusAddr, optionAddr);
}
return 0;
}
u32 sceKernelStopUnloadSelfModuleWithStatus(u32 exitCode, u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr) {
if (loadedModules.size() > 1) {
ERROR_LOG_REPORT(SCEMODULE, "UNIMPL sceKernelStopUnloadSelfModuleWithStatus(%08x, %08x, %08x, %08x, %08x): game may have crashed", exitCode, argSize, argp, statusAddr, optionAddr);
@@ -2195,7 +2267,7 @@ const HLEFunction ModuleMgrForUser[] =
{0x977DE386,&WrapU_CUU<sceKernelLoadModule>,"sceKernelLoadModule"},
{0xb7f46618,&WrapU_UUU<sceKernelLoadModuleByID>,"sceKernelLoadModuleByID"},
{0x50F0C1EC,&WrapV_UUUUU<sceKernelStartModule>,"sceKernelStartModule", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0xD675EBB8,&sceKernelExitGame,"sceKernelSelfStopUnloadModule"}, //HACK
{0xD675EBB8,WrapU_UUUU<sceKernelStopUnloadSelfModule>, "sceKernelStopUnloadSelfModule"},
{0xd1ff982a,&WrapU_UUUUU<sceKernelStopModule>,"sceKernelStopModule", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED},
{0x2e0911aa,WrapU_U<sceKernelUnloadModule>,"sceKernelUnloadModule"},
{0x710F61B5,0,"sceKernelLoadModuleMs"},