diff --git a/Core/Dialog/PSPDialog.cpp b/Core/Dialog/PSPDialog.cpp index c87a35dc1a..b1cd357cbe 100644 --- a/Core/Dialog/PSPDialog.cpp +++ b/Core/Dialog/PSPDialog.cpp @@ -273,6 +273,15 @@ u32 PSPDialog::CalcFadedColor(u32 inColor) const { return (inColor & 0x00FFFFFF) | (alpha << 24); } +void PSPDialog::ResetState() { + status = SCE_UTILITY_STATUS_NONE; + pendingStatus = SCE_UTILITY_STATUS_NONE; + pendingStatusTicks = 0; + volatileLocked_ = false; + isFading = false; + fadeValue = 0; +} + void PSPDialog::DoState(PointerWrap &p) { auto s = p.Section("PSPDialog", 1, 3); if (!s) diff --git a/Core/Dialog/PSPDialog.h b/Core/Dialog/PSPDialog.h index 7272225533..48a46300a5 100644 --- a/Core/Dialog/PSPDialog.h +++ b/Core/Dialog/PSPDialog.h @@ -51,6 +51,9 @@ public: virtual int Update(int animSpeed) = 0; virtual int Shutdown(bool force = false); virtual void DoState(PointerWrap &p); + // For loading a state that doesn't have this dialog: back to NONE, without anything Shutdown does + // on the way (writing results, releasing volatile memory), which would hit the loaded state. + virtual void ResetState(); virtual pspUtilityDialogCommon *GetCommonParam() { // This is returned properly by the derived classes (or should be...). return nullptr; diff --git a/Core/Dialog/PSPHtmlViewerDialog.cpp b/Core/Dialog/PSPHtmlViewerDialog.cpp index 391a4d5185..1c9559e5c0 100644 --- a/Core/Dialog/PSPHtmlViewerDialog.cpp +++ b/Core/Dialog/PSPHtmlViewerDialog.cpp @@ -191,6 +191,14 @@ int PSPHtmlViewerDialog::Shutdown(bool force) { return 0; } +void PSPHtmlViewerDialog::ResetState() { + PSPDialog::ResetState(); + // The block belonged to this session's memory, not the loaded one. + workMemory_ = 0; + started_ = false; + params_ = 0; +} + void PSPHtmlViewerDialog::DoState(PointerWrap &p) { PSPDialog::DoState(p); diff --git a/Core/Dialog/PSPHtmlViewerDialog.h b/Core/Dialog/PSPHtmlViewerDialog.h index aa57f54ac4..5a5868a68b 100644 --- a/Core/Dialog/PSPHtmlViewerDialog.h +++ b/Core/Dialog/PSPHtmlViewerDialog.h @@ -35,6 +35,7 @@ public: int Update(int animSpeed) override; int Shutdown(bool force = false) override; void DoState(PointerWrap &p) override; + void ResetState() override; pspUtilityDialogCommon *GetCommonParam() override; // Until one has started, all the HtmlViewer calls return WRONG_TYPE. diff --git a/Core/Dialog/PSPNetconfDialog.cpp b/Core/Dialog/PSPNetconfDialog.cpp index b361a0e886..64426ce490 100644 --- a/Core/Dialog/PSPNetconfDialog.cpp +++ b/Core/Dialog/PSPNetconfDialog.cpp @@ -344,7 +344,8 @@ int PSPNetconfDialog::Update(int animSpeed) { EndDraw(); } - if (ReadStatus() == SCE_UTILITY_STATUS_FINISHED || pendingStatus == SCE_UTILITY_STATUS_FINISHED) + const bool finished = ReadStatus() == SCE_UTILITY_STATUS_FINISHED || pendingStatus == SCE_UTILITY_STATUS_FINISHED; + if (finished && Memory::IsValidAddress(requestAddr)) Memory::Memcpy(requestAddr, &request, std::min((u32)request.common.size, (u32)sizeof(request)), "NetConfDialogParam"); return 0; @@ -365,7 +366,7 @@ int PSPNetconfDialog::Shutdown(bool force) { void PSPNetconfDialog::DoState(PointerWrap &p) { PSPDialog::DoState(p); - auto s = p.Section("PSPNetconfigDialog", 0, 2); + auto s = p.Section("PSPNetconfigDialog", 0, 3); if (!s) return; @@ -380,9 +381,22 @@ void PSPNetconfDialog::DoState(PointerWrap &p) { scanStep = 0; connResult = -1; } + if (s >= 3) { + Do(p, requestAddr); + Do(p, showNoWlanNotice_); + } else if (p.mode == p.MODE_READ) { + // requestAddr is kept: most likely the same address in the same game. + showNoWlanNotice_ = !g_Config.bEnableWlan; + } if (p.mode == p.MODE_READ) { - startTime = 0; + // The connect timeout starts over. The DNS config the json gave isn't in the state, so get + // it again (it's cached). + startTime = (u64)(time_now_d() * 1000000.0); + jsonReady_ = false; + if (ReadStatus() != SCE_UTILITY_STATUS_NONE) { + StartInfraJsonDownload(); + } } } diff --git a/Core/Dialog/PSPNpSigninDialog.cpp b/Core/Dialog/PSPNpSigninDialog.cpp index 064c54fb11..c97f6e39d7 100644 --- a/Core/Dialog/PSPNpSigninDialog.cpp +++ b/Core/Dialog/PSPNpSigninDialog.cpp @@ -185,16 +185,20 @@ int PSPNpSigninDialog::Shutdown(bool force) { void PSPNpSigninDialog::DoState(PointerWrap &p) { PSPDialog::DoState(p); - auto s = p.Section("PSPNpSigninDialog", 1, 1); + auto s = p.Section("PSPNpSigninDialog", 1, 2); if (!s) return; Do(p, request); Do(p, step); //Do(p, npSigninResult); + // Older states keep this session's requestAddr: most likely the same address in the same game. + if (s >= 2) { + Do(p, requestAddr); + } if (p.mode == p.MODE_READ) { - startTime = 0; + startTime = (u64)(time_now_d() * 1000000.0); } } diff --git a/Core/Dialog/PSPScreenshotDialog.cpp b/Core/Dialog/PSPScreenshotDialog.cpp index dcef0c30c5..85b48d4f7f 100644 --- a/Core/Dialog/PSPScreenshotDialog.cpp +++ b/Core/Dialog/PSPScreenshotDialog.cpp @@ -81,6 +81,9 @@ int PSPScreenshotDialog::Init(u32 paramAddr) { } int PSPScreenshotDialog::Update(int animSpeed) { + if (ReadStatus() == SCE_UTILITY_STATUS_NONE) { + return SCE_ERROR_UTILITY_INVALID_STATUS; + } UpdateCommon(); if (UseAutoStatus()) { if (ReadStatus() == SCE_UTILITY_STATUS_INITIALIZE) { @@ -98,6 +101,14 @@ int PSPScreenshotDialog::Update(int animSpeed) { return 0; } +int PSPScreenshotDialog::Shutdown(bool force) { + // TODO: Only from FINISHED, like the other dialogs? Update moves on to SHUTDOWN by itself here. + if (!force && ReadStatus() == SCE_UTILITY_STATUS_NONE) { + return SCE_ERROR_UTILITY_INVALID_STATUS; + } + return PSPDialog::Shutdown(force); +} + int PSPScreenshotDialog::ContStart() { // Based on JPCSP http://code.google.com/p/jpcsp/source/detail?r=3381 if (ReadStatus() != SCE_UTILITY_STATUS_SCREENSHOT_UNKNOWN) diff --git a/Core/Dialog/PSPScreenshotDialog.h b/Core/Dialog/PSPScreenshotDialog.h index c5eb2c0c06..48d6a1679d 100644 --- a/Core/Dialog/PSPScreenshotDialog.h +++ b/Core/Dialog/PSPScreenshotDialog.h @@ -29,6 +29,7 @@ public: int Init(u32 paramAddr); int Update(int animSpeed) override; + int Shutdown(bool force = false) override; int ContStart(); void DoState(PointerWrap &p) override; pspUtilityDialogCommon *GetCommonParam() override; diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 054b2b0a5e..77f643ab9b 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -609,13 +609,21 @@ void __UtilityDoState(PointerWrap &p) { lastSaveStateVersion = -1; } else { lastSaveStateVersion = s.Version(); + if (p.mode == PointerWrap::MODE_READ) { + npSigninDialog->ResetState(); + } } + // Dialogs an older state doesn't have mustn't keep this session's state. if (s >= 8) { gameSharingDialog->DoState(p); + } else if (p.mode == PointerWrap::MODE_READ) { + gameSharingDialog->ResetState(); } if (s >= 9) { htmlViewerDialog->DoState(p); + } else if (p.mode == PointerWrap::MODE_READ) { + htmlViewerDialog->ResetState(); } if (!hasAccessThread && accessThread) { @@ -790,6 +798,9 @@ static int UtilityFinishDialog(int type) { static int sceUtilitySavedataInitStart(u32 paramAddr) { if (UtilityDialogBusy() && currentDialogType != UtilityDialogType::SAVEDATA && PSP_CoreParameter().compat.flags().YugiohSaveFix) { WARN_LOG_REPORT(Log::sceUtility, "Yugioh Savedata Correction (state=%d)", lastSaveStateVersion); + PSPDialog *other = CurrentDialog(currentDialogType); + // Its own lock first, so the unlock below only takes one its thread held. + other->FinishVolatile(); if (accessThread) { accessThread->Terminate(); delete accessThread; @@ -799,7 +810,7 @@ static int sceUtilitySavedataInitStart(u32 paramAddr) { // Try to unlock in case other dialog was shutting down. KernelVolatileMemUnlock(0); } - CurrentDialog(currentDialogType)->Shutdown(true); + other->Shutdown(true); } return hleLogDebug(Log::sceUtility, UtilityInitStart(UtilityDialogType::SAVEDATA, saveDialog, paramAddr));