diff --git a/src/core/libraries/save_data/dialog/savedatadialog.cpp b/src/core/libraries/save_data/dialog/savedatadialog.cpp index a647d80f9..0ad7d7dc0 100644 --- a/src/core/libraries/save_data/dialog/savedatadialog.cpp +++ b/src/core/libraries/save_data/dialog/savedatadialog.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/elf_info.h" #include "common/logging/log.h" #include "core/libraries/libs.h" #include "core/libraries/system/commondialog.h" diff --git a/src/core/libraries/save_data/dialog/savedatadialog_ui.cpp b/src/core/libraries/save_data/dialog/savedatadialog_ui.cpp index 9cfdba52c..156d2f8b7 100644 --- a/src/core/libraries/save_data/dialog/savedatadialog_ui.cpp +++ b/src/core/libraries/save_data/dialog/savedatadialog_ui.cpp @@ -15,6 +15,7 @@ using namespace ImGui; using namespace Libraries::CommonDialog; +using Common::ElfInfo; constexpr u32 OrbisSaveDataBlockSize = 32768; // 32 KiB @@ -48,7 +49,7 @@ void SaveDialogResult::CopyTo(OrbisSaveDataDialogResult& result) const { result.mode = this->mode; result.result = this->result; result.buttonId = this->button_id; - if (has_item) { + if (mode == SaveDataDialogMode::LIST || ElfInfo::Instance().FirmwareVer() >= ElfInfo::FW_45) { if (result.dirName != nullptr) { result.dirName->data.FromString(this->dir_name); } @@ -202,6 +203,7 @@ SaveDialogState::SystemState::SystemState(const SaveDialogState& state, auto& sys = *param.sysMsgParam; switch (sys.msgType) { case SystemMessageType::NODATA: { + return_cancel = true; this->msg = "There is no saved data"; } break; case SystemMessageType::CONFIRM: @@ -214,6 +216,7 @@ SaveDialogState::SystemState::SystemState(const SaveDialogState& state, M("Do you want to overwrite the existing saved data?", "##UNKNOWN##", "##UNKNOWN##"); break; case SystemMessageType::NOSPACE: + return_cancel = true; M(fmt::format( "There is not enough space to save the data. To continue {} free space is required.", SpaceSizeToString(sys.value * OrbisSaveDataBlockSize)), @@ -225,12 +228,15 @@ SaveDialogState::SystemState::SystemState(const SaveDialogState& state, M("Saving...", "Loading...", "Deleting..."); break; case SystemMessageType::FILE_CORRUPTED: + return_cancel = true; this->msg = "The saved data is corrupted."; break; case SystemMessageType::FINISHED: + return_cancel = true; M("Saved successfully.", "Loading complete.", "Deletion complete."); break; case SystemMessageType::NOSPACE_CONTINUABLE: + return_cancel = true; M(fmt::format("There is not enough space to save the data. {} free space is required.", SpaceSizeToString(sys.value * OrbisSaveDataBlockSize)), "##UNKNOWN##", "##UNKNOWN##"); @@ -282,29 +288,36 @@ SaveDialogState::ErrorCodeState::ErrorCodeState(const OrbisSaveDataDialogParam& } SaveDialogState::ProgressBarState::ProgressBarState(const SaveDialogState& state, const OrbisSaveDataDialogParam& param) { + static auto fw_ver = ElfInfo::Instance().FirmwareVer(); + this->progress = 0; auto& bar = *param.progressBarParam; - switch (bar.sysMsgType) { - case ProgressSystemMessageType::INVALID: - this->msg = bar.msg != nullptr ? std::string{bar.msg} : std::string{}; - break; - case ProgressSystemMessageType::PROGRESS: - switch (state.type) { - case DialogType::SAVE: - this->msg = "Saving..."; + + if (bar.msg != nullptr) { + this->msg = std::string{bar.msg}; + } else { + switch (bar.sysMsgType) { + case ProgressSystemMessageType::INVALID: + this->msg = "INVALID"; break; - case DialogType::LOAD: - this->msg = "Loading..."; + case ProgressSystemMessageType::PROGRESS: + switch (state.type) { + case DialogType::SAVE: + this->msg = "Saving..."; + break; + case DialogType::LOAD: + this->msg = "Loading..."; + break; + case DialogType::DELETE: + this->msg = "Deleting..."; + break; + } break; - case DialogType::DELETE: - this->msg = "Deleting..."; + case ProgressSystemMessageType::RESTORE: + this->msg = "Restoring saved data..."; break; } - break; - case ProgressSystemMessageType::RESTORE: - this->msg = "Restoring saved data..."; - break; } } @@ -352,11 +365,8 @@ void SaveDialogUi::Finish(ButtonId buttonId, Result r) { result->result = r; result->button_id = buttonId; result->user_data = this->state->user_data; - if (state) { - if (state->mode != SaveDataDialogMode::LIST && !state->save_list.empty()) { - result->dir_name = state->save_list.front().dir_name; - } - result->has_item = state->mode == SaveDataDialogMode::LIST || !state->save_list.empty(); + if (state && state->mode != SaveDataDialogMode::LIST && !state->save_list.empty()) { + result->dir_name = state->save_list.front().dir_name; } } if (status) { @@ -642,6 +652,8 @@ void SaveDialogUi::DrawUser() { if (!state->save_list.empty()) { DrawItem(0, state->save_list.front(), false); + } else if (state->new_item) { + DrawItem(0, *state->new_item, false); } auto has_btn = btn_type != ButtonType::NONE; @@ -666,7 +678,7 @@ void SaveDialogUi::DrawUser() { if (has_btn) { int count = 1; - if (btn_type == ButtonType::YESNO || btn_type == ButtonType::ONCANCEL) { + if (btn_type == ButtonType::YESNO || btn_type == ButtonType::OKCANCEL) { ++count; } @@ -682,19 +694,28 @@ void SaveDialogUi::DrawUser() { } SameLine(); if (Button("No", BUTTON_SIZE)) { - Finish(ButtonId::NO); + if (ElfInfo::Instance().FirmwareVer() < ElfInfo::FW_45) { + Finish(ButtonId::INVALID, Result::USER_CANCELED); + } else { + Finish(ButtonId::NO); + } } if (first_render || IsKeyPressed(ImGuiKey_GamepadFaceRight)) { SetItemCurrentNavFocus(); } } else { if (Button("OK", BUTTON_SIZE)) { - Finish(ButtonId::OK); + if (btn_type == ButtonType::OK && + ElfInfo::Instance().FirmwareVer() < ElfInfo::FW_45) { + Finish(ButtonId::INVALID, Result::USER_CANCELED); + } else { + Finish(ButtonId::OK); + } } if (first_render) { SetItemCurrentNavFocus(); } - if (btn_type == ButtonType::ONCANCEL) { + if (btn_type == ButtonType::OKCANCEL) { SameLine(); if (Button("Cancel", BUTTON_SIZE)) { Finish(ButtonId::INVALID, Result::USER_CANCELED); @@ -713,6 +734,8 @@ void SaveDialogUi::DrawSystemMessage() { if (!state->save_list.empty()) { DrawItem(0, state->save_list.front(), false); + } else if (state->new_item) { + DrawItem(0, *state->new_item, false); } const auto ws = GetWindowSize(); @@ -736,12 +759,20 @@ void SaveDialogUi::DrawSystemMessage() { }); BeginGroup(); if (Button(sys_state.show_no ? "Yes" : "OK", BUTTON_SIZE)) { - Finish(ButtonId::YES); + if (sys_state.return_cancel && ElfInfo::Instance().FirmwareVer() < ElfInfo::FW_45) { + Finish(ButtonId::INVALID, Result::USER_CANCELED); + } else { + Finish(ButtonId::YES); + } } SameLine(); if (sys_state.show_no) { if (Button("No", BUTTON_SIZE)) { - Finish(ButtonId::NO); + if (ElfInfo::Instance().FirmwareVer() < ElfInfo::FW_45) { + Finish(ButtonId::INVALID, Result::USER_CANCELED); + } else { + Finish(ButtonId::NO); + } } } else if (sys_state.show_cancel) { if (Button("Cancel", BUTTON_SIZE)) { @@ -759,6 +790,8 @@ void SaveDialogUi::DrawErrorCode() { if (!state->save_list.empty()) { DrawItem(0, state->save_list.front(), false); + } else if (state->new_item) { + DrawItem(0, *state->new_item, false); } const auto ws = GetWindowSize(); @@ -774,7 +807,11 @@ void SaveDialogUi::DrawErrorCode() { ws.y - FOOTER_HEIGHT + 5.0f, }); if (Button("OK", BUTTON_SIZE)) { - Finish(ButtonId::OK); + if (ElfInfo::Instance().FirmwareVer() < ElfInfo::FW_45) { + Finish(ButtonId::INVALID, Result::USER_CANCELED); + } else { + Finish(ButtonId::OK); + } } if (first_render) { SetItemCurrentNavFocus(); @@ -788,6 +825,8 @@ void SaveDialogUi::DrawProgressBar() { if (!state->save_list.empty()) { DrawItem(0, state->save_list.front(), false); + } else if (state->new_item) { + DrawItem(0, *state->new_item, false); } const auto& msg = bar_state.msg; diff --git a/src/core/libraries/save_data/dialog/savedatadialog_ui.h b/src/core/libraries/save_data/dialog/savedatadialog_ui.h index f8a2dccd8..3f414470f 100644 --- a/src/core/libraries/save_data/dialog/savedatadialog_ui.h +++ b/src/core/libraries/save_data/dialog/savedatadialog_ui.h @@ -48,7 +48,7 @@ enum class ButtonType : u32 { OK = 0, YESNO = 1, NONE = 2, - ONCANCEL = 3, + OKCANCEL = 3, }; enum class UserMessageType : u32 { @@ -201,7 +201,6 @@ struct SaveDialogResult { std::string dir_name{}; PSF param{}; void* user_data{}; - bool has_item{false}; void CopyTo(OrbisSaveDataDialogResult& result) const; }; @@ -223,6 +222,8 @@ public: bool show_no{}; // Yes instead of OK bool show_cancel{}; + bool return_cancel{}; + SystemState(const SaveDialogState& state, const OrbisSaveDataDialogParam& param); }; struct ErrorCodeState { diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index ca94d96fb..07d501a69 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -28,11 +28,13 @@ namespace fs = std::filesystem; namespace chrono = std::chrono; using Common::CString; +using Common::ElfInfo; namespace Libraries::SaveData { enum class Error : u32 { OK = 0, + USER_SERVICE_NOT_INITIALIZED = 0x80960002, PARAMETER = 0x809F0000, NOT_INITIALIZED = 0x809F0001, OUT_OF_MEMORY = 0x809F0002, @@ -191,7 +193,9 @@ struct OrbisSaveDataMemorySetup2 { OrbisUserServiceUserId userId; size_t memorySize; size_t iconMemorySize; + // +4.5 const OrbisSaveDataParam* initParam; + // +4.5 const OrbisSaveDataIcon* initIcon; std::array _reserved; }; @@ -241,6 +245,7 @@ struct OrbisSaveDataMountResult { OrbisSaveDataMountPoint mount_point; OrbisSaveDataBlocks required_blocks; u32 _unused; + // +4.5 OrbisSaveDataMountStatus mount_status; std::array _reserved; s32 : 32; @@ -278,8 +283,11 @@ struct OrbisSaveDataDirNameSearchResult { int : 32; OrbisSaveDataDirName* dirNames; u32 dirNamesNum; + // +1.7 u32 setNum; + // +1.7 OrbisSaveDataParam* params; + // +2.5 OrbisSaveDataSearchInfo* infos; std::array _reserved; int : 32; @@ -303,11 +311,13 @@ struct OrbisSaveDataEvent { static bool g_initialized = false; static std::string g_game_serial; +static u32 g_fw_ver; static std::array, 16> g_mount_slots; static void initialize() { g_initialized = true; - g_game_serial = Common::ElfInfo::Instance().GameSerial(); + g_game_serial = ElfInfo::Instance().GameSerial(); + g_fw_ver = ElfInfo::Instance().FirmwareVer(); } // game_00other | game*other @@ -336,6 +346,16 @@ static bool match(std::string_view str, std::string_view pattern) { return str_it == str.end() && pat_it == pattern.end(); } +static Error setNotInitializedError() { + if (g_fw_ver < ElfInfo::FW_20) { + return Error::INTERNAL; + } + if (g_fw_ver < ElfInfo::FW_25) { + return Error::USER_SERVICE_NOT_INITIALIZED; + } + return Error::NOT_INITIALIZED; +} + static Error saveDataMount(const OrbisSaveDataMount2* mount_info, OrbisSaveDataMountResult* mount_result) { @@ -351,7 +371,7 @@ static Error saveDataMount(const OrbisSaveDataMount2* mount_info, { const auto save_path = SaveInstance::MakeDirSavePath(mount_info->userId, g_game_serial, mount_info->dirName->data); - if (Backup::IsBackupExecutingFor(save_path)) { + if (Backup::IsBackupExecutingFor(save_path) && g_fw_ver) { return Error::BACKUP_BUSY; } } @@ -360,11 +380,14 @@ static Error saveDataMount(const OrbisSaveDataMount2* mount_info, const bool is_ro = True(mount_mode & OrbisSaveDataMountMode::RDONLY); const bool create = True(mount_mode & OrbisSaveDataMountMode::CREATE); - const bool create_if_not_exist = True(mount_mode & OrbisSaveDataMountMode::CREATE2); + const bool create_if_not_exist = + True(mount_mode & OrbisSaveDataMountMode::CREATE2) && g_fw_ver >= ElfInfo::FW_45; ASSERT(!create || !create_if_not_exist); // Can't have both const bool copy_icon = True(mount_mode & OrbisSaveDataMountMode::COPY_ICON); - const bool ignore_corrupt = True(mount_mode & OrbisSaveDataMountMode::DESTRUCT_OFF); + + const bool ignore_corrupt = + True(mount_mode & OrbisSaveDataMountMode::DESTRUCT_OFF) || g_fw_ver < ElfInfo::FW_16; const std::string_view dir_name{mount_info->dirName->data}; @@ -436,9 +459,11 @@ static Error saveDataMount(const OrbisSaveDataMount2* mount_info, mount_result->mount_point.data.FromString(save_instance.GetMountPoint()); - mount_result->mount_status = create_if_not_exist && to_be_created - ? OrbisSaveDataMountStatus::CREATED - : OrbisSaveDataMountStatus::NOTHING; + if (g_fw_ver >= ElfInfo::FW_45) { + mount_result->mount_status = create_if_not_exist && to_be_created + ? OrbisSaveDataMountStatus::CREATED + : OrbisSaveDataMountStatus::NOTHING; + } g_mount_slots[slot_num].emplace(std::move(save_instance)); @@ -448,7 +473,7 @@ static Error saveDataMount(const OrbisSaveDataMount2* mount_info, static Error Umount(const OrbisSaveDataMountPoint* mountPoint, bool call_backup = false) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (mountPoint == nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -501,7 +526,7 @@ int PS4_SYSV_ABI sceSaveDataAbort() { Error PS4_SYSV_ABI sceSaveDataBackup(const OrbisSaveDataBackup* backup) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (backup == nullptr || backup->dirName == nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -550,7 +575,7 @@ int PS4_SYSV_ABI sceSaveDataChangeInternal() { Error PS4_SYSV_ABI sceSaveDataCheckBackupData(const OrbisSaveDataCheckBackupData* check) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (check == nullptr || check->dirName == nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -635,7 +660,7 @@ int PS4_SYSV_ABI sceSaveDataCheckSaveDataVersionLatest() { Error PS4_SYSV_ABI sceSaveDataClearProgress() { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } LOG_DEBUG(Lib_SaveData, "called"); Backup::ClearProgress(); @@ -690,7 +715,7 @@ int PS4_SYSV_ABI sceSaveDataDebugTarget() { Error PS4_SYSV_ABI sceSaveDataDelete(const OrbisSaveDataDelete* del) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (del == nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -742,7 +767,7 @@ Error PS4_SYSV_ABI sceSaveDataDirNameSearch(const OrbisSaveDataDirNameSearchCond OrbisSaveDataDirNameSearchResult* result) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (cond == nullptr || result == nullptr || cond->key > OrbisSaveDataSortKey::FREE_BLOCKS || cond->order > OrbisSaveDataSortOrder::DESCENT) { @@ -757,7 +782,9 @@ Error PS4_SYSV_ABI sceSaveDataDirNameSearch(const OrbisSaveDataDirNameSearchCond if (!fs::exists(save_path)) { result->hitNum = 0; - result->setNum = 0; + if (g_fw_ver >= ElfInfo::FW_17) { + result->setNum = 0; + } return Error::OK; } @@ -825,21 +852,25 @@ Error PS4_SYSV_ABI sceSaveDataDirNameSearch(const OrbisSaveDataDirNameSearchCond std::ranges::reverse(dir_list); } - result->hitNum = dir_list.size(); size_t max_count = std::min(static_cast(result->dirNamesNum), dir_list.size()); - result->setNum = max_count; + if (g_fw_ver >= ElfInfo::FW_17) { + result->hitNum = dir_list.size(); + result->setNum = max_count; + } else { + result->hitNum = max_count; + } for (size_t i = 0; i < max_count; i++) { auto& name_data = result->dirNames[i].data; name_data.FromString(dir_list[i]); - if (result->params != nullptr) { + if (g_fw_ver >= ElfInfo::FW_17 && result->params != nullptr) { auto& sfo = map_dir_sfo.at(dir_list[i]); auto& param_data = result->params[i]; param_data.FromSFO(sfo); } - if (result->infos != nullptr) { + if (g_fw_ver >= ElfInfo::FW_25 && result->infos != nullptr) { auto& info = result->infos[i]; info.blocks = map_max_blocks.at(dir_list[i]); info.freeBlocks = map_free_size.at(dir_list[i]); @@ -913,7 +944,7 @@ Error PS4_SYSV_ABI sceSaveDataGetEventResult(const OrbisSaveDataEventParam*, OrbisSaveDataEvent* event) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (event == nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -949,7 +980,7 @@ Error PS4_SYSV_ABI sceSaveDataGetMountInfo(const OrbisSaveDataMountPoint* mountP OrbisSaveDataMountInfo* info) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (mountPoint == nullptr || info == nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -974,7 +1005,7 @@ Error PS4_SYSV_ABI sceSaveDataGetParam(const OrbisSaveDataMountPoint* mountPoint size_t paramBufSize, size_t* gotSize) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (paramType > OrbisSaveDataParamType::MTIME || paramBuf == nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -1049,7 +1080,7 @@ Error PS4_SYSV_ABI sceSaveDataGetParam(const OrbisSaveDataMountPoint* mountPoint Error PS4_SYSV_ABI sceSaveDataGetProgress(float* progress) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (progress == nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -1083,7 +1114,7 @@ Error PS4_SYSV_ABI sceSaveDataGetSaveDataMemory(const OrbisUserServiceUserId use Error PS4_SYSV_ABI sceSaveDataGetSaveDataMemory2(OrbisSaveDataMemoryGet2* getParam) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (getParam == nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -1179,7 +1210,7 @@ Error PS4_SYSV_ABI sceSaveDataLoadIcon(const OrbisSaveDataMountPoint* mountPoint OrbisSaveDataIcon* icon) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (mountPoint == nullptr || icon == nullptr || icon->buf == nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -1208,7 +1239,7 @@ Error PS4_SYSV_ABI sceSaveDataMount(const OrbisSaveDataMount* mount, OrbisSaveDataMountResult* mount_result) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (mount == nullptr && mount->dirName != nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -1229,7 +1260,7 @@ Error PS4_SYSV_ABI sceSaveDataMount2(const OrbisSaveDataMount2* mount, OrbisSaveDataMountResult* mount_result) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (mount == nullptr && mount->dirName != nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -1273,7 +1304,7 @@ int PS4_SYSV_ABI sceSaveDataRegisterEventCallback() { Error PS4_SYSV_ABI sceSaveDataRestoreBackupData(const OrbisSaveDataRestoreBackupData* restore) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (restore == nullptr || restore->dirName == nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -1324,7 +1355,7 @@ Error PS4_SYSV_ABI sceSaveDataSaveIcon(const OrbisSaveDataMountPoint* mountPoint const OrbisSaveDataIcon* icon) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (mountPoint == nullptr || icon == nullptr || icon->buf == nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -1372,7 +1403,7 @@ Error PS4_SYSV_ABI sceSaveDataSetParam(const OrbisSaveDataMountPoint* mountPoint size_t paramBufSize) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (paramType > OrbisSaveDataParamType::USER_PARAM || mountPoint == nullptr || paramBuf == nullptr) { @@ -1437,13 +1468,15 @@ Error PS4_SYSV_ABI sceSaveDataSetSaveDataMemory(OrbisUserServiceUserId userId, v OrbisSaveDataMemorySet2 setParam{}; setParam.userId = userId; setParam.data = &data; + setParam.param = nullptr; + setParam.icon = nullptr; return sceSaveDataSetSaveDataMemory2(&setParam); } Error PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2* setParam) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (setParam == nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -1476,17 +1509,35 @@ Error PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2* return Error::OK; } -int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory(/*u32 userId, size_t memorySize, - OrbisSaveDataParam* param*/) { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); - return ORBIS_OK; +Error PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory(OrbisUserServiceUserId userId, size_t memorySize, + OrbisSaveDataParam* param) { + LOG_DEBUG(Lib_SaveData, "called: userId = {}, memorySize = {}", userId, memorySize); + OrbisSaveDataMemorySetup2 setupParam{}; + setupParam.userId = userId; + setupParam.memorySize = memorySize; + setupParam.initParam = nullptr; + setupParam.initIcon = nullptr; + OrbisSaveDataMemorySetupResult result{}; + const auto res = sceSaveDataSetupSaveDataMemory2(&setupParam, &result); + if (res != Error::OK) { + return res; + } + if (param != nullptr) { + OrbisSaveDataMemorySet2 setParam{}; + setParam.userId = userId; + setParam.data = nullptr; + setParam.param = param; + setParam.icon = nullptr; + sceSaveDataSetSaveDataMemory2(&setParam); + } + return Error::OK; } Error PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2(const OrbisSaveDataMemorySetup2* setupParam, OrbisSaveDataMemorySetupResult* result) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (setupParam == nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -1506,20 +1557,20 @@ Error PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2(const OrbisSaveDataMemorySetu try { size_t existed_size = SaveMemory::CreateSaveMemory(setupParam->memorySize); if (existed_size == 0) { // Just created - if (setupParam->initParam != nullptr) { + if (g_fw_ver >= ElfInfo::FW_45 && setupParam->initParam != nullptr) { auto& sfo = SaveMemory::GetParamSFO(); setupParam->initParam->ToSFO(sfo); } SaveMemory::SaveSFO(); auto init_icon = setupParam->initIcon; - if (init_icon != nullptr) { + if (g_fw_ver >= ElfInfo::FW_45 && init_icon != nullptr) { SaveMemory::SetIcon(init_icon->buf, init_icon->bufSize); } else { SaveMemory::SetIcon(nullptr, 0); } } - if (result != nullptr) { + if (g_fw_ver >= ElfInfo::FW_45 && result != nullptr) { result->existedMemorySize = existed_size; } } catch (const fs::filesystem_error& e) { @@ -1555,7 +1606,7 @@ int PS4_SYSV_ABI sceSaveDataSyncCloudList() { Error PS4_SYSV_ABI sceSaveDataSyncSaveDataMemory(OrbisSaveDataMemorySync* syncParam) { if (!g_initialized) { LOG_INFO(Lib_SaveData, "called without initialize"); - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } if (syncParam == nullptr) { LOG_INFO(Lib_SaveData, "called with invalid parameter"); @@ -1576,11 +1627,15 @@ Error PS4_SYSV_ABI sceSaveDataSyncSaveDataMemory(OrbisSaveDataMemorySync* syncPa Error PS4_SYSV_ABI sceSaveDataTerminate() { LOG_DEBUG(Lib_SaveData, "called"); if (!g_initialized) { - return Error::NOT_INITIALIZED; + return setNotInitializedError(); } - for (const auto& instance : g_mount_slots) { + for (auto& instance : g_mount_slots) { if (instance.has_value()) { - return Error::BUSY; + if (g_fw_ver >= ElfInfo::FW_40) { + return Error::BUSY; + } + instance->Umount(); + instance.reset(); } } g_initialized = false; diff --git a/src/core/libraries/save_data/savedata.h b/src/core/libraries/save_data/savedata.h index 5e6a8ad4c..13b3dd59e 100644 --- a/src/core/libraries/save_data/savedata.h +++ b/src/core/libraries/save_data/savedata.h @@ -165,8 +165,8 @@ int PS4_SYSV_ABI sceSaveDataSetSaveDataLibraryUser(); Error PS4_SYSV_ABI sceSaveDataSetSaveDataMemory(OrbisUserServiceUserId userId, void* buf, size_t bufSize, int64_t offset); Error PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2* setParam); -int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory(/*u32 userId, size_t memorySize, - OrbisSaveDataParam* param*/); +Error PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory(OrbisUserServiceUserId userId, size_t memorySize, + OrbisSaveDataParam* param); Error PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2(const OrbisSaveDataMemorySetup2* setupParam, OrbisSaveDataMemorySetupResult* result); int PS4_SYSV_ABI sceSaveDataShutdownStart();