From d2be4072237162108fdaaccf6c93efb8b9a7e4ae Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 9 Mar 2013 11:37:57 -0800 Subject: [PATCH] Make HLE func delayed results more generic. --- Core/HLE/HLE.cpp | 25 +++++++++++++++++++++++++ Core/HLE/HLE.h | 3 +++ Core/HLE/sceKernelModule.cpp | 17 +---------------- Core/HLE/sceUtility.cpp | 10 ++++------ 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index faeea8ead4..c8ce961aee 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -21,6 +21,7 @@ #include #include "../MemMap.h" #include "../Config.h" +#include "Core/CoreTiming.h" #include "Core/Reporting.h" #include "HLETables.h" @@ -55,12 +56,27 @@ enum static std::vector moduleDB; static std::vector unresolvedSyscalls; static std::vector exportedCalls; +static int delayedResultEvent = -1; static int hleAfterSyscall = HLE_AFTER_NOTHING; static const char *hleAfterSyscallReschedReason; +void hleDelayResultFinish(u64 userdata, int cycleslate) +{ + u32 error; + SceUID threadID = (SceUID) userdata; + SceUID verify = __KernelGetWaitID(threadID, WAITTYPE_DELAY, error); + SceUID result = __KernelGetWaitValue(threadID, error); + + if (error == 0 && verify == 1) + __KernelResumeThreadFromWait(threadID, result); + else + WARN_LOG(HLE, "Someone else woke up HLE-blocked thread?"); +} + void HLEInit() { RegisterAllModules(); + delayedResultEvent = CoreTiming::RegisterEvent("HLEDelayedResult", hleDelayResultFinish); } void HLEDoState(PointerWrap &p) @@ -68,6 +84,8 @@ void HLEDoState(PointerWrap &p) Syscall sc = {""}; p.Do(unresolvedSyscalls, sc); p.Do(exportedCalls, sc); + p.Do(delayedResultEvent); + CoreTiming::RestoreRegisterEvent(delayedResultEvent, "HLEDelayedResult", hleDelayResultFinish); p.DoMarker("HLE"); } @@ -310,6 +328,13 @@ bool hleExecuteDebugBreak(const HLEFunction &func) return true; } +u32 hleDelayResult(u32 result, const char *reason, int usec) +{ + CoreTiming::ScheduleEvent(usToCycles(usec), delayedResultEvent, __KernelGetCurThread()); + __KernelWaitCurThread(WAITTYPE_DELAY, 1, result, 0, false, reason); + return result; +} + inline void hleFinishSyscall(int modulenum, int funcnum) { if ((hleAfterSyscall & HLE_AFTER_CURRENT_CALLBACKS) != 0) diff --git a/Core/HLE/HLE.h b/Core/HLE/HLE.h index 40b4a17dbc..2f71f3c9b8 100644 --- a/Core/HLE/HLE.h +++ b/Core/HLE/HLE.h @@ -87,6 +87,9 @@ void hleRunInterrupts(); // Pause emulation after the syscall finishes. void hleDebugBreak(); +// Delays the result for usec microseconds, allowing other threads to run during this time. +u32 hleDelayResult(u32 result, const char *reason, int usec); + void HLEInit(); void HLEDoState(PointerWrap &p); void HLEShutdown(); diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index f60ff6e215..bb23a869df 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -230,24 +230,13 @@ struct SceKernelSMOption { ////////////////////////////////////////////////////////////////////////// // STATE BEGIN static int actionAfterModule; -static int eventLoadModule = -1; static SceUID mainModuleID; // hack // STATE END ////////////////////////////////////////////////////////////////////////// -void __KernelModuleLoaded(u64 userdata, int cycleslate) -{ - u32 error; - SceUID threadID = userdata & 0xFFFFFFFF; - SceUID moduleID = __KernelGetWaitValue(threadID, error); - if (error == 0 && moduleID != 0) - __KernelResumeThreadFromWait(threadID, moduleID); -} - void __KernelModuleInit() { actionAfterModule = __KernelRegisterActionType(AfterModuleEntryCall::Create); - eventLoadModule = CoreTiming::RegisterEvent("LoadModule", __KernelModuleLoaded); } void __KernelModuleDoState(PointerWrap &p) @@ -255,8 +244,6 @@ void __KernelModuleDoState(PointerWrap &p) p.Do(mainModuleID); p.Do(actionAfterModule); __KernelRestoreActionType(actionAfterModule, AfterModuleEntryCall::Create); - p.Do(eventLoadModule); - CoreTiming::RestoreRegisterEvent(eventLoadModule, "LoadModule", __KernelModuleLoaded); p.DoMarker("sceKernelModule"); } @@ -827,9 +814,7 @@ u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr) } // TODO: This is not the right timing and probably not the right wait type, just an approximation. - CoreTiming::ScheduleEvent(usToCycles(500), eventLoadModule, __KernelGetCurThread()); - __KernelWaitCurThread(WAITTYPE_SEMA, -1, module->GetUID(), 0, false, "module loaded"); - return module->GetUID(); + return hleDelayResult(module->GetUID(), "module loaded", 500); } void sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 returnValueAddr, u32 optionAddr) diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index e3c15bca52..e1ad3272db 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -117,10 +117,9 @@ u32 sceUtilityLoadModule(u32 module) // TODO: Each module has its own timing, technically, but this is a low-end. // Note: Some modules have dependencies, but they still resched. if (module == 0x3FF) - sceKernelDelayThread(130); + return hleDelayResult(0, "utility module loaded", 130); else - sceKernelDelayThread(25000); - return 0; + return hleDelayResult(0, "utility module loaded", 25000); } u32 sceUtilityUnloadModule(u32 module) @@ -136,10 +135,9 @@ u32 sceUtilityUnloadModule(u32 module) // TODO: Each module has its own timing, technically, but this is a low-end. // Note: If not loaded, it should not reschedule actually... if (module == 0x3FF) - sceKernelDelayThread(110); + return hleDelayResult(0, "utility module unloaded", 110); else - sceKernelDelayThread(400); - return 0; + return hleDelayResult(0, "utility module unloaded", 400); } int sceUtilityMsgDialogInitStart(u32 structAddr)