From 608301f86c9bf534af47eed2d883dbf22b1cdfa0 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Wed, 3 Jul 2024 20:04:56 +0300 Subject: [PATCH 01/13] dummy sceAppContentGetAddcontInfoList and fixed structs --- .../libraries/app_content/app_content.cpp | 7 +++++-- src/core/libraries/app_content/app_content.h | 21 +++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/core/libraries/app_content/app_content.cpp b/src/core/libraries/app_content/app_content.cpp index d0184cfa..c43d6c39 100644 --- a/src/core/libraries/app_content/app_content.cpp +++ b/src/core/libraries/app_content/app_content.cpp @@ -120,8 +120,11 @@ int PS4_SYSV_ABI sceAppContentGetAddcontInfo() { return ORBIS_OK; } -int PS4_SYSV_ABI sceAppContentGetAddcontInfoList() { - LOG_ERROR(Lib_AppContent, "(STUBBED) called"); +int PS4_SYSV_ABI sceAppContentGetAddcontInfoList(u32 service_label, + OrbisAppContentAddcontInfo* list, u32 list_num, + u32* hit_num) { + *hit_num = 0; + LOG_ERROR(Lib_AppContent, "(DUMMY) called"); return ORBIS_OK; } diff --git a/src/core/libraries/app_content/app_content.h b/src/core/libraries/app_content/app_content.h index d566b25c..ecf69199 100644 --- a/src/core/libraries/app_content/app_content.h +++ b/src/core/libraries/app_content/app_content.h @@ -31,22 +31,29 @@ struct OrbisAppContentBootParam { }; typedef u32 OrbisAppContentTemporaryDataOption; -constexpr int ORBIS_APP_CONTENT_MOUNTPOINT_DATA_MAXSIZE = 16; -typedef struct OrbisAppContentMountPoint { +constexpr int ORBIS_APP_CONTENT_MOUNTPOINT_DATA_MAXSIZE = 16; + +struct OrbisAppContentMountPoint { char data[ORBIS_APP_CONTENT_MOUNTPOINT_DATA_MAXSIZE]; -} OrbisAppContentMountPoint; +}; constexpr int ORBIS_APP_CONTENT_TEMPORARY_DATA_OPTION_NONE = 0; constexpr int ORBIS_APP_CONTENT_TEMPORARY_DATA_OPTION_FORMAT = (1 << 0); constexpr int ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE = 17; -typedef struct OrbisNpUnifiedEntitlementLabel { +struct OrbisNpUnifiedEntitlementLabel { char data[ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE]; -} OrbisNpUnifiedEntitlementLabel; + char padding[3]; +}; typedef u32 OrbisAppContentAppParamId; +struct OrbisAppContentAddcontInfo { + OrbisNpUnifiedEntitlementLabel entitlement_label; + u32 status; +}; + int PS4_SYSV_ABI _Z5dummyv(); int PS4_SYSV_ABI sceAppContentAddcontDelete(); int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownload(); @@ -64,7 +71,9 @@ int PS4_SYSV_ABI sceAppContentDownloadDataFormat(); int PS4_SYSV_ABI sceAppContentDownloadDataGetAvailableSpaceKb(); int PS4_SYSV_ABI sceAppContentGetAddcontDownloadProgress(); int PS4_SYSV_ABI sceAppContentGetAddcontInfo(); -int PS4_SYSV_ABI sceAppContentGetAddcontInfoList(); +int PS4_SYSV_ABI sceAppContentGetAddcontInfoList(u32 service_label, + OrbisAppContentAddcontInfo* list, u32 list_num, + u32* hit_num); int PS4_SYSV_ABI sceAppContentGetEntitlementKey(); int PS4_SYSV_ABI sceAppContentGetRegion(); int PS4_SYSV_ABI sceAppContentInitialize(const OrbisAppContentInitParam* initParam, From 0228b5861c8dde0a7af328eb1805d5cfd3d2b442 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Wed, 3 Jul 2024 20:05:21 +0300 Subject: [PATCH 02/13] added scePthreadGetthreadid --- src/core/libraries/kernel/thread_management.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 2b526eed..9c3151d8 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -1285,6 +1285,10 @@ int PS4_SYSV_ABI scePthreadOnce(int* once_control, void (*init_routine)(void)) { UNREACHABLE(); } +int PS4_SYSV_ABI scePthreadGetthreadid() { + return (int)g_pthread_self; +} + void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("lZzFeSxPl08", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_setcancelstate); LIB_FUNCTION("0TyVk4MSLt0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_init); @@ -1305,6 +1309,7 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("3kg7rT0NQIs", "libkernel", 1, "libkernel", 1, 1, scePthreadExit); LIB_FUNCTION("7Xl257M4VNI", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_equal); LIB_FUNCTION("h9CcP3J0oVM", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_join); + LIB_FUNCTION("EI-5-jlq2dE", "libkernel", 1, "libkernel", 1, 1, scePthreadGetthreadid); LIB_FUNCTION("aI+OeCz8xrQ", "libkernel", 1, "libkernel", 1, 1, scePthreadSelf); LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self); From 3875c00281eef628fb9ad090274fef8798130348 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 4 Jul 2024 09:38:25 +0300 Subject: [PATCH 03/13] fixed linux compile? --- src/core/libraries/kernel/thread_management.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 9c3151d8..3492cad4 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -1286,7 +1286,7 @@ int PS4_SYSV_ABI scePthreadOnce(int* once_control, void (*init_routine)(void)) { } int PS4_SYSV_ABI scePthreadGetthreadid() { - return (int)g_pthread_self; + return (int)(size_t)g_pthread_self; } void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { From 0ecc54032c0ba395c02b9728bc5e9ec48ef65071 Mon Sep 17 00:00:00 2001 From: raziel1000 Date: Thu, 4 Jul 2024 01:51:46 -0600 Subject: [PATCH 04/13] - Several SaveData functions. Dysmantle and we are doomed should save and load now. --- src/core/file_sys/fs.cpp | 7 +- src/core/file_sys/fs.h | 2 +- src/core/libraries/kernel/file_system.cpp | 3 +- src/core/libraries/save_data/error_codes.h | 26 +- src/core/libraries/save_data/savedata.cpp | 313 ++++++++++++++++----- src/core/libraries/save_data/savedata.h | 226 +++++++++++++-- src/emulator.cpp | 3 + 7 files changed, 488 insertions(+), 92 deletions(-) diff --git a/src/core/file_sys/fs.cpp b/src/core/file_sys/fs.cpp index 912c74bf..a1c03d89 100644 --- a/src/core/file_sys/fs.cpp +++ b/src/core/file_sys/fs.cpp @@ -18,7 +18,12 @@ void MntPoints::Mount(const std::filesystem::path& host_folder, const std::strin m_mnt_pairs.push_back(pair); } -void MntPoints::Unmount(const std::string& path) {} // TODO! +void MntPoints::Unmount(const std::filesystem::path& host_folder, const std::string& guest_folder) { + auto it = std::remove_if(m_mnt_pairs.begin(), m_mnt_pairs.end(), [&](const MntPair& pair) { + return pair.guest_path == guest_folder; + }); + m_mnt_pairs.erase(it, m_mnt_pairs.end()); +} void MntPoints::UnmountAll() { std::scoped_lock lock{m_mutex}; diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h index 4ba01685..b31931d1 100644 --- a/src/core/file_sys/fs.h +++ b/src/core/file_sys/fs.h @@ -22,7 +22,7 @@ public: virtual ~MntPoints() = default; void Mount(const std::filesystem::path& host_folder, const std::string& guest_folder); - void Unmount(const std::string& path); + void Unmount(const std::filesystem::path& host_folder, const std::string& guest_folder); void UnmountAll(); std::string GetHostDirectory(const std::string& guest_directory); std::string GetHostFile(const std::string& guest_file); diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index c3b6c3ae..b58555d5 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -227,7 +227,8 @@ int PS4_SYSV_ABI sceKernelMkdir(const char* path, u16 mode) { return SCE_KERNEL_ERROR_EEXIST; } - if (!std::filesystem::create_directory(dir_name)) { + //CUSA02456: path = /aotl after sceSaveDataMount(mode = 1) + if (dir_name.empty() || !std::filesystem::create_directory(dir_name)) { return SCE_KERNEL_ERROR_EIO; } diff --git a/src/core/libraries/save_data/error_codes.h b/src/core/libraries/save_data/error_codes.h index 0dfe9def..a4a1b7a5 100644 --- a/src/core/libraries/save_data/error_codes.h +++ b/src/core/libraries/save_data/error_codes.h @@ -3,6 +3,26 @@ #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 +constexpr int ORBIS_SAVE_DATA_ERROR_PARAMETER = 0x809F0000; +constexpr int ORBIS_SAVE_DATA_ERROR_NOT_INITIALIZED = 0x809F0001; +constexpr int ORBIS_SAVE_DATA_ERROR_OUT_OF_MEMORY = 0x809F0002; +constexpr int ORBIS_SAVE_DATA_ERROR_BUSY = 0x809F0003; +constexpr int ORBIS_SAVE_DATA_ERROR_NOT_MOUNTED = 0x809F0004; +constexpr int ORBIS_SAVE_DATA_ERROR_NO_PERMISSION = 0x809F0005; +constexpr int ORBIS_SAVE_DATA_ERROR_FINGERPRINT_MISMATCH = 0x809F0006; +constexpr int ORBIS_SAVE_DATA_ERROR_EXISTS = 0x809F0007; +constexpr int ORBIS_SAVE_DATA_ERROR_NOT_FOUND = 0x809F0008; +constexpr int ORBIS_SAVE_DATA_ERROR_NO_SPACE_FS = 0x809F000A; +constexpr int ORBIS_SAVE_DATA_ERROR_INTERNAL = 0x809F000B; +constexpr int ORBIS_SAVE_DATA_ERROR_MOUNT_FULL = 0x809F000C; +constexpr int ORBIS_SAVE_DATA_ERROR_BAD_MOUNTED = 0x809F000D; +constexpr int ORBIS_SAVE_DATA_ERROR_FILE_NOT_FOUND = 0x809F000E; +constexpr int ORBIS_SAVE_DATA_ERROR_BROKEN = 0x809F000F; +constexpr int ORBIS_SAVE_DATA_ERROR_INVALID_LOGIN_USER = 0x809F0011; +constexpr int ORBIS_SAVE_DATA_ERROR_MEMORY_NOT_READY = 0x809F0012; +constexpr int ORBIS_SAVE_DATA_ERROR_BACKUP_BUSY = 0x809F0013; +constexpr int ORBIS_SAVE_DATA_ERROR_NOT_REGIST_CALLBACK = 0x809F0015; +constexpr int ORBIS_SAVE_DATA_ERROR_BUSY_FOR_SAVING = 0x809F0016; +constexpr int ORBIS_SAVE_DATA_ERROR_LIMITATION_OVER = 0x809F0017; +constexpr int ORBIS_SAVE_DATA_ERROR_EVENT_BUSY = 0x809F0018; +constexpr int ORBIS_SAVE_DATA_ERROR_PARAMSFO_TRANSFER_TITLE_ID_NOT_FOUND = 0x809F0019; diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index d4f04a25..68bb5566 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include +#include #include #include #include @@ -13,8 +15,8 @@ #include "error_codes.h" namespace Libraries::SaveData { - static std::string g_mount_point = "/savedata0"; // temp mount point (todo) +std::string game_serial; int PS4_SYSV_ABI sceSaveDataAbort() { LOG_ERROR(Lib_SaveData, "(STUBBED) called"); @@ -46,8 +48,14 @@ int PS4_SYSV_ABI sceSaveDataChangeInternal() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataCheckBackupData() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataCheckBackupData(const OrbisSaveDataCheckBackupData* check) { + auto* mnt = Common::Singleton::Instance(); + std::string mount_dir = mnt->GetHostFile(check->dirName->data); + if (!std::filesystem::exists(mount_dir)) { + return ORBIS_SAVE_DATA_ERROR_NOT_FOUND; + } + LOG_INFO(Lib_SaveData, "called = {}", mount_dir); + return ORBIS_OK; } @@ -136,8 +144,14 @@ int PS4_SYSV_ABI sceSaveDataDebugTarget() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataDelete() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataDelete(const OrbisSaveDataDelete* del) { + const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / + std::to_string(1) / game_serial / std::string(del->dirName->data); + LOG_INFO(Lib_SaveData, "called: dirname = {}, mount_dir = {}", (char*)del->dirName->data, + mount_dir.string()); + if (std::filesystem::exists(mount_dir) && std::filesystem::is_directory(mount_dir)) { + std::filesystem::remove_all(mount_dir); + } return ORBIS_OK; } @@ -161,8 +175,14 @@ int PS4_SYSV_ABI sceSaveDataDeleteUser() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataDirNameSearch() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataDirNameSearch(const OrbisSaveDataDirNameSearchCond* cond, + OrbisSaveDataDirNameSearchResult* result) { + if (cond == nullptr || cond->dirName == nullptr) + return ORBIS_SAVE_DATA_ERROR_PARAMETER; + LOG_ERROR(Lib_SaveData, + "TODO sceSaveDataDirNameSearch: search_dir_name = {}, key = {}, result = {}", + cond->dirName->data, (int)cond->key, (result->infos == nullptr)); + return ORBIS_OK; } @@ -226,8 +246,22 @@ int PS4_SYSV_ABI sceSaveDataGetEventInfo() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataGetEventResult() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataGetEventResult(const OrbisSaveDataEventParam* eventParam, + OrbisSaveDataEvent* event) { + LOG_INFO(Lib_SaveData, "called sceSaveDataGetEventResult : null = {}", (eventParam == nullptr)); + if (eventParam == nullptr) + return ORBIS_SAVE_DATA_ERROR_PARAMETER; + + const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / + std::to_string(1) / game_serial; // fix me + + Common::FS::IOFile file(mount_dir / "param.txt", Common::FS::FileAccessMode::Read); + OrbisSaveDataParam* param = new OrbisSaveDataParam{}; + file.ReadRaw(param, sizeof(OrbisSaveDataParam)); + + LOG_INFO(Lib_SaveData, "called"); + event->userId = 1; + return ORBIS_OK; } @@ -241,8 +275,11 @@ int PS4_SYSV_ABI sceSaveDataGetMountedSaveDataCount() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataGetMountInfo() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataGetMountInfo(const OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataMountInfo* info) { + LOG_INFO(Lib_SaveData, "called"); + info->blocks = ORBIS_SAVE_DATA_BLOCKS_MAX; + info->freeBlocks = ORBIS_SAVE_DATA_BLOCKS_MAX; return ORBIS_OK; } @@ -261,13 +298,43 @@ int PS4_SYSV_ABI sceSaveDataGetSaveDataCount() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory(const u32 userId, void* buf, const size_t bufSize, + const int64_t offset) { + const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / + std::to_string(userId) / game_serial / "save_mem1.sav"; + + Common::FS::IOFile file(mount_dir, Common::FS::FileAccessMode::Read); + if (!file.IsOpen()) { + return false; + } + file.Seek(offset); + size_t nbytes = file.ReadRaw(buf, bufSize); + LOG_INFO(Lib_SaveData, "called: bufSize = {}, offset = {}", bufSize, offset, nbytes); + return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory2() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory2(OrbisSaveDataMemoryGet2* getParam) { + const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / + std::to_string(getParam->userId) / game_serial; + if (getParam == nullptr) + return ORBIS_SAVE_DATA_ERROR_PARAMETER; + if (getParam->data != nullptr) { + Common::FS::IOFile file(mount_dir / "save_mem2.sav", Common::FS::FileAccessMode::Read); + if (!file.IsOpen()) { + return false; + } + file.Seek(getParam->data->offset); + size_t nbytes = file.ReadRaw(getParam->data->buf, getParam->data->bufSize); + LOG_INFO(Lib_SaveData, "called: bufSize = {}, offset = {}", getParam->data->bufSize, + getParam->data->offset); + } + + if (getParam->param != nullptr) { + Common::FS::IOFile file1(mount_dir / "param.txt", Common::FS::FileAccessMode::Read); + size_t nbytes = file1.ReadRaw(getParam->param, sizeof(OrbisSaveDataParam)); + } + return ORBIS_OK; } @@ -297,17 +364,23 @@ int PS4_SYSV_ABI sceSaveDataGetUpdatedDataCount() { } int PS4_SYSV_ABI sceSaveDataInitialize() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); + LOG_INFO(Lib_SaveData, "called"); + static auto* param_sfo = Common::Singleton::Instance(); + game_serial = std::string(param_sfo->GetString("CONTENT_ID"), 7, 9); return ORBIS_OK; } int PS4_SYSV_ABI sceSaveDataInitialize2() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); + LOG_INFO(Lib_SaveData, "called"); + static auto* param_sfo = Common::Singleton::Instance(); + game_serial = std::string(param_sfo->GetString("CONTENT_ID"), 7, 9); return ORBIS_OK; } int PS4_SYSV_ABI sceSaveDataInitialize3() { - LOG_ERROR(Lib_SaveData, "(DUMMY) called"); + LOG_INFO(Lib_SaveData, "called"); + static auto* param_sfo = Common::Singleton::Instance(); + game_serial = std::string(param_sfo->GetString("CONTENT_ID"), 7, 9); return ORBIS_OK; } @@ -326,18 +399,24 @@ int PS4_SYSV_ABI sceSaveDataIsMounted() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataLoadIcon() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataLoadIcon(const OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataIcon* icon) { + auto* mnt = Common::Singleton::Instance(); + std::string mount_dir = mnt->GetHostFile(mountPoint->data); + LOG_INFO(Lib_SaveData, "called: dir = {}", mount_dir); + + if (icon != nullptr) { + Common::FS::IOFile file(mount_dir + "/save_data.png", Common::FS::FileAccessMode::Read); + icon->bufSize = file.GetSize(); + size_t nbytes = file.ReadRaw(icon->buf, icon->bufSize); + } return ORBIS_OK; } -s32 saveDataMount(u32 user_id, std::string dir_name, u32 mount_mode, +s32 saveDataMount(u32 user_id, char* dir_name, u32 mount_mode, OrbisSaveDataMountResult* mount_result) { - - 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(user_id) / "savedata" / id / dir_name; + std::to_string(user_id) / game_serial / dir_name; switch (mount_mode) { case ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY: case ORBIS_SAVE_DATA_MOUNT_MODE_RDWR: @@ -346,10 +425,9 @@ s32 saveDataMount(u32 user_id, std::string dir_name, u32 mount_mode, 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); + std::strncpy(mount_result->mount_point.data, g_mount_point.c_str(), 16); + mnt->Mount(mount_dir, mount_result->mount_point.data); } break; case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY: @@ -357,17 +435,22 @@ s32 saveDataMount(u32 user_id, std::string dir_name, u32 mount_mode, case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF | - ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: { + ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: + case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | + ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF: { + auto* mnt = Common::Singleton::Instance(); if (std::filesystem::exists(mount_dir)) { + std::strncpy(mount_result->mount_point.data, g_mount_point.c_str(), 16); + mnt->Mount(mount_dir, mount_result->mount_point.data); + mount_result->required_blocks = 0; + mount_result->mount_status = 0; 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); + if (std::filesystem::create_directories(mount_dir)) { + std::strncpy(mount_result->mount_point.data, g_mount_point.c_str(), 16); + mnt->Mount(mount_dir, mount_result->mount_point.data); + mount_result->mount_status = 1; + } } break; case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | @@ -375,12 +458,10 @@ s32 saveDataMount(u32 user_id, std::string dir_name, u32 mount_mode, if (!std::filesystem::exists(mount_dir)) { std::filesystem::create_directories(mount_dir); } - auto* mnt = Common::Singleton::Instance(); - mnt->Mount(mount_dir, g_mount_point); - + std::strncpy(mount_result->mount_point.data, g_mount_point.c_str(), 16); + mnt->Mount(mount_dir, mount_result->mount_point.data); mount_result->mount_status = 1; - strncpy(mount_result->mount_point.data, g_mount_point.c_str(), 16); } break; default: UNREACHABLE(); @@ -395,9 +476,9 @@ s32 PS4_SYSV_ABI sceSaveDataMount(const OrbisSaveDataMount* mount, if (mount == nullptr) { return ORBIS_SAVE_DATA_ERROR_PARAMETER; } - LOG_INFO(Lib_SaveData, "called: mount = {}, mode = {}, blocks = {}", mount->dir_name->data, + LOG_INFO(Lib_SaveData, "called: dirName = {}, mode = {}, blocks = {}", mount->dir_name->data, mount->mount_mode, mount->blocks); - return saveDataMount(mount->user_id, std::string(mount->dir_name->data), mount->mount_mode, + return saveDataMount(mount->user_id, (char*)mount->dir_name->data, mount->mount_mode, mount_result); } @@ -406,9 +487,9 @@ s32 PS4_SYSV_ABI sceSaveDataMount2(const OrbisSaveDataMount2* mount, if (mount == nullptr) { return ORBIS_SAVE_DATA_ERROR_PARAMETER; } - LOG_INFO(Lib_SaveData, "called: mount = {}, mode = {}, blocks = {}", mount->dir_name->data, + LOG_INFO(Lib_SaveData, "called: dirName = {}, mode = {}, blocks = {}", mount->dir_name->data, mount->mount_mode, mount->blocks); - return saveDataMount(mount->user_id, std::string(mount->dir_name->data), mount->mount_mode, + return saveDataMount(mount->user_id, (char*)mount->dir_name->data, mount->mount_mode, mount_result); } @@ -457,8 +538,16 @@ int PS4_SYSV_ABI sceSaveDataRestoreLoadSaveDataMemory() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataSaveIcon() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataSaveIcon(const OrbisSaveDataMountPoint* mountPoint, + const OrbisSaveDataIcon* icon) { + auto* mnt = Common::Singleton::Instance(); + std::string mount_dir = mnt->GetHostFile(mountPoint->data); + LOG_INFO(Lib_SaveData, "called = {}", mount_dir); + + if (icon != nullptr) { + Common::FS::IOFile file(mount_dir + "/save_data.png", Common::FS::FileAccessMode::Write); + file.WriteRaw((void*)icon->buf, icon->bufSize); + } return ORBIS_OK; } @@ -472,8 +561,17 @@ int PS4_SYSV_ABI sceSaveDataSetEventInfo() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataSetParam() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataSetParam(const OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataParamType paramType, const void* paramBuf, + size_t paramBufSize) { + auto* mnt = Common::Singleton::Instance(); + std::string mount_dir = mnt->GetHostFile(mountPoint->data); + LOG_INFO(Lib_SaveData, "called = {}, mountPoint->data = {}", mount_dir, mountPoint->data); + + if (paramBuf != nullptr) { + Common::FS::IOFile file(mount_dir + "/param.txt", Common::FS::FileAccessMode::Write); + file.WriteRaw((void*)paramBuf, paramBufSize); + } return ORBIS_OK; } @@ -482,23 +580,89 @@ int PS4_SYSV_ABI sceSaveDataSetSaveDataLibraryUser() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory(const u32 userId, const void* buf, + const size_t bufSize, const int64_t offset) { + LOG_INFO(Lib_SaveData, "called"); + const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / + std::to_string(userId) / game_serial / "save_mem1.sav"; + + Common::FS::IOFile file(mount_dir, Common::FS::FileAccessMode::Write); + file.Seek(offset); + file.WriteRaw((void*)buf, bufSize); + return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2* setParam) { + LOG_INFO(Lib_SaveData, "called: dataNum = {}, slotId= {}", setParam->dataNum, setParam->slotId); + const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / + std::to_string(setParam->userId) / game_serial; + if (setParam->data != nullptr) { + Common::FS::IOFile file(mount_dir / "save_mem2.sav", Common::FS::FileAccessMode::Write); + if (!file.IsOpen()) + return -1; + file.Seek(setParam->data->offset); + file.WriteRaw((void*)setParam->data->buf, setParam->data->bufSize); + } + + if (setParam->param != nullptr) { + Common::FS::IOFile file(mount_dir / "param.txt", Common::FS::FileAccessMode::Write); + file.WriteRaw((void*)setParam->param, sizeof(OrbisSaveDataParam)); + } + + if (setParam->icon != nullptr) { + Common::FS::IOFile file(mount_dir / "save_icon.png", Common::FS::FileAccessMode::Write); + file.WriteRaw((void*)setParam->icon->buf, setParam->icon->bufSize); + } + return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory(u32 userId, size_t memorySize, + OrbisSaveDataParam* param) { + + LOG_INFO(Lib_SaveData, "called:userId = {}, memorySize = {}", userId, memorySize); + + const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / + std::to_string(userId) / game_serial; + + if (std::filesystem::exists(mount_dir)) { + return ORBIS_SAVE_DATA_ERROR_EXISTS; + } + std::filesystem::create_directories(mount_dir); + std::vector buf(memorySize); + Common::FS::IOFile::WriteBytes(mount_dir / "save_mem1.sav", buf); return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2(const OrbisSaveDataMemorySetup2* setupParam, + OrbisSaveDataMemorySetupResult* result) { + if (setupParam == nullptr) { + return ORBIS_SAVE_DATA_ERROR_PARAMETER; + } + LOG_INFO(Lib_SaveData, "called"); + // if (setupParam->option == 1) { // check this later. + const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / + std::to_string(setupParam->userId) / game_serial; + if (std::filesystem::exists(mount_dir) && + std::filesystem::exists(mount_dir / "save_mem2.sav")) { + Common::FS::IOFile file(mount_dir / "save_mem2.sav", Common::FS::FileAccessMode::Read); + if (!file.IsOpen()) + return -1; + // Bunny - CUSA07988 has a null result, having null result is checked and valid. + if (result != nullptr) + result->existedMemorySize = file.GetSize(); // Assign the saved data size. + // do not return ORBIS_SAVE_DATA_ERROR_EXISTS, as it will not trigger + // sceSaveDataGetSaveDataMemory2. + } else { + std::filesystem::create_directories(mount_dir); + std::vector buf(setupParam->memorySize); // check if > 0x1000000 (16.77mb) or x2? + Common::FS::IOFile::WriteBytes(mount_dir / "save_mem2.sav", buf); + std::vector paramBuf(sizeof(OrbisSaveDataParam)); + Common::FS::IOFile::WriteBytes(mount_dir / "param.txt", paramBuf); + std::vector iconBuf(setupParam->iconMemorySize); + Common::FS::IOFile::WriteBytes(mount_dir / "save_icon.png", iconBuf); + } return ORBIS_OK; } @@ -517,8 +681,8 @@ int PS4_SYSV_ABI sceSaveDataSyncCloudList() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataSyncSaveDataMemory() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataSyncSaveDataMemory(OrbisSaveDataMemorySync* syncParam) { + LOG_ERROR(Lib_SaveData, "(STUBBED) called: option = {}", syncParam->option); return ORBIS_OK; } @@ -533,12 +697,16 @@ int PS4_SYSV_ABI sceSaveDataTransferringMount() { } 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; + return ORBIS_SAVE_DATA_ERROR_NOT_MOUNTED; } + const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / + std::to_string(1) / game_serial / mountPoint->data; auto* mnt = Common::Singleton::Instance(); - mnt->Unmount(std::string(mountPoint->data)); + + mnt->Unmount(mount_dir, mountPoint->data); + LOG_INFO(Lib_SaveData, "mountPoint = {}", std::string(mountPoint->data)); + return ORBIS_OK; } @@ -547,8 +715,27 @@ int PS4_SYSV_ABI sceSaveDataUmountSys() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataUmountWithBackup() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); +int PS4_SYSV_ABI sceSaveDataUmountWithBackup(const OrbisSaveDataMountPoint* mountPoint) { + LOG_ERROR(Lib_SaveData, "called = {}", std::string(mountPoint->data)); + auto* mnt = Common::Singleton::Instance(); + std::string mount_dir = mnt->GetHostFile(mountPoint->data); + if (!std::filesystem::exists(mount_dir)) { + return ORBIS_SAVE_DATA_ERROR_NOT_FOUND; + } else { + std::filesystem::path mnt_dir(mount_dir); + std::filesystem::create_directories(mnt_dir.parent_path() / "backup"); + + for (const auto& entry : std::filesystem::recursive_directory_iterator(mnt_dir)) { + const auto& path = entry.path(); + std::filesystem::path target_path = mnt_dir.parent_path() / "backup"; + + if (std::filesystem::is_regular_file(path)) { + std::filesystem::copy(path, target_path, + std::filesystem::copy_options::overwrite_existing); + } + } + mnt->Unmount(mount_dir, mountPoint->data); + } return ORBIS_OK; } diff --git a/src/core/libraries/save_data/savedata.h b/src/core/libraries/save_data/savedata.h index 60f99cea..dbfbd320 100644 --- a/src/core/libraries/save_data/savedata.h +++ b/src/core/libraries/save_data/savedata.h @@ -43,19 +43,18 @@ struct OrbisSaveDataMountResult { }; constexpr int ORBIS_SAVE_DATA_TITLE_ID_DATA_SIZE = 10; -typedef struct OrbisSaveDataTitleId { +struct OrbisSaveDataTitleId { char data[ORBIS_SAVE_DATA_TITLE_ID_DATA_SIZE]; char padding[6]; - -} OrbisSaveDataTitleId; +}; constexpr int ORBIS_SAVE_DATA_FINGERPRINT_DATA_SIZE = 65; -typedef struct OrbisSaveDataFingerprint { +struct OrbisSaveDataFingerprint { char data[ORBIS_SAVE_DATA_FINGERPRINT_DATA_SIZE]; char padding[15]; -} OrbisSaveDataFingerprint; +}; -typedef struct OrbisSaveDataMount { +struct OrbisSaveDataMount { s32 user_id; s32 pad; const OrbisSaveDataTitleId* titleId; @@ -64,7 +63,114 @@ typedef struct OrbisSaveDataMount { u64 blocks; u32 mount_mode; u8 reserved[32]; -} OrbisSaveDataMount; +}; + +typedef u32 OrbisSaveDataParamType; + +constexpr int ORBIS_SAVE_DATA_TITLE_MAXSIZE = 128; +constexpr int ORBIS_SAVE_DATA_SUBTITLE_MAXSIZE = 128; +constexpr int ORBIS_SAVE_DATA_DETAIL_MAXSIZE = 1024; +struct OrbisSaveDataParam { + char title[ORBIS_SAVE_DATA_TITLE_MAXSIZE]; + char subTitle[ORBIS_SAVE_DATA_SUBTITLE_MAXSIZE]; + char detail[ORBIS_SAVE_DATA_DETAIL_MAXSIZE]; + u32 userParam; + int : 32; + time_t mtime; + u8 reserved[32]; +}; + +struct OrbisSaveDataIcon { + void* buf; + size_t bufSize; + size_t dataSize; + u8 reserved[32]; +}; + +typedef u32 OrbisSaveDataSaveDataMemoryOption; +#define ORBIS_SAVE_DATA_MEMORY_OPTION_NONE (0x00000000) +#define ORBIS_SAVE_DATA_MEMORY_OPTION_SET_PARAM (0x00000001 << 0) +#define ORBIS_SAVE_DATA_MEMORY_OPTION_DOUBLE_BUFFER (0x00000001 << 1) + +struct OrbisSaveDataMemorySetup2 { + OrbisSaveDataSaveDataMemoryOption option; + s32 userId; + size_t memorySize; + size_t iconMemorySize; + const OrbisSaveDataParam* initParam; + const OrbisSaveDataIcon* initIcon; + u32 slotId; + u8 reserved[20]; +}; + +struct OrbisSaveDataMemorySetupResult { + size_t existedMemorySize; + u8 reserved[16]; +}; + +typedef u32 OrbisSaveDataEventType; +#define SCE_SAVE_DATA_EVENT_TYPE_INVALID (0) +#define SCE_SAVE_DATA_EVENT_TYPE_UMOUNT_BACKUP_END (1) +#define SCE_SAVE_DATA_EVENT_TYPE_BACKUP_END (2) +#define SCE_SAVE_DATA_EVENT_TYPE_SAVE_DATA_MEMORY_SYNC_END (3) + +struct OrbisSaveDataEvent { + OrbisSaveDataEventType type; + s32 errorCode; + s32 userId; + u8 padding[4]; + OrbisSaveDataTitleId titleId; + OrbisSaveDataDirName dirName; + u8 reserved[40]; +}; + +struct OrbisSaveDataMemoryData { + void* buf; + size_t bufSize; + off_t offset; + u8 reserved[40]; +}; + +struct OrbisSaveDataMemoryGet2 { + s32 userId; + u8 padding[4]; + OrbisSaveDataMemoryData* data; + OrbisSaveDataParam* param; + OrbisSaveDataIcon* icon; + u32 slotId; + u8 reserved[28]; +}; + +struct OrbisSaveDataMemorySet2 { + s32 userId; + u8 padding[4]; + const OrbisSaveDataMemoryData* data; + const OrbisSaveDataParam* param; + const OrbisSaveDataIcon* icon; + u32 dataNum; + u8 slotId; + u8 reserved[24]; +}; + +struct OrbisSaveDataCheckBackupData { + s32 userId; + int : 32; + const OrbisSaveDataTitleId* titleId; + const OrbisSaveDataDirName* dirName; + OrbisSaveDataParam* param; + OrbisSaveDataIcon* icon; + u8 reserved[32]; +}; + +struct OrbisSaveDataMountInfo { + u64 blocks; + u64 freeBlocks; + u8 reserved[32]; +}; + +#define ORBIS_SAVE_DATA_BLOCK_SIZE (32768) +#define ORBIS_SAVE_DATA_BLOCKS_MIN2 (96) +#define ORBIS_SAVE_DATA_BLOCKS_MAX (32768) // savedataMount2 mountModes (ORed values) constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY = 1; @@ -73,6 +179,69 @@ 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; +typedef struct _OrbisSaveDataEventParam OrbisSaveDataEventParam; + +typedef u32 OrbisSaveDataSortKey; +#define ORBIS_SAVE_DATA_SORT_KEY_DIRNAME (0) +#define ORBIS_SAVE_DATA_SORT_KEY_USER_PARAM (1) +#define ORBIS_SAVE_DATA_SORT_KEY_BLOCKS (2) +#define ORBIS_SAVE_DATA_SORT_KEY_MTIME (3) +#define ORBIS_SAVE_DATA_SORT_KEY_FREE_BLOCKS (5) + +typedef u32 OrbisSaveDataSortOrder; +#define ORBIS_SAVE_DATA_SORT_ORDER_ASCENT (0) +#define ORBIS_SAVE_DATA_SORT_ORDER_DESCENT (1) + +struct OrbisSaveDataDirNameSearchCond { + s32 userId; + int : 32; + const OrbisSaveDataTitleId* titleId; + const OrbisSaveDataDirName* dirName; + OrbisSaveDataSortKey key; + OrbisSaveDataSortOrder order; + u8 reserved[32]; +}; + +struct OrbisSaveDataSearchInfo { + u64 blocks; + u64 freeBlocks; + u8 reserved[32]; +}; + +struct OrbisSaveDataDirNameSearchResult { + u32 hitNum; + int : 32; + OrbisSaveDataDirName* dirNames; + u32 dirNamesNum; + u32 setNum; + OrbisSaveDataParam* params; + OrbisSaveDataSearchInfo* infos; + u8 reserved[12]; + int : 32; +}; + +struct OrbisSaveDataDelete { + s32 userId; + int : 32; + const OrbisSaveDataTitleId* titleId; + const OrbisSaveDataDirName* dirName; + u32 unused; + u8 reserved[32]; + int : 32; +}; + +typedef u32 OrbisSaveDataMemorySyncOption; + +#define SCE_SAVE_DATA_MEMORY_SYNC_OPTION_NONE (0x00000000) +#define SCE_SAVE_DATA_MEMORY_SYNC_OPTION_BLOCKING (0x00000001 << 0) + +struct OrbisSaveDataMemorySync { + s32 userId; + u32 slotId; + OrbisSaveDataMemorySyncOption option; + u8 reserved[28]; + +}; int PS4_SYSV_ABI sceSaveDataAbort(); int PS4_SYSV_ABI sceSaveDataBackup(); @@ -80,7 +249,7 @@ int PS4_SYSV_ABI sceSaveDataBindPsnAccount(); int PS4_SYSV_ABI sceSaveDataBindPsnAccountForSystemBackup(); int PS4_SYSV_ABI sceSaveDataChangeDatabase(); int PS4_SYSV_ABI sceSaveDataChangeInternal(); -int PS4_SYSV_ABI sceSaveDataCheckBackupData(); +int PS4_SYSV_ABI sceSaveDataCheckBackupData(const OrbisSaveDataCheckBackupData* check); int PS4_SYSV_ABI sceSaveDataCheckBackupDataForCdlg(); int PS4_SYSV_ABI sceSaveDataCheckBackupDataInternal(); int PS4_SYSV_ABI sceSaveDataCheckCloudData(); @@ -98,12 +267,13 @@ int PS4_SYSV_ABI sceSaveDataDebugCreateSaveDataRoot(); int PS4_SYSV_ABI sceSaveDataDebugGetThreadId(); int PS4_SYSV_ABI sceSaveDataDebugRemoveSaveDataRoot(); int PS4_SYSV_ABI sceSaveDataDebugTarget(); -int PS4_SYSV_ABI sceSaveDataDelete(); +int PS4_SYSV_ABI sceSaveDataDelete(const OrbisSaveDataDelete* del); int PS4_SYSV_ABI sceSaveDataDelete5(); int PS4_SYSV_ABI sceSaveDataDeleteAllUser(); int PS4_SYSV_ABI sceSaveDataDeleteCloudData(); int PS4_SYSV_ABI sceSaveDataDeleteUser(); -int PS4_SYSV_ABI sceSaveDataDirNameSearch(); +int PS4_SYSV_ABI sceSaveDataDirNameSearch(const OrbisSaveDataDirNameSearchCond* cond, + OrbisSaveDataDirNameSearchResult* result); int PS4_SYSV_ABI sceSaveDataDirNameSearchInternal(); int PS4_SYSV_ABI sceSaveDataDownload(); int PS4_SYSV_ABI sceSaveDataGetAllSize(); @@ -116,15 +286,18 @@ int PS4_SYSV_ABI sceSaveDataGetClientThreadPriority(); int PS4_SYSV_ABI sceSaveDataGetCloudQuotaInfo(); int PS4_SYSV_ABI sceSaveDataGetDataBaseFilePath(); int PS4_SYSV_ABI sceSaveDataGetEventInfo(); -int PS4_SYSV_ABI sceSaveDataGetEventResult(); +int PS4_SYSV_ABI sceSaveDataGetEventResult(const OrbisSaveDataEventParam* eventParam, + OrbisSaveDataEvent* event); int PS4_SYSV_ABI sceSaveDataGetFormat(); int PS4_SYSV_ABI sceSaveDataGetMountedSaveDataCount(); -int PS4_SYSV_ABI sceSaveDataGetMountInfo(); +int PS4_SYSV_ABI sceSaveDataGetMountInfo(const OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataMountInfo* info); int PS4_SYSV_ABI sceSaveDataGetParam(); int PS4_SYSV_ABI sceSaveDataGetProgress(); int PS4_SYSV_ABI sceSaveDataGetSaveDataCount(); -int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory(); -int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory2(); +int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory(const u32 userId, void* buf, const size_t bufSize, + const int64_t offset); +int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory2(OrbisSaveDataMemoryGet2* getParam); int PS4_SYSV_ABI sceSaveDataGetSaveDataRootDir(); int PS4_SYSV_ABI sceSaveDataGetSaveDataRootPath(); int PS4_SYSV_ABI sceSaveDataGetSaveDataRootUsbPath(); @@ -136,7 +309,8 @@ int PS4_SYSV_ABI sceSaveDataInitialize3(); int PS4_SYSV_ABI sceSaveDataInitializeForCdlg(); int PS4_SYSV_ABI sceSaveDataIsDeletingUsbDb(); int PS4_SYSV_ABI sceSaveDataIsMounted(); -int PS4_SYSV_ABI sceSaveDataLoadIcon(); +int PS4_SYSV_ABI sceSaveDataLoadIcon(const OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataIcon* icon); int PS4_SYSV_ABI sceSaveDataMount(const OrbisSaveDataMount* mount, OrbisSaveDataMountResult* mount_result); s32 PS4_SYSV_ABI sceSaveDataMount2(const OrbisSaveDataMount2* mount, @@ -150,24 +324,30 @@ int PS4_SYSV_ABI sceSaveDataRegisterEventCallback(); int PS4_SYSV_ABI sceSaveDataRestoreBackupData(); int PS4_SYSV_ABI sceSaveDataRestoreBackupDataForCdlg(); int PS4_SYSV_ABI sceSaveDataRestoreLoadSaveDataMemory(); -int PS4_SYSV_ABI sceSaveDataSaveIcon(); +int PS4_SYSV_ABI sceSaveDataSaveIcon(const OrbisSaveDataMountPoint* mountPoint, + const OrbisSaveDataIcon* icon); int PS4_SYSV_ABI sceSaveDataSetAutoUploadSetting(); int PS4_SYSV_ABI sceSaveDataSetEventInfo(); -int PS4_SYSV_ABI sceSaveDataSetParam(); +int PS4_SYSV_ABI sceSaveDataSetParam(const OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataParamType paramType, const void* paramBuf, + size_t paramBufSize); int PS4_SYSV_ABI sceSaveDataSetSaveDataLibraryUser(); -int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory(); -int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(); -int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory(); -int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2(); +int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory(const u32 userId, const void* buf, + const size_t bufSize, const int64_t offset); +int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2* setParam); +int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory(u32 userId, size_t memorySize, + OrbisSaveDataParam* param); +int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2(const OrbisSaveDataMemorySetup2* setupParam, + OrbisSaveDataMemorySetupResult* result); int PS4_SYSV_ABI sceSaveDataShutdownStart(); int PS4_SYSV_ABI sceSaveDataSupportedFakeBrokenStatus(); int PS4_SYSV_ABI sceSaveDataSyncCloudList(); -int PS4_SYSV_ABI sceSaveDataSyncSaveDataMemory(); +int PS4_SYSV_ABI sceSaveDataSyncSaveDataMemory(OrbisSaveDataMemorySync* syncParam); int PS4_SYSV_ABI sceSaveDataTerminate(); int PS4_SYSV_ABI sceSaveDataTransferringMount(); int PS4_SYSV_ABI sceSaveDataUmount(const OrbisSaveDataMountPoint* mountPoint); int PS4_SYSV_ABI sceSaveDataUmountSys(); -int PS4_SYSV_ABI sceSaveDataUmountWithBackup(); +int PS4_SYSV_ABI sceSaveDataUmountWithBackup(const OrbisSaveDataMountPoint* mountPoint); int PS4_SYSV_ABI sceSaveDataUnregisterEventCallback(); int PS4_SYSV_ABI sceSaveDataUpload(); int PS4_SYSV_ABI Func_02E4C4D201716422(); diff --git a/src/emulator.cpp b/src/emulator.cpp index c16e5b3f..596c526b 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -85,6 +85,9 @@ void Emulator::Run(const std::filesystem::path& file) { } mnt->Mount(mount_data_dir, "/data"); // should just exist, manually create with game serial const auto& mount_temp_dir = Common::FS::GetUserPath(Common::FS::PathType::TempDataDir) / id; + if (!std::filesystem::exists(mount_temp_dir)) { + std::filesystem::create_directory(mount_temp_dir); + } mnt->Mount(mount_temp_dir, "/temp0"); // called in app_content ==> stat/mkdir // Initialize kernel and library facilities. From c2c55fea87f3e569c3b1776090812267461c889e Mon Sep 17 00:00:00 2001 From: raziel1000 Date: Thu, 4 Jul 2024 01:53:06 -0600 Subject: [PATCH 05/13] mr clang format --- src/core/libraries/save_data/savedata.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/libraries/save_data/savedata.h b/src/core/libraries/save_data/savedata.h index dbfbd320..f342d0dd 100644 --- a/src/core/libraries/save_data/savedata.h +++ b/src/core/libraries/save_data/savedata.h @@ -240,7 +240,6 @@ struct OrbisSaveDataMemorySync { u32 slotId; OrbisSaveDataMemorySyncOption option; u8 reserved[28]; - }; int PS4_SYSV_ABI sceSaveDataAbort(); From 1968b2aa81a85e473bfed69894860455a80983ac Mon Sep 17 00:00:00 2001 From: raziel1000 Date: Thu, 4 Jul 2024 01:54:50 -0600 Subject: [PATCH 06/13] ... --- src/core/libraries/kernel/file_system.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index b58555d5..718da18f 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -227,7 +227,7 @@ int PS4_SYSV_ABI sceKernelMkdir(const char* path, u16 mode) { return SCE_KERNEL_ERROR_EEXIST; } - //CUSA02456: path = /aotl after sceSaveDataMount(mode = 1) + // CUSA02456: path = /aotl after sceSaveDataMount(mode = 1) if (dir_name.empty() || !std::filesystem::create_directory(dir_name)) { return SCE_KERNEL_ERROR_EIO; } From e22ad65e70bcc17190738ca594dcd258707bfaa3 Mon Sep 17 00:00:00 2001 From: raziel1000 Date: Thu, 4 Jul 2024 01:57:03 -0600 Subject: [PATCH 07/13] .... --- src/core/file_sys/fs.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/core/file_sys/fs.cpp b/src/core/file_sys/fs.cpp index a1c03d89..40b0bcc5 100644 --- a/src/core/file_sys/fs.cpp +++ b/src/core/file_sys/fs.cpp @@ -19,9 +19,8 @@ void MntPoints::Mount(const std::filesystem::path& host_folder, const std::strin } void MntPoints::Unmount(const std::filesystem::path& host_folder, const std::string& guest_folder) { - auto it = std::remove_if(m_mnt_pairs.begin(), m_mnt_pairs.end(), [&](const MntPair& pair) { - return pair.guest_path == guest_folder; - }); + auto it = std::remove_if(m_mnt_pairs.begin(), m_mnt_pairs.end(), + [&](const MntPair& pair) { return pair.guest_path == guest_folder; }); m_mnt_pairs.erase(it, m_mnt_pairs.end()); } From bdcadf63d23c7bc219f54c0ae7a0f6be2443fdbf Mon Sep 17 00:00:00 2001 From: raziel1000 Date: Thu, 4 Jul 2024 02:22:43 -0600 Subject: [PATCH 08/13] scePthreadSetprio, scePthreadGetprio --- src/core/libraries/kernel/thread_management.cpp | 11 +++++++++++ src/core/libraries/kernel/thread_management.h | 1 + 2 files changed, 12 insertions(+) diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 3492cad4..5cbf2eaf 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -1289,6 +1289,15 @@ int PS4_SYSV_ABI scePthreadGetthreadid() { return (int)(size_t)g_pthread_self; } +int PS4_SYSV_ABI scePthreadGetprio(ScePthread thread, int* prio) { + *prio = thread->prio; + return ORBIS_OK; +} +int PS4_SYSV_ABI scePthreadSetprio(ScePthread thread, int prio) { + thread->prio = prio; + return ORBIS_OK; +} + void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("lZzFeSxPl08", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_setcancelstate); LIB_FUNCTION("0TyVk4MSLt0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_init); @@ -1310,6 +1319,8 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("7Xl257M4VNI", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_equal); LIB_FUNCTION("h9CcP3J0oVM", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_join); LIB_FUNCTION("EI-5-jlq2dE", "libkernel", 1, "libkernel", 1, 1, scePthreadGetthreadid); + LIB_FUNCTION("1tKyG7RlMJo", "libkernel", 1, "libkernel", 1, 1, scePthreadGetprio); + LIB_FUNCTION("W0Hpm2X0uPE", "libkernel", 1, "libkernel", 1, 1, scePthreadSetprio); LIB_FUNCTION("aI+OeCz8xrQ", "libkernel", 1, "libkernel", 1, 1, scePthreadSelf); LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self); diff --git a/src/core/libraries/kernel/thread_management.h b/src/core/libraries/kernel/thread_management.h index f578355d..9926b379 100644 --- a/src/core/libraries/kernel/thread_management.h +++ b/src/core/libraries/kernel/thread_management.h @@ -58,6 +58,7 @@ struct PthreadInternal { std::atomic_bool is_free; using Destructor = std::pair; std::vector key_destructors; + int prio; }; struct PthreadAttrInternal { From 8d17f87a08618afc9cf91d98eef2eb35b0f6eabf Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 4 Jul 2024 11:38:23 +0300 Subject: [PATCH 09/13] improved file not found return in sceKernelOpen --- src/core/libraries/kernel/file_system.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 718da18f..3c5c0ac9 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -90,7 +90,11 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { } if (!file->f.IsOpen()) { h->DeleteHandle(handle); - return SCE_KERNEL_ERROR_EACCES; + if (create) { + return ORBIS_KERNEL_ERROR_EACCES; + } else { + return ORBIS_KERNEL_ERROR_ENOENT; + } } } file->is_opened = true; From fd39c50910941b03492609196b5fdc5304485539 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 4 Jul 2024 13:49:11 +0300 Subject: [PATCH 10/13] improved sceAppContentAppParamGetInt --- src/core/libraries/app_content/app_content.cpp | 15 ++++++++++++--- src/core/libraries/error_codes.h | 3 +++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/core/libraries/app_content/app_content.cpp b/src/core/libraries/app_content/app_content.cpp index c43d6c39..aadc368f 100644 --- a/src/core/libraries/app_content/app_content.cpp +++ b/src/core/libraries/app_content/app_content.cpp @@ -52,7 +52,7 @@ int PS4_SYSV_ABI sceAppContentAddcontUnmount() { int PS4_SYSV_ABI sceAppContentAppParamGetInt(OrbisAppContentAppParamId paramId, s32* value) { if (value == nullptr) - return 0x80D90002; + return ORBIS_APP_CONTENT_ERROR_PARAMETER; auto* param_sfo = Common::Singleton::Instance(); switch (paramId) { case ORBIS_APP_CONTENT_APPPARAM_ID_SKU_FLAG: @@ -70,9 +70,18 @@ int PS4_SYSV_ABI sceAppContentAppParamGetInt(OrbisAppContentAppParamId paramId, case ORBIS_APP_CONTENT_APPPARAM_ID_USER_DEFINED_PARAM_4: *value = param_sfo->GetInteger("USER_DEFINED_PARAM_4"); break; + default: + LOG_ERROR(Lib_AppContent, " paramId = {}, value = {} paramId is not valid", paramId, + *value); + return ORBIS_APP_CONTENT_ERROR_PARAMETER; } - LOG_ERROR(Lib_AppContent, " paramId = {}, value = {}", paramId, *value); - return *value == -1 ? 0x80D90005 : ORBIS_OK; + if (*value == -1) { + LOG_ERROR(Lib_AppContent, + " paramId = {}, value = {} value is not valid can't read param.sfo?", paramId, + *value); + return ORBIS_APP_CONTENT_ERROR_PARAMETER; + } + return ORBIS_OK; } int PS4_SYSV_ABI sceAppContentAppParamGetString() { diff --git a/src/core/libraries/error_codes.h b/src/core/libraries/error_codes.h index c7732ad5..63016213 100644 --- a/src/core/libraries/error_codes.h +++ b/src/core/libraries/error_codes.h @@ -453,3 +453,6 @@ constexpr int ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE = 0x80551608; constexpr int ORBIS_NP_TROPHY_ERROR_HANDLE_EXCEEDS_MAX = 0x80551624; constexpr int ORBIS_NP_TROPHY_ERROR_CONTEXT_ALREADY_EXISTS = 0x80551613; constexpr int ORBIS_NP_TROPHY_ERROR_CONTEXT_EXCEEDS_MAX = 0x80551622; + +// AppContent library +constexpr int ORBIS_APP_CONTENT_ERROR_PARAMETER = 0x80D90002; From a91c049754132ca0055238c160881c595949b101 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 4 Jul 2024 14:30:34 +0300 Subject: [PATCH 11/13] added library to print system info to be able to debug user files better --- .gitmodules | 3 +++ CMakeLists.txt | 2 +- externals/CMakeLists.txt | 3 +++ externals/hwinfo | 1 + src/emulator.cpp | 17 +++++++++++++++++ src/emulator.h | 1 + 6 files changed, 26 insertions(+), 1 deletion(-) create mode 160000 externals/hwinfo diff --git a/.gitmodules b/.gitmodules index d6965722..4dfb37c7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -58,3 +58,6 @@ [submodule "externals/tracy"] path = externals/tracy url = https://github.com/shadps4-emu/tracy.git +[submodule "externals/hwinfo"] + path = externals/hwinfo + url = https://github.com/shadps4-emu/ext-hwinfo.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 6724bff9..da3ba430 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -541,7 +541,7 @@ endif() create_target_directory_groups(shadps4) -target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient) +target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient hwinfo::HWinfo) target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::SPIRV glslang::glslang SDL3::SDL3) if (NOT ENABLE_QT_GUI) diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index ca9c6747..ceec21c0 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -140,3 +140,6 @@ option(TRACY_ON_DEMAND "" ON) option(TRACY_NO_FRAME_IMAGE "" ON) option(TRACY_FIBERS "" ON) # For AmdGpu frontend profiling add_subdirectory(tracy) + +# hwinfo +add_subdirectory(hwinfo) \ No newline at end of file diff --git a/externals/hwinfo b/externals/hwinfo new file mode 160000 index 00000000..81ea6332 --- /dev/null +++ b/externals/hwinfo @@ -0,0 +1 @@ +Subproject commit 81ea6332fd4839890b1904f9668865145450f8da diff --git a/src/emulator.cpp b/src/emulator.cpp index 596c526b..303accf3 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -15,12 +15,14 @@ #include "common/logging/backend.h" #include "common/path_util.h" #include "common/singleton.h" +#include "common/version.h" #include "core/file_sys/fs.h" #include "core/libraries/kernel/thread_management.h" #include "core/libraries/libs.h" #include "core/linker.h" #include "core/memory.h" #include "emulator.h" +#include "hwinfo/hwinfo.h" Frontend::WindowSDL* g_window = nullptr; @@ -40,6 +42,8 @@ Emulator::Emulator() // Start logger. Common::Log::Initialize(); Common::Log::Start(); + LOG_INFO(Loader, "Starting shadps4 emulator v{} ", Common::VERSION); + PrintSystemInfo(); } Emulator::~Emulator() { @@ -177,4 +181,17 @@ void Emulator::LoadSystemModules(const std::filesystem::path& file) { } } +void Emulator::PrintSystemInfo() { + auto cpus = hwinfo::getAllCPUs(); + for (const auto& cpu : cpus) { + LOG_INFO(Loader, "CPU #{} {}", cpu.id(), cpu.modelName()); + } + hwinfo::OS os; + LOG_INFO(Loader, "{}", os.name()); + auto gpus = hwinfo::getAllGPUs(); + for (auto& gpu : gpus) { + LOG_INFO(Loader, "GPU #{} {}", gpu.id(), gpu.name()); + } +} + } // namespace Core diff --git a/src/emulator.h b/src/emulator.h index b61ce95e..fce612dc 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -29,6 +29,7 @@ public: private: void LoadSystemModules(const std::filesystem::path& file); + void PrintSystemInfo(); Core::MemoryManager* memory; Input::GameController* controller = Common::Singleton::Instance(); From 724869e0880c2f574f05b4edb02a3e79554281e8 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 4 Jul 2024 14:31:58 +0300 Subject: [PATCH 12/13] fixed submodule --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 4dfb37c7..5733f4fe 100644 --- a/.gitmodules +++ b/.gitmodules @@ -60,4 +60,4 @@ url = https://github.com/shadps4-emu/tracy.git [submodule "externals/hwinfo"] path = externals/hwinfo - url = https://github.com/shadps4-emu/ext-hwinfo.git + url = https://github.com/lfreist/hwinfo.git From 7ea87f69ea2c9a7de6a8e5ab0155d2d7ce0a2e24 Mon Sep 17 00:00:00 2001 From: raziel1000 Date: Thu, 4 Jul 2024 21:02:59 -0600 Subject: [PATCH 13/13] forgot duplicate. --- src/core/libraries/save_data/savedata.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index 2cc80323..3f470e67 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -438,9 +438,7 @@ s32 saveDataMount(u32 user_id, char* dir_name, u32 mount_mode, case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF | - ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: - case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | - ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF: { + ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: { auto* mnt = Common::Singleton::Instance(); if (std::filesystem::exists(mount_dir)) { std::strncpy(mount_result->mount_point.data, g_mount_point.c_str(), 16);