diff --git a/Core/Dialog/PSPDialog.cpp b/Core/Dialog/PSPDialog.cpp index 3862189990..8870017a82 100644 --- a/Core/Dialog/PSPDialog.cpp +++ b/Core/Dialog/PSPDialog.cpp @@ -24,6 +24,7 @@ #include "Core/Dialog/PSPDialog.h" #include "Core/HLE/sceCtrl.h" #include "Core/HLE/scePower.h" +#include "Core/HLE/sceUtility.h" #include "Core/MemMapHelpers.h" #include "Core/Util/PPGeDraw.h" @@ -42,11 +43,13 @@ PSPDialog::DialogStatus PSPDialog::GetStatus() { if (pendingStatus == SCE_UTILITY_STATUS_NONE && status == SCE_UTILITY_STATUS_SHUTDOWN) { if (volatileLocked_) { FinishVolatile(); + UtilityCancelVolatileUnlock(); volatileLocked_ = false; } } else if (pendingStatus == SCE_UTILITY_STATUS_RUNNING && status == SCE_UTILITY_STATUS_INITIALIZE) { if (!volatileLocked_) { volatileLocked_ = KernelVolatileMemLock(0, 0, 0) == 0; + UtilityCancelVolatileUnlock(); changeAllowed = volatileLocked_; } } @@ -71,12 +74,14 @@ void PSPDialog::ChangeStatus(DialogStatus newStatus, int delayUs) { if (newStatus == SCE_UTILITY_STATUS_NONE && status == SCE_UTILITY_STATUS_SHUTDOWN) { if (volatileLocked_) { FinishVolatile(); + UtilityCancelVolatileUnlock(); volatileLocked_ = false; } } else if (newStatus == SCE_UTILITY_STATUS_RUNNING && status == SCE_UTILITY_STATUS_INITIALIZE) { if (!volatileLocked_) { // TODO: Should probably make the status pending instead? volatileLocked_ = KernelVolatileMemLock(0, 0, 0) == 0; + UtilityCancelVolatileUnlock(); } } status = newStatus; @@ -84,6 +89,9 @@ void PSPDialog::ChangeStatus(DialogStatus newStatus, int delayUs) { } else { pendingStatus = newStatus; pendingStatusTicks = CoreTiming::GetTicks() + usToCycles(delayUs); + if (volatileLocked_ && newStatus == SCE_UTILITY_STATUS_NONE && status == SCE_UTILITY_STATUS_SHUTDOWN) { + UtilityScheduleVolatileUnlock(usToCycles(delayUs)); + } } } diff --git a/Core/Dialog/PSPDialog.h b/Core/Dialog/PSPDialog.h index 0804f36240..7a156bad6c 100644 --- a/Core/Dialog/PSPDialog.h +++ b/Core/Dialog/PSPDialog.h @@ -83,6 +83,9 @@ public: void StartDraw(); void EndDraw(); + + void FinishVolatile(); + protected: PPGeStyle FadedStyle(PPGeAlign align, float scale); PPGeImageStyle FadedImageStyle(); @@ -123,8 +126,6 @@ protected: int cancelButtonFlag; private: - void FinishVolatile(); - DialogStatus status = SCE_UTILITY_STATUS_NONE; bool volatileLocked_ = false; }; diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 8e2c27ac09..221a8ce24b 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -24,11 +24,12 @@ #include "Common/Serialize/SerializeFuncs.h" #include "Common/Serialize/SerializeMap.h" #include "Common/Serialize/SerializeSet.h" +#include "Core/Config.h" +#include "Core/CoreTiming.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/MIPS/MIPS.h" #include "Core/Reporting.h" -#include "Core/Config.h" #include "Core/System.h" #include "Core/HLE/sceKernel.h" @@ -36,8 +37,6 @@ #include "Core/HLE/sceKernelThread.h" #include "Core/HLE/sceUtility.h" -#include "Core/HLE/sceCtrl.h" -#include "Core/Util/PPGeDraw.h" #include "Core/Dialog/PSPSaveDialog.h" #include "Core/Dialog/PSPMsgDialog.h" #include "Core/Dialog/PSPPlaceholderDialog.h" @@ -65,7 +64,6 @@ const int SCE_ERROR_MODULE_BAD_ID = 0x80111101; const int SCE_ERROR_MODULE_ALREADY_LOADED = 0x80111102; const int SCE_ERROR_MODULE_NOT_LOADED = 0x80111103; const int SCE_ERROR_AV_MODULE_BAD_ID = 0x80110F01; -int oldStatus = 100; //random value static const int noDeps[] = {0}; static const int httpModuleDeps[] = {0x0102, 0x0103, 0x0104, 0}; @@ -141,7 +139,9 @@ static PSPNetconfDialog netDialog; static PSPScreenshotDialog screenshotDialog; static PSPGamedataInstallDialog gamedataInstallDialog; +static int oldStatus = 100; //random value static std::map currentlyLoadedModules; +static int volatileUnlockEvent = -1; static void ActivateDialog(UtilityDialogType type) { if (!currentDialogActive) { @@ -160,15 +160,26 @@ static void DeactivateDialog() { } } +static void UtilityVolatileUnlock(u64 userdata, int cyclesLate) { + // There can only be one active, so just try each of them. + saveDialog.FinishVolatile(); + msgDialog.FinishVolatile(); + oskDialog.FinishVolatile(); + netDialog.FinishVolatile(); + screenshotDialog.FinishVolatile(); + gamedataInstallDialog.FinishVolatile(); +} + void __UtilityInit() { currentDialogType = UTILITY_DIALOG_NONE; DeactivateDialog(); SavedataParam::Init(); currentlyLoadedModules.clear(); + volatileUnlockEvent = CoreTiming::RegisterEvent("UtilityVolatileUnlock", UtilityVolatileUnlock); } void __UtilityDoState(PointerWrap &p) { - auto s = p.Section("sceUtility", 1, 2); + auto s = p.Section("sceUtility", 1, 3); if (!s) { return; } @@ -191,6 +202,13 @@ void __UtilityDoState(PointerWrap &p) { currentlyLoadedModules[*it] = 0; } } + + if (s >= 3) { + Do(p, volatileUnlockEvent); + } else { + volatileUnlockEvent = -1; + } + CoreTiming::RestoreRegisterEvent(volatileUnlockEvent, "UtilityVolatileUnlock", UtilityVolatileUnlock); } void __UtilityShutdown() { @@ -202,6 +220,14 @@ void __UtilityShutdown() { gamedataInstallDialog.Shutdown(true); } +void UtilityScheduleVolatileUnlock(s64 cyclesIntoFuture) { + CoreTiming::ScheduleEvent(cyclesIntoFuture, volatileUnlockEvent, 0); +} + +void UtilityCancelVolatileUnlock() { + CoreTiming::UnscheduleEvent(volatileUnlockEvent, 0); +} + static int sceUtilitySavedataInitStart(u32 paramAddr) { if (currentDialogActive && currentDialogType != UTILITY_DIALOG_SAVEDATA) diff --git a/Core/HLE/sceUtility.h b/Core/HLE/sceUtility.h index 6d0be037bf..593d45d8fd 100644 --- a/Core/HLE/sceUtility.h +++ b/Core/HLE/sceUtility.h @@ -83,4 +83,7 @@ void __UtilityInit(); void __UtilityDoState(PointerWrap &p); void __UtilityShutdown(); +void UtilityScheduleVolatileUnlock(s64 cyclesIntoFuture); +void UtilityCancelVolatileUnlock(); + void Register_sceUtility();