diff --git a/src/core/libraries/kernel/event_flag/event_flag.cpp b/src/core/libraries/kernel/event_flag/event_flag.cpp index 659d3cd7..0ca95768 100644 --- a/src/core/libraries/kernel/event_flag/event_flag.cpp +++ b/src/core/libraries/kernel/event_flag/event_flag.cpp @@ -48,6 +48,8 @@ int PS4_SYSV_ABI sceKernelCreateEventFlag(OrbisKernelEventFlag* ef, const char* case 0x20: thread_mode = EventFlagInternal::ThreadMode::Multi; break; + case 0x00: + break; default: UNREACHABLE(); } diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 42cb2cbb..1216d61c 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -634,6 +634,35 @@ int PS4_SYSV_ABI scePthreadCondBroadcast(ScePthreadCond* cond) { return (result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL); } +int PS4_SYSV_ABI scePthreadCondTimedwait(ScePthreadCond* cond, ScePthreadMutex* mutex, u64 usec) { + cond = static_cast(createCond(cond)); + if (cond == nullptr) { + return SCE_KERNEL_ERROR_EINVAL; + } + if (mutex == nullptr || *mutex == nullptr) { + return SCE_KERNEL_ERROR_EINVAL; + } + timespec time{}; + time.tv_sec = usec / 1000000; + time.tv_nsec = ((usec % 1000000) * 1000); + int result = pthread_cond_timedwait(&(*cond)->cond, &(*mutex)->pth_mutex, &time); + + LOG_INFO(Kernel_Pthread, "scePthreadCondTimedwait, result={}", result); + + switch (result) { + case 0: + return SCE_OK; + case ETIMEDOUT: + return SCE_KERNEL_ERROR_ETIMEDOUT; + case EINTR: + return SCE_KERNEL_ERROR_EINTR; + case EAGAIN: + return SCE_KERNEL_ERROR_EAGAIN; + default: + return SCE_KERNEL_ERROR_EINVAL; + } +} + int PS4_SYSV_ABI posix_pthread_mutex_init(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr) { // LOG_INFO(Kernel_Pthread, "posix pthread_mutex_init redirect to scePthreadMutexInit"); int result = scePthreadMutexInit(mutex, attr, nullptr); @@ -1029,6 +1058,7 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("WKAXJ4XBPQ4", "libkernel", 1, "libkernel", 1, 1, scePthreadCondWait); LIB_FUNCTION("waPcxYiR3WA", "libkernel", 1, "libkernel", 1, 1, scePthreadCondattrDestroy); LIB_FUNCTION("kDh-NfxgMtE", "libkernel", 1, "libkernel", 1, 1, scePthreadCondSignal); + LIB_FUNCTION("BmMjYxmew1w", "libkernel", 1, "libkernel", 1, 1, scePthreadCondTimedwait); // posix calls LIB_FUNCTION("ttHNfU+qDBU", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_init); LIB_FUNCTION("7H0iTOciTLo", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_lock); diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index e63f9c1d..d3e585c0 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -331,22 +331,14 @@ int PS4_SYSV_ABI sceSaveDataLoadIcon() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataMount() { - LOG_ERROR(Lib_SaveData, "(STUBBED) called"); - return ORBIS_OK; -} - -s32 PS4_SYSV_ABI sceSaveDataMount2(const OrbisSaveDataMount2* mount, - OrbisSaveDataMountResult* mount_result) { - LOG_INFO(Lib_SaveData, "called user_id = {} dir_name = {} blocks = {} mount_mode = {}", - mount->user_id, mount->dir_name->data, mount->blocks, mount->mount_mode); +s32 saveDataMount(u32 user_id, std::string 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(mount->user_id) / "savedata" / id / - std::string(mount->dir_name->data); - switch (mount->mount_mode) { + std::to_string(user_id) / "savedata" / id / dir_name; + switch (mount_mode) { case ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY: case ORBIS_SAVE_DATA_MOUNT_MODE_RDWR: { if (!std::filesystem::exists(mount_dir)) { @@ -372,6 +364,18 @@ s32 PS4_SYSV_ABI sceSaveDataMount2(const OrbisSaveDataMount2* mount, mount_result->mount_status = 1; strncpy(mount_result->mount_point.data, g_mount_point.c_str(), 16); } break; + case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE2 | ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | + ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: { + if (!std::filesystem::exists(mount_dir)) { + 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(); } @@ -380,6 +384,28 @@ s32 PS4_SYSV_ABI sceSaveDataMount2(const OrbisSaveDataMount2* mount, return ORBIS_OK; } +s32 PS4_SYSV_ABI sceSaveDataMount(const OrbisSaveDataMount* mount, + OrbisSaveDataMountResult* mount_result) { + if (mount == nullptr) { + return ORBIS_SAVE_DATA_ERROR_PARAMETER; + } + LOG_INFO(Lib_SaveData, "called: mount = {}, 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, + mount_result); +} + +s32 PS4_SYSV_ABI sceSaveDataMount2(const OrbisSaveDataMount2* mount, + OrbisSaveDataMountResult* mount_result) { + if (mount == nullptr) { + return ORBIS_SAVE_DATA_ERROR_PARAMETER; + } + LOG_INFO(Lib_SaveData, "called: mount = {}, 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, + mount_result); +} + int PS4_SYSV_ABI sceSaveDataMount5() { LOG_ERROR(Lib_SaveData, "(STUBBED) called"); return ORBIS_OK; diff --git a/src/core/libraries/save_data/savedata.h b/src/core/libraries/save_data/savedata.h index a4541587..60f99cea 100644 --- a/src/core/libraries/save_data/savedata.h +++ b/src/core/libraries/save_data/savedata.h @@ -42,6 +42,30 @@ struct OrbisSaveDataMountResult { s32 unk1; }; +constexpr int ORBIS_SAVE_DATA_TITLE_ID_DATA_SIZE = 10; +typedef 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 { + char data[ORBIS_SAVE_DATA_FINGERPRINT_DATA_SIZE]; + char padding[15]; +} OrbisSaveDataFingerprint; + +typedef struct OrbisSaveDataMount { + s32 user_id; + s32 pad; + const OrbisSaveDataTitleId* titleId; + const OrbisSaveDataDirName* dir_name; + const OrbisSaveDataFingerprint* fingerprint; + u64 blocks; + u32 mount_mode; + u8 reserved[32]; +} OrbisSaveDataMount; + // savedataMount2 mountModes (ORed values) constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY = 1; constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_RDWR = 2; @@ -113,7 +137,8 @@ int PS4_SYSV_ABI sceSaveDataInitializeForCdlg(); int PS4_SYSV_ABI sceSaveDataIsDeletingUsbDb(); int PS4_SYSV_ABI sceSaveDataIsMounted(); int PS4_SYSV_ABI sceSaveDataLoadIcon(); -int PS4_SYSV_ABI sceSaveDataMount(); +int PS4_SYSV_ABI sceSaveDataMount(const OrbisSaveDataMount* mount, + OrbisSaveDataMountResult* mount_result); s32 PS4_SYSV_ABI sceSaveDataMount2(const OrbisSaveDataMount2* mount, OrbisSaveDataMountResult* mount_result); int PS4_SYSV_ABI sceSaveDataMount5();