diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index a2dfcbc1..5176fb0d 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -82,6 +82,15 @@ size_t PS4_SYSV_ABI sceKernelWrite(int d, void* buf, size_t nbytes) { if (buf == nullptr) { return SCE_KERNEL_ERROR_EFAULT; } + if (d == 1) { + // temp, just to print the message. not a file? + // CUSA00402 - Crimsonland and probably other games. + char* msg = reinterpret_cast(buf); + size_t length = std::strlen(msg); + LOG_INFO(Kernel_Fs, "sceKernelWrite fd = 1, str = {}, length = {}", msg, length); + return length; + } + auto* h = Common::Singleton::Instance(); auto* file = h->GetFile(d); if (file == nullptr) { @@ -159,7 +168,12 @@ int PS4_SYSV_ABI sceKernelMkdir(const char* path, u16 mode) { return SCE_KERNEL_ERROR_EEXIST; } - if (!std::filesystem::create_directory(dir_name)) { + if (!std::filesystem::create_directories(dir_name)) { + // check me on saveDataMount. + // CUSA02456: calls sceSaveDataMount then mkdir + // CUSA00402: calls mkdir first before sceSaveDataMount + // maybe consider mounting save data at emu start? (added in main) + return SCE_KERNEL_ERROR_EIO; } diff --git a/src/core/libraries/kernel/libkernel.cpp b/src/core/libraries/kernel/libkernel.cpp index a621e4b7..b22da842 100644 --- a/src/core/libraries/kernel/libkernel.cpp +++ b/src/core/libraries/kernel/libkernel.cpp @@ -23,6 +23,7 @@ #include #else #include +#include #endif #include @@ -217,6 +218,18 @@ int PS4_SYSV_ABI sceKernelGetCpumode() { return SCE_KERNEL_CPUMODE_7CPU_NORMAL; } +int PS4_SYSV_ABI scePthreadGetthreadid() { +#ifdef _WIN64 + return GetCurrentProcessId(); +#else + return getpid(); +#endif +} + +int PS4_SYSV_ABI posix_getpid() { + return scePthreadGetthreadid(); +} + void LibKernel_Register(Core::Loader::SymbolsResolver* sym) { // obj LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard); @@ -250,6 +263,8 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("DRuBt2pvICk", "libkernel", 1, "libkernel", 1, 1, ps4__read); LIB_FUNCTION("k+AXqu2-eBc", "libScePosix", 1, "libkernel", 1, 1, posix_getpagesize); LIB_FUNCTION("VOx8NGmHXTs", "libkernel", 1, "libkernel", 1, 1, sceKernelGetCpumode); + LIB_FUNCTION("EI-5-jlq2dE", "libkernel", 1, "libkernel", 1, 1, scePthreadGetthreadid); + LIB_FUNCTION("HoLVWNanBBc", "libScePosix", 1, "libkernel", 1, 1, posix_getpid); Libraries::Kernel::fileSystemSymbolsRegister(sym); Libraries::Kernel::timeSymbolsRegister(sym); diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 198eac55..f8c0485e 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -177,6 +177,22 @@ int PS4_SYSV_ABI scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachst return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL; } +int PS4_SYSV_ABI posix_pthread_attr_setdetachstate(ScePthreadAttr* attr, int detachstate) { + int result = scePthreadAttrSetdetachstate(attr, detachstate); + if (result < 0) { + UNREACHABLE(); + } + return result; +} + +int PS4_SYSV_ABI posix_pthread_attr_destroy(ScePthreadAttr* attr) { + int result = scePthreadAttrDestroy(attr); + if (result < 0) { + UNREACHABLE(); + } + return result; +} + int PS4_SYSV_ABI scePthreadAttrSetinheritsched(ScePthreadAttr* attr, int inheritSched) { if (attr == nullptr || *attr == nullptr) { return SCE_KERNEL_ERROR_EINVAL; @@ -899,7 +915,13 @@ void PS4_SYSV_ABI scePthreadYield() { } int PS4_SYSV_ABI scePthreadDetach(ScePthread thread) { - LOG_INFO(Kernel_Pthread, "thread create name = {}", thread->name); + LOG_INFO(Kernel_Pthread, "thread detach name = {}", thread->name); + thread->is_detached = true; + return ORBIS_OK; +} + +int PS4_SYSV_ABI posix_pthread_detach(ScePthread thread) { + LOG_INFO(Kernel_Pthread, "thread detach name = {}", thread->name); thread->is_detached = true; return ORBIS_OK; } @@ -965,6 +987,31 @@ int PS4_SYSV_ABI posix_pthread_setspecific(pthread_key_t key, void* ptr) { } } +int PS4_SYSV_ABI scePthreadSetschedparam(ScePthread thread, int policy, + const SceKernelSchedParam* param) { + int ppolicy; + if (policy != SCHED_OTHER) + ppolicy = SCHED_OTHER; + int result = pthread_setschedparam(thread->pth, ppolicy, param); + // 0 only on win? + LOG_INFO(Kernel_Pthread, "Todo? scePthreadSetschedparam: policy = {}, result = {}", policy, + result); + return result; +} + +int PS4_SYSV_ABI posix_pthread_setschedparam(ScePthread thread, int policy, + const SceKernelSchedParam* param) { + int result = scePthreadSetschedparam(thread, policy, param); + LOG_INFO(Kernel_Pthread, "Todo? posix_pthread_setschedparam: policy = {}, result = {}", policy, + result); + return result; +} + +int PS4_SYSV_ABI posix_sched_get_priority_max(int algo) { + LOG_INFO(Kernel_Pthread, "posix_sched_get_priority_max: algo = {}", algo); + return SCE_KERNEL_PRIO_FIFO_HIGHEST; +} + int PS4_SYSV_ABI scePthreadCondSignal(ScePthreadCond* cond) { if (cond == nullptr) { return SCE_KERNEL_ERROR_EINVAL; @@ -1381,6 +1428,9 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("8+s5BzZjxSg", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrGetaffinity); LIB_FUNCTION("x1X76arYMxU", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrGet); LIB_FUNCTION("UTXzJbWhhTE", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetstacksize); + LIB_FUNCTION("E+tyo3lp5Lw", "libScePosix", 1, "libkernel", 1, 1, + posix_pthread_attr_setdetachstate); + LIB_FUNCTION("zHchY8ft5pk", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_attr_destroy); LIB_FUNCTION("4qGrR6eoP9Y", "libkernel", 1, "libkernel", 1, 1, scePthreadDetach); LIB_FUNCTION("3PtV6p3QNX4", "libkernel", 1, "libkernel", 1, 1, scePthreadEqual); @@ -1391,9 +1441,13 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("6UgtwV+0zb4", "libkernel", 1, "libkernel", 1, 1, scePthreadCreate); LIB_FUNCTION("T72hz6ffq08", "libkernel", 1, "libkernel", 1, 1, scePthreadYield); LIB_FUNCTION("geDaqgH9lTg", "libkernel", 1, "libkernel", 1, 1, scePthreadKeyCreate); + LIB_FUNCTION("oIRFTjoILbg", "libkernel", 1, "libkernel", 1, 1, scePthreadSetschedparam); LIB_FUNCTION("mqULNdimTn0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_key_create); LIB_FUNCTION("mqULNdimTn0", "libkernel", 1, "libkernel", 1, 1, posix_pthread_key_create); LIB_FUNCTION("WrOLvHU0yQM", "libkernel", 1, "libkernel", 1, 1, posix_pthread_setspecific); + LIB_FUNCTION("Xs9hdiD7sAA", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_setschedparam); + LIB_FUNCTION("CBNtXOoef-E", "libScePosix", 1, "libkernel", 1, 1, posix_sched_get_priority_max); + LIB_FUNCTION("+U1R4WtXvoc", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_detach); // mutex calls LIB_FUNCTION("cmo1RIYva9o", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexInit); diff --git a/src/core/libraries/kernel/thread_management.h b/src/core/libraries/kernel/thread_management.h index 64bb2d65..81151b2d 100644 --- a/src/core/libraries/kernel/thread_management.h +++ b/src/core/libraries/kernel/thread_management.h @@ -17,6 +17,13 @@ class SymbolsResolver; namespace Libraries::Kernel { +/* sceKernelSchedGetPriorityMax/Min */ +constexpr int SCE_KERNEL_SCHED_FIFO = SCHED_FIFO; +constexpr int SCE_KERNEL_SCHED_RR = SCHED_RR; +constexpr int SCE_KERNEL_PRIO_FIFO_DEFAULT = 700; +constexpr int SCE_KERNEL_PRIO_FIFO_HIGHEST = 256; +constexpr int SCE_KERNEL_PRIO_FIFO_LOWEST = 767; + struct PthreadInternal; struct PthreadAttrInternal; struct PthreadMutexInternal; diff --git a/src/core/libraries/save_data/error_codes.h b/src/core/libraries/save_data/error_codes.h index 0dfe9def..18bff912 100644 --- a/src/core/libraries/save_data/error_codes.h +++ b/src/core/libraries/save_data/error_codes.h @@ -4,5 +4,7 @@ #pragma once constexpr int ORBIS_SAVE_DATA_ERROR_PARAMETER = 0x809f0000; +constexpr int ORBIS_SAVE_DATA_ERROR_NOT_INITIALIZED = + 0x809f0001; // save data library not initialized yet 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 e63f9c1d..d2386e47 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -13,7 +13,7 @@ #include "error_codes.h" namespace Libraries::SaveData { - +static bool initialized = false; static std::string g_mount_point = "/savedata0"; // temp mount point (todo) int PS4_SYSV_ABI sceSaveDataAbort() { @@ -241,8 +241,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(OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataMountInfo* info) { + LOG_ERROR(Lib_SaveData, "(STUBBED) called, mount = {}", mountPoint->data); + info->blocks = 100000; + info->freeBlocks = 100000; return ORBIS_OK; } @@ -296,17 +299,20 @@ int PS4_SYSV_ABI sceSaveDataGetUpdatedDataCount() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataInitialize() { +int PS4_SYSV_ABI sceSaveDataInitialize(const OrbisSaveDataInitParams* initParam) { + initialized = true; // todo. LOG_ERROR(Lib_SaveData, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataInitialize2() { +int PS4_SYSV_ABI sceSaveDataInitialize2(const OrbisSaveDataInitParams* initParam) { + initialized = true; // todo. LOG_ERROR(Lib_SaveData, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceSaveDataInitialize3() { +int PS4_SYSV_ABI sceSaveDataInitialize3(const OrbisSaveDataInitParams* initParam) { + initialized = true; // todo. LOG_ERROR(Lib_SaveData, "(DUMMY) called"); return ORBIS_OK; } @@ -331,32 +337,25 @@ 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)) { - return ORBIS_SAVE_DATA_ERROR_NOT_FOUND; + if (!initialized /* !std::filesystem::exists(mount_dir)*/) { + // check this. example: CUSA02456 + return ORBIS_SAVE_DATA_ERROR_NOT_INITIALIZED; } 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); + LOG_ERROR(Lib_SaveData, "mount = {}", mount_result->mount_point.data); } 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 | @@ -372,6 +371,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 +391,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..27ff0ebc 100644 --- a/src/core/libraries/save_data/savedata.h +++ b/src/core/libraries/save_data/savedata.h @@ -29,6 +29,30 @@ struct OrbisSaveDataMount2 { s32 unk2; }; +constexpr int SCE_SAVE_DATA_TITLE_ID_DATA_SIZE = 10; +typedef struct OrbisSaveDataTitleId { + char data[SCE_SAVE_DATA_TITLE_ID_DATA_SIZE]; + char padding[6]; + +} OrbisSaveDataTitleId; + +constexpr int SCE_SAVE_DATA_FINGERPRINT_DATA_SIZE = 65; +typedef struct OrbisSaveDataFingerprint { + char data[SCE_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; + struct OrbisSaveDataMountPoint { char data[ORBIS_SAVE_DATA_MOUNT_POINT_DATA_MAXSIZE]; }; @@ -42,6 +66,14 @@ struct OrbisSaveDataMountResult { s32 unk1; }; +typedef struct OrbisSaveDataMountInfo { + u64 blocks; // total num of blocks + u64 freeBlocks; // free num of blocks + uint8_t reserved[32]; +} OrbisSaveDataMountInfo; + +typedef struct _OrbisSaveDataInitParams OrbisSaveDataInitParams; + // savedataMount2 mountModes (ORed values) constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY = 1; constexpr int ORBIS_SAVE_DATA_MOUNT_MODE_RDWR = 2; @@ -95,7 +127,8 @@ int PS4_SYSV_ABI sceSaveDataGetEventInfo(); int PS4_SYSV_ABI sceSaveDataGetEventResult(); int PS4_SYSV_ABI sceSaveDataGetFormat(); int PS4_SYSV_ABI sceSaveDataGetMountedSaveDataCount(); -int PS4_SYSV_ABI sceSaveDataGetMountInfo(); +int PS4_SYSV_ABI sceSaveDataGetMountInfo(OrbisSaveDataMountPoint* mountPoint, + OrbisSaveDataMountInfo* info); int PS4_SYSV_ABI sceSaveDataGetParam(); int PS4_SYSV_ABI sceSaveDataGetProgress(); int PS4_SYSV_ABI sceSaveDataGetSaveDataCount(); @@ -106,14 +139,15 @@ int PS4_SYSV_ABI sceSaveDataGetSaveDataRootPath(); int PS4_SYSV_ABI sceSaveDataGetSaveDataRootUsbPath(); int PS4_SYSV_ABI sceSaveDataGetSavePoint(); int PS4_SYSV_ABI sceSaveDataGetUpdatedDataCount(); -int PS4_SYSV_ABI sceSaveDataInitialize(); -int PS4_SYSV_ABI sceSaveDataInitialize2(); -int PS4_SYSV_ABI sceSaveDataInitialize3(); +int PS4_SYSV_ABI sceSaveDataInitialize(const OrbisSaveDataInitParams* initParam); +int PS4_SYSV_ABI sceSaveDataInitialize2(const OrbisSaveDataInitParams* initParam); +int PS4_SYSV_ABI sceSaveDataInitialize3(const OrbisSaveDataInitParams* initParam); 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(); diff --git a/src/main.cpp b/src/main.cpp index 2a7f839e..11376c45 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -63,6 +63,13 @@ int main(int argc, char* argv[]) { u32 fw_version = param_sfo->GetInteger("SYSTEM_VER"); std::string app_version = param_sfo->GetString("APP_VER"); LOG_INFO(Loader, "Fw: {:#x} App Version: {}", fw_version, app_version); + + // Just testing for now. + // Working fine, one case only so far (CUSA00402 - Crimsonland) + const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / + "1" / "savedata" / id; + mnt->Mount(mount_dir, "/savedata0"); + } else if (entry.path().filename() == "pic0.png" || entry.path().filename() == "pic1.png") { auto* splash = Common::Singleton::Instance();