diff --git a/CMakeLists.txt b/CMakeLists.txt index 95fe228b..d64c6b81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,6 +141,7 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp src/core/libraries/system/msgdialog.h src/core/libraries/system/posix.cpp src/core/libraries/system/posix.h + src/core/libraries/save_data/error_codes.h src/core/libraries/save_data/savedata.cpp src/core/libraries/save_data/savedata.h src/core/libraries/system/savedatadialog.cpp diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index eafab7bc..d82c8730 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -35,6 +35,7 @@ static auto UserPaths = [] { create_path(PathType::LogDir, user_dir / LOG_DIR); create_path(PathType::ScreenshotsDir, user_dir / SCREENSHOTS_DIR); create_path(PathType::ShaderDir, user_dir / SHADER_DIR); + create_path(PathType::SaveDataDir, user_dir / SAVEDATA_DIR); return paths; }(); diff --git a/src/common/path_util.h b/src/common/path_util.h index 1836a3ac..618d0bda 100644 --- a/src/common/path_util.h +++ b/src/common/path_util.h @@ -13,7 +13,7 @@ enum class PathType { LogDir, // Where log files are stored. ScreenshotsDir, // Where screenshots are stored. ShaderDir, // Where shaders are stored. - App0, // Where guest application data is stored. + SaveDataDir, // Where guest save data is stored. }; constexpr auto PORTABLE_DIR = "user"; @@ -22,7 +22,7 @@ constexpr auto PORTABLE_DIR = "user"; constexpr auto LOG_DIR = "log"; constexpr auto SCREENSHOTS_DIR = "screenshots"; constexpr auto SHADER_DIR = "shader"; -constexpr auto APP0_DIR = "app0"; +constexpr auto SAVEDATA_DIR = "savedata"; // Filenames constexpr auto LOG_FILE = "shad_log.txt"; diff --git a/src/core/libraries/save_data/error_codes.h b/src/core/libraries/save_data/error_codes.h new file mode 100644 index 00000000..0dfe9def --- /dev/null +++ b/src/core/libraries/save_data/error_codes.h @@ -0,0 +1,8 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +constexpr int ORBIS_SAVE_DATA_ERROR_PARAMETER = 0x809f0000; +constexpr int ORBIS_SAVE_DATA_ERROR_NOT_FOUND = 0x809f0008; // save data doesn't exist +constexpr int ORBIS_SAVE_DATA_ERROR_EXISTS = 0x809f0007; // save data directory,same name exists \ No newline at end of file diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index 5082abb7..e63f9c1d 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -1,14 +1,21 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include +#include +#include +#include #include "common/assert.h" #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "core/libraries/save_data/savedata.h" +#include "error_codes.h" namespace Libraries::SaveData { +static std::string g_mount_point = "/savedata0"; // temp mount point (todo) + int PS4_SYSV_ABI sceSaveDataAbort() { LOG_ERROR(Lib_SaveData, "(STUBBED) called"); return ORBIS_OK; @@ -331,13 +338,46 @@ int PS4_SYSV_ABI sceSaveDataMount() { s32 PS4_SYSV_ABI sceSaveDataMount2(const OrbisSaveDataMount2* mount, OrbisSaveDataMountResult* mount_result) { - // will return save data not found , breakpoint for others - LOG_ERROR(Lib_SaveData, "(DUMMY) called user_id = {} dir_name = {} blocks = {} mount_mode = {}", - mount->user_id, mount->dir_name->data, mount->blocks, mount->mount_mode); - if (mount->mount_mode == 1) { // open - return 0x809F0008; // save data not found + LOG_INFO(Lib_SaveData, "called user_id = {} dir_name = {} blocks = {} mount_mode = {}", + mount->user_id, mount->dir_name->data, mount->blocks, mount->mount_mode); + + auto* param_sfo = Common::Singleton::Instance(); + std::string id(param_sfo->GetString("CONTENT_ID"), 7, 9); + const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / + std::to_string(mount->user_id) / "savedata" / id / + std::string(mount->dir_name->data); + switch (mount->mount_mode) { + case ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY: + case ORBIS_SAVE_DATA_MOUNT_MODE_RDWR: { + if (!std::filesystem::exists(mount_dir)) { + return ORBIS_SAVE_DATA_ERROR_NOT_FOUND; + } + auto* mnt = Common::Singleton::Instance(); + mnt->Mount(mount_dir, g_mount_point); + + mount_result->mount_status = 0; + strncpy(mount_result->mount_point.data, g_mount_point.c_str(), 16); + } break; + case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR: + case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | + ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: { + if (std::filesystem::exists(mount_dir)) { + return ORBIS_SAVE_DATA_ERROR_EXISTS; + } + std::filesystem::create_directories(mount_dir); + + auto* mnt = Common::Singleton::Instance(); + mnt->Mount(mount_dir, g_mount_point); + + mount_result->mount_status = 1; + strncpy(mount_result->mount_point.data, g_mount_point.c_str(), 16); + } break; + default: + UNREACHABLE(); } - UNREACHABLE(); + mount_result->required_blocks = 0; + + return ORBIS_OK; } int PS4_SYSV_ABI sceSaveDataMount5() { @@ -460,8 +500,13 @@ int PS4_SYSV_ABI sceSaveDataTransferringMount() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataUmount() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +s32 PS4_SYSV_ABI sceSaveDataUmount(const OrbisSaveDataMountPoint* mountPoint) { + LOG_INFO(Lib_SaveData, "mountPoint = {}", std::string(mountPoint->data)); + if (std::string(mountPoint->data).empty()) { + return ORBIS_SAVE_DATA_ERROR_PARAMETER; + } + auto* mnt = Common::Singleton::Instance(); + mnt->Unmount(std::string(mountPoint->data)); return ORBIS_OK; } diff --git a/src/core/libraries/save_data/savedata.h b/src/core/libraries/save_data/savedata.h index 6dfd8820..a4541587 100644 --- a/src/core/libraries/save_data/savedata.h +++ b/src/core/libraries/save_data/savedata.h @@ -42,6 +42,14 @@ struct OrbisSaveDataMountResult { s32 unk1; }; +// savedataMount2 mountModes (ORed values) +constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY = 1; +constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_RDWR = 2; +constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_CREATE = 4; +constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF = 8; +constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON = 16; +constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 = 32; + int PS4_SYSV_ABI sceSaveDataAbort(); int PS4_SYSV_ABI sceSaveDataBackup(); int PS4_SYSV_ABI sceSaveDataBindPsnAccount(); @@ -132,7 +140,7 @@ int PS4_SYSV_ABI sceSaveDataSyncCloudList(); int PS4_SYSV_ABI sceSaveDataSyncSaveDataMemory(); int PS4_SYSV_ABI sceSaveDataTerminate(); int PS4_SYSV_ABI sceSaveDataTransferringMount(); -int PS4_SYSV_ABI sceSaveDataUmount(); +int PS4_SYSV_ABI sceSaveDataUmount(const OrbisSaveDataMountPoint* mountPoint); int PS4_SYSV_ABI sceSaveDataUmountSys(); int PS4_SYSV_ABI sceSaveDataUmountWithBackup(); int PS4_SYSV_ABI sceSaveDataUnregisterEventCallback(); diff --git a/src/core/libraries/system/msgdialog.h b/src/core/libraries/system/msgdialog.h index 76a7d3f0..28d37913 100644 --- a/src/core/libraries/system/msgdialog.h +++ b/src/core/libraries/system/msgdialog.h @@ -14,6 +14,13 @@ namespace Libraries::MsgDialog { using OrbisUserServiceUserId = s32; +enum OrbisCommonDialogStatus { + ORBIS_COMMON_DIALOG_STATUS_NONE = 0, + ORBIS_COMMON_DIALOG_STATUS_INITIALIZED = 1, + ORBIS_COMMON_DIALOG_STATUS_RUNNING = 2, + ORBIS_COMMON_DIALOG_STATUS_FINISHED = 3 +}; + enum OrbisMsgDialogMode { ORBIS_MSG_DIALOG_MODE_USER_MSG = 1, ORBIS_MSG_DIALOG_MODE_PROGRESS_BAR = 2,