diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index faeea8ead4..4930f92723 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,19 @@ 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; +} + +void hleEatMicro(int usec) +{ + // Maybe this should Idle, at least for larger delays? Could that cause issues? + currentMIPS->downcount -= (int) usToCycles(usec); +} + 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..2618eefcfb 100644 --- a/Core/HLE/HLE.h +++ b/Core/HLE/HLE.h @@ -87,6 +87,10 @@ 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 hleEatMicro(int usec); + void HLEInit(); void HLEDoState(PointerWrap &p); void HLEShutdown(); diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 651a5adbd1..2eebe46f1a 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -543,6 +543,7 @@ u32 sceDisplayWaitVblank() { return 0; } else { DEBUG_LOG(HLE,"sceDisplayWaitVblank() - not waiting since in vBlank"); + hleEatMicro(5); return 1; } } @@ -562,6 +563,7 @@ u32 sceDisplayWaitVblankCB() { return 0; } else { DEBUG_LOG(HLE,"sceDisplayWaitVblank() - not waiting since in vBlank"); + hleEatMicro(5); return 1; } } @@ -584,12 +586,7 @@ u32 sceDisplayGetVcount() { // Too spammy // DEBUG_LOG(HLE,"%i=sceDisplayGetVcount()", vCount); - // Puyo Puyo Fever polls this as a substitute for waiting for vblank. - // As a result, the game never gets to reschedule so it doesn't mix audio and things break. - // Need to find a better hack as this breaks games like Project Diva. - // hleReSchedule("sceDisplayGetVcount hack"); // Puyo puyo hack? - - CoreTiming::Idle(1000000); + hleEatMicro(2); return vCount; } 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..677b271fac 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -17,6 +17,7 @@ #include "HLE.h" #include "../MIPS/MIPS.h" +#include "Core/Reporting.h" #include "sceKernel.h" #include "sceKernelThread.h" @@ -30,6 +31,7 @@ #include "../Dialog/PSPOskDialog.h" const int SCE_ERROR_MODULE_BAD_ID = 0x80111101; +const int SCE_ERROR_AV_MODULE_BAD_ID = 0x80110F01; PSPSaveDialog saveDialog; PSPMsgDialog msgDialog; @@ -92,16 +94,21 @@ int sceUtilitySavedataUpdate(int animSpeed) u32 sceUtilityLoadAvModule(u32 module) { + if (module > 7) + { + ERROR_LOG(HLE, "sceUtilityLoadAvModule(%i): invalid module id", module); + Reporting::ReportMessage("sceUtilityLoadAvModule(%i): invalid module id", module); + return SCE_ERROR_AV_MODULE_BAD_ID; + } + DEBUG_LOG(HLE,"sceUtilityLoadAvModule(%i)", module); - hleReSchedule("utilityloadavmodule"); - return 0; + return hleDelayResult(0, "utility av module loaded", 25000); } u32 sceUtilityUnloadAvModule(u32 module) { DEBUG_LOG(HLE,"sceUtilityUnloadAvModule(%i)", module); - hleReSchedule("utilityunloadavmodule"); - return 0; + return hleDelayResult(0, "utility av module unloaded", 800); } u32 sceUtilityLoadModule(u32 module) @@ -110,6 +117,7 @@ u32 sceUtilityLoadModule(u32 module) if (module < 0x100 || module > 0x601) { ERROR_LOG(HLE, "sceUtilityLoadModule(%i): invalid module id", module); + Reporting::ReportMessage("sceUtilityLoadModule(%i): invalid module id", module); return SCE_ERROR_MODULE_BAD_ID; } @@ -117,10 +125,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) @@ -129,6 +136,7 @@ u32 sceUtilityUnloadModule(u32 module) if (module < 0x100 || module > 0x601) { ERROR_LOG(HLE, "sceUtilityUnloadModule(%i): invalid module id", module); + Reporting::ReportMessage("sceUtilityUnloadModule(%i): invalid module id", module); return SCE_ERROR_MODULE_BAD_ID; } @@ -136,10 +144,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) diff --git a/android/jni/TestRunner.cpp b/android/jni/TestRunner.cpp index 6170711f2c..3783081a1f 100644 --- a/android/jni/TestRunner.cpp +++ b/android/jni/TestRunner.cpp @@ -71,6 +71,10 @@ void RunTests() coreParam.useMediaEngine = false; coreParam.collectEmuLog = &output; + // Never report from tests. + std::string savedReportHost = g_Config.sReportHost; + g_Config.sReportHost = ""; + for (int i = 0; i < ARRAY_SIZE(testsToRun); i++) { const char *testName = testsToRun[i]; coreParam.fileToStart = g_Config.memCardDirectory + "pspautotests/tests/" + testName + ".prx"; @@ -136,4 +140,6 @@ void RunTests() } glstate.Restore(); glstate.viewport.set(0,0,pixel_xres,pixel_yres); + + g_Config.sReportHost = savedReportHost; } \ No newline at end of file diff --git a/headless/Headless.cpp b/headless/Headless.cpp index f8db1ff0fb..96ddf00612 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -166,6 +166,8 @@ int main(int argc, const char* argv[]) g_Config.bEnableSound = false; g_Config.bFirstRun = false; g_Config.bIgnoreBadMemAccess = true; + // Never report from tests. + g_Config.sReportHost = ""; #if defined(ANDROID) #elif defined(BLACKBERRY) || defined(__SYMBIAN32__) diff --git a/test.py b/test.py index d2836664b5..625b1d5c93 100755 --- a/test.py +++ b/test.py @@ -53,6 +53,7 @@ tests_good = [ "ctrl/sampling/sampling", "ctrl/sampling2/sampling2", "display/display", + "display/vblankmulti", "dmac/dmactest", "loader/bss/bss", "intr/intr", @@ -134,7 +135,6 @@ tests_next = [ "audio/atrac/atractest", "audio/mp3/mp3test", "audio/sascore/sascore", - "display/vblankmulti", "malloc/malloc", "threads/fpl/fpl", "threads/k0/k0",