Merge pull request #5718 from ErenYeager1836/fix/savedata-dialog-native-state-checks

fix(libSceSaveDataDialog.native): validate dialog state in close, get result and terminate
This commit is contained in:
Adrià authored and GitHub committed 2026-10-15 23:00:55 +02:00
commit 90dea83b59
4 files changed
+31 -1

No files matched your search

@@ -33,6 +33,9 @@ int APS5_VABI sceSaveDataDialogUpdateStatus(void) {
}
int APS5_VABI sceSaveDataDialogGetResult(void* result) {
if (g_status != SAVE_DATA_DIALOG_STATUS_FINISHED) {
return SAVE_DATA_DIALOG_ERROR_NOT_FINISHED;
}
if (result == nullptr) {
return SAVE_DATA_DIALOG_ERROR_ARG_NULL;
}
@@ -76,6 +79,9 @@ int APS5_VABI sceSaveDataDialogOpen(const void* param) {
int APS5_VABI sceSaveDataDialogClose(const void* closeParam) {
(void)closeParam;
if (g_status != SAVE_DATA_DIALOG_STATUS_RUNNING) {
return SAVE_DATA_DIALOG_ERROR_NOT_RUNNING;
}
g_status = SAVE_DATA_DIALOG_STATUS_FINISHED;
return SAVE_DATA_DIALOG_OK;
}
@@ -85,6 +91,9 @@ int APS5_VABI sceSaveDataDialogIsReadyToDisplay(void) {
}
int APS5_VABI sceSaveDataDialogTerminate(void) {
if (g_status == SAVE_DATA_DIALOG_STATUS_NONE) {
return SAVE_DATA_DIALOG_ERROR_NOT_INITIALIZED;
}
g_status = SAVE_DATA_DIALOG_STATUS_NONE;
g_mode = 0;
g_user_data = nullptr;
@@ -7,7 +7,9 @@
constexpr int SAVE_DATA_DIALOG_OK = 0;
constexpr int SAVE_DATA_DIALOG_ERROR_NOT_INITIALIZED = static_cast<int>(0x80B80003);
constexpr int SAVE_DATA_DIALOG_ERROR_ALREADY_INITIALIZED = static_cast<int>(0x80B80004);
constexpr int SAVE_DATA_DIALOG_ERROR_NOT_FINISHED = static_cast<int>(0x80B80005);
constexpr int SAVE_DATA_DIALOG_ERROR_INVALID_STATE = static_cast<int>(0x80B80006);
constexpr int SAVE_DATA_DIALOG_ERROR_NOT_RUNNING = static_cast<int>(0x80B8000B);
constexpr int SAVE_DATA_DIALOG_ERROR_ARG_NULL = static_cast<int>(0x80B8000D);
constexpr int SAVE_DATA_DIALOG_STATUS_NONE = 0;
+19
View File
@@ -34,7 +34,16 @@ static void RequireRunning() {
}
int main() {
Require(sceSaveDataDialogGetStatus() == SAVE_DATA_DIALOG_STATUS_NONE, "initial status");
Require(sceSaveDataDialogTerminate() == SAVE_DATA_DIALOG_ERROR_NOT_INITIALIZED, "terminate before init");
Require(sceSaveDataDialogClose(nullptr) == SAVE_DATA_DIALOG_ERROR_NOT_RUNNING, "close before init");
SaveDataDialogResult uninitResult{};
Require(sceSaveDataDialogGetResult(&uninitResult) == SAVE_DATA_DIALOG_ERROR_NOT_FINISHED, "get result before init");
Require(sceSaveDataDialogInitialize() == 0, "initialize");
Require(sceSaveDataDialogInitialize() == SAVE_DATA_DIALOG_ERROR_ALREADY_INITIALIZED, "double init");
Require(sceSaveDataDialogClose(nullptr) == SAVE_DATA_DIALOG_ERROR_NOT_RUNNING, "close while initialized not running");
Require(sceSaveDataDialogGetResult(&uninitResult) == SAVE_DATA_DIALOG_ERROR_NOT_FINISHED, "get result before open");
SaveDataDirName names[2]{{}, {"SDU1"}};
SaveDataDialogItems items{};
@@ -57,6 +66,8 @@ int main() {
RequireRunning();
Require(sceSaveDataDialogProgressBarSetValue(0, 100) == 0, "complete progress");
RequireRunning();
Require(sceSaveDataDialogGetResult(&uninitResult) == SAVE_DATA_DIALOG_ERROR_NOT_FINISHED,
"get result while running");
Require(sceSaveDataDialogClose(nullptr) == 0, "close save progress");
Require(sceSaveDataDialogUpdateStatus() == SAVE_DATA_DIALOG_STATUS_FINISHED,
"closing save progress must finish it");
@@ -69,10 +80,18 @@ int main() {
"save result must preserve its mode, directory and caller context");
}
Require(sceSaveDataDialogOpen(&param) == 0, "open save progress for terminate test");
RequireRunning();
Require(sceSaveDataDialogTerminate() == 0, "terminate while running");
Require(sceSaveDataDialogGetStatus() == SAVE_DATA_DIALOG_STATUS_NONE, "terminated state");
Require(sceSaveDataDialogTerminate() == SAVE_DATA_DIALOG_ERROR_NOT_INITIALIZED, "terminate after terminate");
Require(sceSaveDataDialogInitialize() == 0, "re-initialize");
param.mode = 1;
Require(sceSaveDataDialogOpen(&param) == 0, "open selection dialog");
Require(sceSaveDataDialogUpdateStatus() == SAVE_DATA_DIALOG_STATUS_FINISHED,
"selection dialog must retain the existing automatic response");
Require(sceSaveDataDialogTerminate() == 0, "terminate");
Require(sceSaveDataDialogTerminate() == SAVE_DATA_DIALOG_ERROR_NOT_INITIALIZED, "terminate when already terminated");
Require(sceSaveDataDialogGetStatus() == SAVE_DATA_DIALOG_STATUS_NONE, "terminated state");
}
+1 -1
View File
@@ -2,4 +2,4 @@
### Silent stubs
- [libSceSaveDataDialog.native](../../../core/libs/prx/libSceSaveDataDialog.native/Export.cpp) shows no UI and ignores progress values. Progress-bar mode (5) stays running until the caller closes it, matching Skyrim PPSA03747's save sequence; other modes still finish immediately and return button 1 and the first nonempty directory name. Console dialog timing and selection behavior remain unverified.
- [libSceSaveDataDialog.native](../../../core/libs/prx/libSceSaveDataDialog.native/Export.cpp) shows no UI and ignores progress values. Progress-bar mode (5) stays running until the caller closes it, matching Skyrim PPSA03747's save sequence; other modes still finish immediately and return button 1 and the first nonempty directory name. Console dialog timing and selection behavior remain unverified. Lifecycle state error codes follow shadPS4: `sceSaveDataDialogClose` returns `SAVE_DATA_DIALOG_ERROR_NOT_RUNNING` whenever not running, `sceSaveDataDialogGetResult` returns `SAVE_DATA_DIALOG_ERROR_NOT_FINISHED` whenever not finished (checked before null pointer), and `sceSaveDataDialogTerminate` closes running dialogs and returns OK, rejecting uninitialized calls with `SAVE_DATA_DIALOG_ERROR_NOT_INITIALIZED`.