mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-14 06:50:29 +02:00
Utility: Release volatile memory on a forced shutdown, fix dialog savestates
- The Yugioh savedata workaround force-stopped the other dialog without releasing the volatile memory it held, so the savedata helper then waited for it forever. - Screenshot's ShutdownStart and Update succeeded when no screenshot was running, putting it back into SHUTDOWN. - Savestates: Netconf didn't keep its request address, and a DNS json download going on was gone after a load, so it could wait for it forever; it now fetches the json again (it's cached). NpSignin didn't keep its request address either. Both restart their timeouts instead of timing out at once. With states from before, they keep the current address as they used to. - Loading a state from before NpSignin, GameSharing or HtmlViewer were saved resets them rather than keeping this session's state (including the HtmlViewer's memory block), and without Shutdown's side effects, which would write to the loaded memory and release its volatile lock. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
6dffcc91d2
commit
41b5074a98
9 files changed
+68
-6
No files matched your search
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
+12
-1
@@ -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));
|
||||
|
||||
Reference in new issue
Block a user