From 51909a3256946a070b5eec2cf1dbae90bc8128c1 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 29 Jun 2014 17:07:04 -0700 Subject: [PATCH 1/4] Separate out io actions from save dialog display. --- Core/Dialog/PSPSaveDialog.cpp | 268 ++++++++++++++++++---------------- Core/Dialog/PSPSaveDialog.h | 3 + 2 files changed, 142 insertions(+), 129 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 4060405db0..b9550131d3 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -618,11 +618,6 @@ int PSPSaveDialog::Update(int animSpeed) display = DS_SAVE_CONFIRM_OVERWRITE; } else { display = DS_SAVE_SAVING; - if (param.Save(param.GetPspParam(), GetSelectedSaveDirName())) { - param.SetPspParam(param.GetPspParam()); // Optim : Just Update modified save - display = DS_SAVE_DONE; - } else - display = DS_SAVE_LIST_CHOICE; // This will probably need error message ? } } EndDraw(); @@ -643,13 +638,6 @@ int PSPSaveDialog::Update(int animSpeed) StartFade(false); } else if (IsButtonPressed(okButtonFlag)) { display = DS_SAVE_SAVING; - if (param.Save(param.GetPspParam(), GetSelectedSaveDirName())) { - param.SetPspParam(param.GetPspParam()); // Optim : Just Update modified save - display = DS_SAVE_DONE; - } else { - // TODO: This should probably show an error message? - StartFade(false); - } } EndDraw(); @@ -674,21 +662,13 @@ int PSPSaveDialog::Update(int animSpeed) } } else if (IsButtonPressed(okButtonFlag)) { display = DS_SAVE_SAVING; - if (param.Save(param.GetPspParam(), GetSelectedSaveDirName())) { - param.SetPspParam(param.GetPspParam()); // Optim : Just Update modified save - display = DS_SAVE_DONE; - } else { - // TODO: This should probably show an error message? - if (param.GetPspParam()->mode != SCE_UTILITY_SAVEDATA_TYPE_SAVE) - display = DS_SAVE_LIST_CHOICE; - else - StartFade(false); - } } EndDraw(); break; case DS_SAVE_SAVING: + ExecuteIOAction(); + StartDraw(); DisplaySaveIcon(); @@ -735,8 +715,6 @@ int PSPSaveDialog::Update(int animSpeed) StartFade(false); } else if (IsButtonPressed(okButtonFlag)) { display = DS_LOAD_LOADING; - if (param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave)) - display = DS_LOAD_DONE; } EndDraw(); @@ -757,17 +735,13 @@ int PSPSaveDialog::Update(int animSpeed) StartFade(false); } else if (IsButtonPressed(okButtonFlag)) { display = DS_LOAD_LOADING; - if (param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave)) - display = DS_LOAD_DONE; - else { - param.GetPspParam()->common.result = SCE_UTILITY_DIALOG_RESULT_CANCEL; - StartFade(false); - } } EndDraw(); break; case DS_LOAD_LOADING: + ExecuteIOAction(); + StartDraw(); DisplaySaveIcon(); @@ -857,17 +831,14 @@ int PSPSaveDialog::Update(int animSpeed) display = DS_DELETE_LIST_CHOICE; else { display = DS_DELETE_DELETING; - if (param.Delete(param.GetPspParam(),currentSelectedSave)) { - param.SetPspParam(param.GetPspParam()); // Optim : Just Update modified save - display = DS_DELETE_DONE; - } else - display = DS_DELETE_LIST_CHOICE; // This will probably need error message ? } } EndDraw(); break; case DS_DELETE_DELETING: + ExecuteIOAction(); + StartDraw(); DisplayMessage(d->T("Deleting","Deleting\nPlease Wait...")); @@ -910,99 +881,10 @@ int PSPSaveDialog::Update(int animSpeed) break; case DS_NONE: // For action which display nothing - { - switch ((SceUtilitySavedataType)(u32)param.GetPspParam()->mode) - { - case SCE_UTILITY_SAVEDATA_TYPE_LOAD: // Only load and exit - case SCE_UTILITY_SAVEDATA_TYPE_AUTOLOAD: - if (param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave)) - param.GetPspParam()->common.result = 0; - else - param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_LOAD_NO_DATA; - ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); - break; - case SCE_UTILITY_SAVEDATA_TYPE_SAVE: // Only save and exit - case SCE_UTILITY_SAVEDATA_TYPE_AUTOSAVE: - if (param.Save(param.GetPspParam(), GetSelectedSaveDirName())) - param.GetPspParam()->common.result = 0; - else - param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_SAVE_MS_NOSPACE; - ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); - break; - case SCE_UTILITY_SAVEDATA_TYPE_SIZES: - param.GetPspParam()->common.result = param.GetSizes(param.GetPspParam()); - ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); - break; - case SCE_UTILITY_SAVEDATA_TYPE_LIST: - param.GetList(param.GetPspParam()); - param.GetPspParam()->common.result = 0; - ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); - break; - case SCE_UTILITY_SAVEDATA_TYPE_FILES: - param.GetPspParam()->common.result = param.GetFilesList(param.GetPspParam()); - ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); - break; - case SCE_UTILITY_SAVEDATA_TYPE_GETSIZE: - { - bool result = param.GetSize(param.GetPspParam()); - // TODO: According to JPCSP, should test/verify this part but seems edge casey. - if (MemoryStick_State() != PSP_MEMORYSTICK_STATE_DRIVER_READY) - param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_MEMSTICK; - else if (result) - param.GetPspParam()->common.result = 0; - else - param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; - ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); - } - break; - case SCE_UTILITY_SAVEDATA_TYPE_DELETEDATA: - DEBUG_LOG(SCEUTILITY, "sceUtilitySavedata DELETEDATA: %s", param.GetPspParam()->saveName); - param.GetPspParam()->common.result = param.DeleteData(param.GetPspParam()); - ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); - break; - //case SCE_UTILITY_SAVEDATA_TYPE_AUTODELETE: - case SCE_UTILITY_SAVEDATA_TYPE_SINGLEDELETE: - if (param.Delete(param.GetPspParam(), param.GetSelectedSave())) - param.GetPspParam()->common.result = 0; - else - param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_DELETE_NO_DATA; - ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); - break; - // TODO: Should reset the directory's other files. - case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATA: - case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATASECURE: - if (param.Save(param.GetPspParam(), GetSelectedSaveDirName(), param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_MAKEDATASECURE)) - param.GetPspParam()->common.result = 0; - else - param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; - ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); - break; - case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATA: - case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATASECURE: - if (param.Save(param.GetPspParam(), GetSelectedSaveDirName(), param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_WRITEDATASECURE)) - param.GetPspParam()->common.result = 0; - else - param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; - ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); - break; - case SCE_UTILITY_SAVEDATA_TYPE_READDATA: - case SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE: - if (param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave, param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE)) - param.GetPspParam()->common.result = 0; - else if (param.secureCanSkip(param.GetPspParam(),param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE)) { - INFO_LOG(SCEUTILITY,"Has not been saved yet, just skip."); - param.GetPspParam()->common.result = 0; - } - else - param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; // not sure if correct code - ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); - break; - default: - ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); - break; - } - } + ExecuteNotVisibleIOAction(); + ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); break; + default: ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); break; @@ -1014,8 +896,136 @@ int PSPSaveDialog::Update(int animSpeed) return 0; } -int PSPSaveDialog::Shutdown(bool force) -{ +void PSPSaveDialog::ExecuteIOAction() { + switch (display) { + case DS_LOAD_LOADING: + if (param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave)) { + display = DS_LOAD_DONE; + } else { + // TODO: This should probably show an error message? + param.GetPspParam()->common.result = SCE_UTILITY_DIALOG_RESULT_CANCEL; + StartFade(false); + } + break; + case DS_SAVE_SAVING: + if (param.Save(param.GetPspParam(), GetSelectedSaveDirName())) { + param.SetPspParam(param.GetPspParam()); // Optim : Just Update modified save + display = DS_SAVE_DONE; + } else { + // TODO: This should probably show an error message? + if (param.GetPspParam()->mode != SCE_UTILITY_SAVEDATA_TYPE_SAVE) { + display = DS_SAVE_LIST_CHOICE; + } else { + StartFade(false); + } + } + break; + case DS_DELETE_DELETING: + if (param.Delete(param.GetPspParam(),currentSelectedSave)) { + param.SetPspParam(param.GetPspParam()); // Optim : Just Update modified save + display = DS_DELETE_DONE; + } else { + display = DS_DELETE_LIST_CHOICE; // This will probably need error message ? + } + break; + case DS_NONE: + ExecuteNotVisibleIOAction(); + break; + + default: + // Nothing to do here. + break; + } +} + +void PSPSaveDialog::ExecuteNotVisibleIOAction() { + switch ((SceUtilitySavedataType)(u32)param.GetPspParam()->mode) { + case SCE_UTILITY_SAVEDATA_TYPE_LOAD: // Only load and exit + case SCE_UTILITY_SAVEDATA_TYPE_AUTOLOAD: + if (param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave)) { + param.GetPspParam()->common.result = 0; + } else { + param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_LOAD_NO_DATA; + } + break; + case SCE_UTILITY_SAVEDATA_TYPE_SAVE: // Only save and exit + case SCE_UTILITY_SAVEDATA_TYPE_AUTOSAVE: + if (param.Save(param.GetPspParam(), GetSelectedSaveDirName())) { + param.GetPspParam()->common.result = 0; + } else { + param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_SAVE_MS_NOSPACE; + } + break; + case SCE_UTILITY_SAVEDATA_TYPE_SIZES: + param.GetPspParam()->common.result = param.GetSizes(param.GetPspParam()); + break; + case SCE_UTILITY_SAVEDATA_TYPE_LIST: + param.GetList(param.GetPspParam()); + param.GetPspParam()->common.result = 0; + break; + case SCE_UTILITY_SAVEDATA_TYPE_FILES: + param.GetPspParam()->common.result = param.GetFilesList(param.GetPspParam()); + break; + case SCE_UTILITY_SAVEDATA_TYPE_GETSIZE: + { + bool result = param.GetSize(param.GetPspParam()); + // TODO: According to JPCSP, should test/verify this part but seems edge casey. + if (MemoryStick_State() != PSP_MEMORYSTICK_STATE_DRIVER_READY) { + param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_MEMSTICK; + } else if (result) { + param.GetPspParam()->common.result = 0; + } else { + param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; + } + } + break; + case SCE_UTILITY_SAVEDATA_TYPE_DELETEDATA: + DEBUG_LOG(SCEUTILITY, "sceUtilitySavedata DELETEDATA: %s", param.GetPspParam()->saveName); + param.GetPspParam()->common.result = param.DeleteData(param.GetPspParam()); + break; + //case SCE_UTILITY_SAVEDATA_TYPE_AUTODELETE: + case SCE_UTILITY_SAVEDATA_TYPE_SINGLEDELETE: + if (param.Delete(param.GetPspParam(), param.GetSelectedSave())) { + param.GetPspParam()->common.result = 0; + } else { + param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_DELETE_NO_DATA; + } + break; + // TODO: Should reset the directory's other files. + case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATA: + case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATASECURE: + if (param.Save(param.GetPspParam(), GetSelectedSaveDirName(), param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_MAKEDATASECURE)) { + param.GetPspParam()->common.result = 0; + } else { + param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; + } + break; + case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATA: + case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATASECURE: + if (param.Save(param.GetPspParam(), GetSelectedSaveDirName(), param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_WRITEDATASECURE)) { + param.GetPspParam()->common.result = 0; + } else { + param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; + } + break; + case SCE_UTILITY_SAVEDATA_TYPE_READDATA: + case SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE: + if (param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave, param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE)) { + param.GetPspParam()->common.result = 0; + } else if (param.secureCanSkip(param.GetPspParam(),param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE)) { + // TODO: This makes loading/saving work in some games but also confuses them. Must be wrong in some way. + INFO_LOG(SCEUTILITY,"Has not been saved yet, just skip."); + param.GetPspParam()->common.result = 0; + } else { + param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; // not sure if correct code + } + break; + default: + break; + } +} + +int PSPSaveDialog::Shutdown(bool force) { if (GetStatus() != SCE_UTILITY_STATUS_FINISHED && !force) return SCE_ERROR_UTILITY_INVALID_STATUS; diff --git a/Core/Dialog/PSPSaveDialog.h b/Core/Dialog/PSPSaveDialog.h index d1a51dcc7e..e4c1e79e72 100644 --- a/Core/Dialog/PSPSaveDialog.h +++ b/Core/Dialog/PSPSaveDialog.h @@ -89,6 +89,9 @@ private: void DisplayMessage(std::string text, bool hasYesNo = false); const std::string GetSelectedSaveDirName() const; + void ExecuteIOAction(); + void ExecuteNotVisibleIOAction(); + enum DisplayState { DS_NONE, From 553c870ee90784c33864c8a02bbc00eb992d1674 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 29 Jun 2014 17:29:02 -0700 Subject: [PATCH 2/4] Execute savedata io on a separate thread. Some savedata is sorta large, like 1MB, this makes it save more smoothly. --- Core/Dialog/PSPSaveDialog.cpp | 90 ++++++++++++++++++++++++++++++----- Core/Dialog/PSPSaveDialog.h | 16 ++++++- 2 files changed, 92 insertions(+), 14 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index b9550131d3..71849d3164 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -16,6 +16,8 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "i18n/i18n.h" +#include "native/thread/thread.h" +#include "native/thread/threadutil.h" #include "Common/ChunkFile.h" @@ -46,6 +48,7 @@ PSPSaveDialog::PSPSaveDialog() : PSPDialog() , display(DS_NONE) , currentSelectedSave(0) + , ioThread(0) { param.SetPspParam(0); } @@ -60,7 +63,10 @@ int PSPSaveDialog::Init(int paramAddr) ERROR_LOG_REPORT(SCEUTILITY, "A save request is already running, not starting a new one"); return SCE_ERROR_UTILITY_INVALID_STATUS; } - + + JoinIOThread(); + ioThreadStatus = SAVEIO_NONE; + requestAddr = paramAddr; int size = Memory::Read_U32(requestAddr); memset(&request, 0, sizeof(request)); @@ -618,6 +624,7 @@ int PSPSaveDialog::Update(int animSpeed) display = DS_SAVE_CONFIRM_OVERWRITE; } else { display = DS_SAVE_SAVING; + StartIOThread(); } } EndDraw(); @@ -638,6 +645,7 @@ int PSPSaveDialog::Update(int animSpeed) StartFade(false); } else if (IsButtonPressed(okButtonFlag)) { display = DS_SAVE_SAVING; + StartIOThread(); } EndDraw(); @@ -662,12 +670,15 @@ int PSPSaveDialog::Update(int animSpeed) } } else if (IsButtonPressed(okButtonFlag)) { display = DS_SAVE_SAVING; + StartIOThread(); } EndDraw(); break; case DS_SAVE_SAVING: - ExecuteIOAction(); + if (ioThreadStatus != SAVEIO_PENDING) { + JoinIOThread(); + } StartDraw(); @@ -681,6 +692,7 @@ int PSPSaveDialog::Update(int animSpeed) EndDraw(); break; case DS_SAVE_DONE: + JoinIOThread(); StartDraw(); DisplaySaveIcon(); @@ -715,6 +727,7 @@ int PSPSaveDialog::Update(int animSpeed) StartFade(false); } else if (IsButtonPressed(okButtonFlag)) { display = DS_LOAD_LOADING; + StartIOThread(); } EndDraw(); @@ -735,12 +748,15 @@ int PSPSaveDialog::Update(int animSpeed) StartFade(false); } else if (IsButtonPressed(okButtonFlag)) { display = DS_LOAD_LOADING; + StartIOThread(); } EndDraw(); break; case DS_LOAD_LOADING: - ExecuteIOAction(); + if (ioThreadStatus != SAVEIO_PENDING) { + JoinIOThread(); + } StartDraw(); @@ -754,6 +770,7 @@ int PSPSaveDialog::Update(int animSpeed) EndDraw(); break; case DS_LOAD_DONE: + JoinIOThread(); StartDraw(); DisplaySaveIcon(); @@ -831,13 +848,16 @@ int PSPSaveDialog::Update(int animSpeed) display = DS_DELETE_LIST_CHOICE; else { display = DS_DELETE_DELETING; + StartIOThread(); } } EndDraw(); break; case DS_DELETE_DELETING: - ExecuteIOAction(); + if (ioThreadStatus != SAVEIO_PENDING) { + JoinIOThread(); + } StartDraw(); @@ -848,6 +868,7 @@ int PSPSaveDialog::Update(int animSpeed) EndDraw(); break; case DS_DELETE_DONE: + JoinIOThread(); StartDraw(); DisplayMessage(d->T("Delete completed")); @@ -881,8 +902,17 @@ int PSPSaveDialog::Update(int animSpeed) break; case DS_NONE: // For action which display nothing - ExecuteNotVisibleIOAction(); - ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); + switch (ioThreadStatus) { + case SAVEIO_NONE: + StartIOThread(); + break; + case SAVEIO_PENDING: + case SAVEIO_DONE: + // To make sure there aren't any timing variations, we sync the next frame. + JoinIOThread(); + ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); + break; + } break; default: @@ -936,6 +966,8 @@ void PSPSaveDialog::ExecuteIOAction() { // Nothing to do here. break; } + + ioThreadStatus = SAVEIO_DONE; } void PSPSaveDialog::ExecuteNotVisibleIOAction() { @@ -1025,10 +1057,36 @@ void PSPSaveDialog::ExecuteNotVisibleIOAction() { } } +void PSPSaveDialog::JoinIOThread() { + if (ioThread) { + ioThread->join(); + delete ioThread; + ioThread = 0; + } +} + +static void DoExecuteIOAction(PSPSaveDialog *dialog) { + setCurrentThreadName("SaveIO"); + dialog->ExecuteIOAction(); +} + +void PSPSaveDialog::StartIOThread() { + if (ioThread) { + WARN_LOG_REPORT(SCEUTILITY, "Starting a save io thread when one already pending, uh oh."); + JoinIOThread(); + } + + ioThreadStatus = SAVEIO_PENDING; + ioThread = new std::thread(&DoExecuteIOAction, this); +} + int PSPSaveDialog::Shutdown(bool force) { if (GetStatus() != SCE_UTILITY_STATUS_FINISHED && !force) return SCE_ERROR_UTILITY_INVALID_STATUS; + JoinIOThread(); + ioThreadStatus = SAVEIO_NONE; + PSPDialog::Shutdown(force); if (!force) { ChangeStatusShutdown(SAVEDATA_SHUTDOWN_DELAY_US); @@ -1038,13 +1096,14 @@ int PSPSaveDialog::Shutdown(bool force) { return 0; } -void PSPSaveDialog::DoState(PointerWrap &p) -{ +void PSPSaveDialog::DoState(PointerWrap &p) { + JoinIOThread(); PSPDialog::DoState(p); - auto s = p.Section("PSPSaveDialog", 1); - if (!s) + auto s = p.Section("PSPSaveDialog", 1, 2); + if (!s) { return; + } p.Do(display); param.DoState(p); @@ -1052,14 +1111,19 @@ void PSPSaveDialog::DoState(PointerWrap &p) // Just reset it. bool hasParam = param.GetPspParam() != NULL; p.Do(hasParam); - if (hasParam) + if (hasParam) { param.SetPspParam(&request); + } p.Do(requestAddr); p.Do(currentSelectedSave); p.Do(yesnoChoice); + if (s > 2) { + p.Do(ioThreadStatus); + } else { + ioThreadStatus = SAVEIO_NONE; + } } -pspUtilityDialogCommon *PSPSaveDialog::GetCommonParam() -{ +pspUtilityDialogCommon *PSPSaveDialog::GetCommonParam() { return ¶m.GetPspParam()->common; } diff --git a/Core/Dialog/PSPSaveDialog.h b/Core/Dialog/PSPSaveDialog.h index e4c1e79e72..242849c5f7 100644 --- a/Core/Dialog/PSPSaveDialog.h +++ b/Core/Dialog/PSPSaveDialog.h @@ -17,6 +17,7 @@ #pragma once +#include "native/thread/thread.h" #include "Core/Dialog/PSPDialog.h" #include "Core/Dialog/SavedataParam.h" @@ -73,6 +74,8 @@ public: virtual void DoState(PointerWrap &p); virtual pspUtilityDialogCommon *GetCommonParam(); + void ExecuteIOAction(); + protected: virtual bool UseAutoStatus() { return false; @@ -89,7 +92,8 @@ private: void DisplayMessage(std::string text, bool hasYesNo = false); const std::string GetSelectedSaveDirName() const; - void ExecuteIOAction(); + void JoinIOThread(); + void StartIOThread(); void ExecuteNotVisibleIOAction(); enum DisplayState @@ -133,5 +137,15 @@ private: int currentSelectedSave; int yesnoChoice; + + enum SaveIOStatus + { + SAVEIO_NONE, + SAVEIO_PENDING, + SAVEIO_DONE, + }; + + std::thread *ioThread; + volatile SaveIOStatus ioThreadStatus; }; From e3c68763650f22247d3859dc510fcf53e56f6f73 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 29 Jun 2014 17:42:20 -0700 Subject: [PATCH 3/4] Show a message when saving/loading fails. --- Core/Dialog/PSPSaveDialog.cpp | 76 ++++++++++++++++++++++++++++++----- Core/Dialog/PSPSaveDialog.h | 6 ++- 2 files changed, 71 insertions(+), 11 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 71849d3164..9f17d16836 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -691,6 +691,30 @@ int PSPSaveDialog::Update(int animSpeed) EndDraw(); break; + case DS_SAVE_FAILED: + JoinIOThread(); + StartDraw(); + + DisplaySaveIcon(); + DisplaySaveDataInfo2(); + + DisplayMessage(d->T("SavingFailed", "Unable to save data.")); + + DisplayButtons(DS_BUTTON_CANCEL); + DisplayBanner(DB_SAVE); + + if (IsButtonPressed(cancelButtonFlag)) { + // Go back to the list so they can try again. + if (param.GetPspParam()->mode != SCE_UTILITY_SAVEDATA_TYPE_SAVE) { + display = DS_SAVE_LIST_CHOICE; + } else { + param.GetPspParam()->common.result = SCE_UTILITY_DIALOG_RESULT_CANCEL; + StartFade(false); + } + } + + EndDraw(); + break; case DS_SAVE_DONE: JoinIOThread(); StartDraw(); @@ -769,6 +793,30 @@ int PSPSaveDialog::Update(int animSpeed) EndDraw(); break; + case DS_LOAD_FAILED: + JoinIOThread(); + StartDraw(); + + DisplaySaveIcon(); + DisplaySaveDataInfo2(); + + DisplayMessage(d->T("LoadingFailed", "Unable to load data.")); + + DisplayButtons(DS_BUTTON_CANCEL); + DisplayBanner(DB_LOAD); + + if (IsButtonPressed(cancelButtonFlag)) { + // Go back to the list so they can try again. + if (param.GetPspParam()->mode != SCE_UTILITY_SAVEDATA_TYPE_LOAD) { + display = DS_LOAD_LIST_CHOICE; + } else { + param.GetPspParam()->common.result = SCE_UTILITY_DIALOG_RESULT_CANCEL; + StartFade(false); + } + } + + EndDraw(); + break; case DS_LOAD_DONE: JoinIOThread(); StartDraw(); @@ -867,6 +915,21 @@ int PSPSaveDialog::Update(int animSpeed) EndDraw(); break; + case DS_DELETE_FAILED: + JoinIOThread(); + StartDraw(); + + DisplayMessage(d->T("DeleteFailed", "Unable to delete data.")); + + DisplayButtons(DS_BUTTON_CANCEL); + DisplayBanner(DB_DELETE); + + if (IsButtonPressed(cancelButtonFlag)) { + display = DS_DELETE_LIST_CHOICE; + } + + EndDraw(); + break; case DS_DELETE_DONE: JoinIOThread(); StartDraw(); @@ -932,9 +995,7 @@ void PSPSaveDialog::ExecuteIOAction() { if (param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave)) { display = DS_LOAD_DONE; } else { - // TODO: This should probably show an error message? - param.GetPspParam()->common.result = SCE_UTILITY_DIALOG_RESULT_CANCEL; - StartFade(false); + display = DS_LOAD_FAILED; } break; case DS_SAVE_SAVING: @@ -942,12 +1003,7 @@ void PSPSaveDialog::ExecuteIOAction() { param.SetPspParam(param.GetPspParam()); // Optim : Just Update modified save display = DS_SAVE_DONE; } else { - // TODO: This should probably show an error message? - if (param.GetPspParam()->mode != SCE_UTILITY_SAVEDATA_TYPE_SAVE) { - display = DS_SAVE_LIST_CHOICE; - } else { - StartFade(false); - } + display = DS_SAVE_FAILED; } break; case DS_DELETE_DELETING: @@ -955,7 +1011,7 @@ void PSPSaveDialog::ExecuteIOAction() { param.SetPspParam(param.GetPspParam()); // Optim : Just Update modified save display = DS_DELETE_DONE; } else { - display = DS_DELETE_LIST_CHOICE; // This will probably need error message ? + display = DS_DELETE_FAILED; } break; case DS_NONE: diff --git a/Core/Dialog/PSPSaveDialog.h b/Core/Dialog/PSPSaveDialog.h index 242849c5f7..c26a40c437 100644 --- a/Core/Dialog/PSPSaveDialog.h +++ b/Core/Dialog/PSPSaveDialog.h @@ -116,7 +116,11 @@ private: DS_DELETE_CONFIRM, DS_DELETE_DELETING, DS_DELETE_DONE, - DS_DELETE_NODATA + DS_DELETE_NODATA, + + DS_SAVE_FAILED, + DS_LOAD_FAILED, + DS_DELETE_FAILED, }; enum DialogBanner From 01d3dcdc99ecbbedb2069994cae5e7c58060021b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 29 Jun 2014 17:44:56 -0700 Subject: [PATCH 4/4] Prevent a possible race condition in save/load. --- Core/Dialog/PSPSaveDialog.cpp | 2 ++ Core/Dialog/PSPSaveDialog.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 9f17d16836..7a228b07ac 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -584,6 +584,7 @@ int PSPSaveDialog::Update(int animSpeed) memset(&request, 0, sizeof(request)); Memory::Memcpy(&request, requestAddr, size); Memory::Memcpy(&originalRequest, requestAddr, size); + lock_guard guard(paramLock); param.SetPspParam(&request); } @@ -990,6 +991,7 @@ int PSPSaveDialog::Update(int animSpeed) } void PSPSaveDialog::ExecuteIOAction() { + lock_guard guard(paramLock); switch (display) { case DS_LOAD_LOADING: if (param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave)) { diff --git a/Core/Dialog/PSPSaveDialog.h b/Core/Dialog/PSPSaveDialog.h index c26a40c437..dc39b7b917 100644 --- a/Core/Dialog/PSPSaveDialog.h +++ b/Core/Dialog/PSPSaveDialog.h @@ -18,6 +18,7 @@ #pragma once #include "native/thread/thread.h" +#include "native/base/mutex.h" #include "Core/Dialog/PSPDialog.h" #include "Core/Dialog/SavedataParam.h" @@ -150,6 +151,7 @@ private: }; std::thread *ioThread; + recursive_mutex paramLock; volatile SaveIOStatus ioThreadStatus; };