diff --git a/CMakeLists.txt b/CMakeLists.txt index c1a9e29a..9306f1a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -175,6 +175,8 @@ set(LIBC_SOURCES src/core/libraries/libc/libc.cpp src/core/libraries/libc/libc_string.h src/core/libraries/libc/libc_stdlib.cpp src/core/libraries/libc/libc_stdlib.h + src/core/libraries/libc_internal/libc_internal.cpp + src/core/libraries/libc_internal/libc_internal.h ) set(PAD_LIB src/core/libraries/pad/pad.cpp diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 75064a21..a86c5ac8 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -100,6 +100,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { SUB(Lib, NpScore) \ SUB(Lib, NpTrophy) \ SUB(Lib, Screenshot) \ + SUB(Lib, LibCInternal) \ CLS(Frontend) \ CLS(Render) \ SUB(Render, Vulkan) \ diff --git a/src/common/logging/types.h b/src/common/logging/types.h index d18612c2..908cecd9 100644 --- a/src/common/logging/types.h +++ b/src/common/logging/types.h @@ -67,6 +67,7 @@ enum class Class : u8 { Lib_NpScore, ///< The LibSceNpScore implementation Lib_NpTrophy, ///< The LibSceNpTrophy implementation Lib_Screenshot, ///< The LibSceScreenshot implementation + Lib_LibCInternal, ///< The LibCInternal implementation. Frontend, ///< Emulator UI Render, ///< Video Core Render_Vulkan, ///< Vulkan backend diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index d82c8730..35ac4448 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -36,6 +36,7 @@ static auto UserPaths = [] { create_path(PathType::ScreenshotsDir, user_dir / SCREENSHOTS_DIR); create_path(PathType::ShaderDir, user_dir / SHADER_DIR); create_path(PathType::SaveDataDir, user_dir / SAVEDATA_DIR); + create_path(PathType::SysModuleDir, user_dir / SYSMODULES_DIR); return paths; }(); diff --git a/src/common/path_util.h b/src/common/path_util.h index 618d0bda..ea457040 100644 --- a/src/common/path_util.h +++ b/src/common/path_util.h @@ -14,6 +14,7 @@ enum class PathType { ScreenshotsDir, // Where screenshots are stored. ShaderDir, // Where shaders are stored. SaveDataDir, // Where guest save data is stored. + SysModuleDir, // Where system modules are stored. }; constexpr auto PORTABLE_DIR = "user"; @@ -23,6 +24,7 @@ constexpr auto LOG_DIR = "log"; constexpr auto SCREENSHOTS_DIR = "screenshots"; constexpr auto SHADER_DIR = "shader"; constexpr auto SAVEDATA_DIR = "savedata"; +constexpr auto SYSMODULES_DIR = "sys_modules"; // Filenames constexpr auto LOG_FILE = "shad_log.txt"; diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 92d4e92e..95f7b35b 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -899,6 +899,94 @@ int PS4_SYSV_ABI scePthreadDetach(ScePthread thread) { return ORBIS_OK; } +ScePthread PS4_SYSV_ABI pthread_self() { + return g_pthread_self; +} + +int PS4_SYSV_ABI scePthreadCondSignal(ScePthreadCond* cond) { + if (cond == nullptr) { + return SCE_KERNEL_ERROR_EINVAL; + } + + int result = pthread_cond_signal(&(*cond)->cond); + + LOG_INFO(Kernel_Pthread, "scePthreadCondSignal, result={}", result); + + switch (result) { + case 0: + return SCE_OK; + case EBUSY: + return SCE_KERNEL_ERROR_EBUSY; + default: + return SCE_KERNEL_ERROR_EINVAL; + } +} + +int PS4_SYSV_ABI scePthreadCondWait(ScePthreadCond* cond, ScePthreadMutex* mutex) { + if (cond == nullptr || *cond == nullptr) { + // return SCE_KERNEL_ERROR_EINVAL; + cond = static_cast(createCond(cond)); // check this. Kero Blaster. + } + if (mutex == nullptr || *mutex == nullptr) { + return SCE_KERNEL_ERROR_EINVAL; + } + int result = pthread_cond_wait(&(*cond)->cond, &(*mutex)->pth_mutex); + + LOG_INFO(Kernel_Pthread, "scePthreadCondWait, result={}", result); + + switch (result) { + case 0: + return SCE_OK; + case EINTR: + return SCE_KERNEL_ERROR_EINTR; + case EAGAIN: + return SCE_KERNEL_ERROR_EAGAIN; + default: + return SCE_KERNEL_ERROR_EINVAL; + } +} + +int PS4_SYSV_ABI scePthreadCondattrDestroy(ScePthreadCondattr* attr) { + if (attr == nullptr) { + return SCE_KERNEL_ERROR_EINVAL; + } + int result = pthread_condattr_destroy(&(*attr)->cond_attr); + + LOG_INFO(Kernel_Pthread, "scePthreadCondattrDestroy: result = {} ", result); + + switch (result) { + case 0: + return SCE_OK; + case ENOMEM: + return SCE_KERNEL_ERROR_ENOMEM; + default: + return SCE_KERNEL_ERROR_EINVAL; + } +} + +int PS4_SYSV_ABI scePthreadMutexTrylock(ScePthreadMutex* mutex) { + + if (mutex == nullptr) { + return ORBIS_KERNEL_ERROR_EINVAL; + } + + int result = pthread_mutex_trylock(&(*mutex)->pth_mutex); + if (result != 0) { + LOG_INFO(Kernel_Pthread, "name={}, result={}", (*mutex)->name, result); + } + switch (result) { + case 0: + return ORBIS_OK; + case EAGAIN: + return ORBIS_KERNEL_ERROR_EAGAIN; + case EBUSY: + return ORBIS_KERNEL_ERROR_EBUSY; + case EINVAL: + default: + return ORBIS_KERNEL_ERROR_EINVAL; + } +} + void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("4+h9EzwKF4I", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetschedpolicy); LIB_FUNCTION("-Wreprtu0Qs", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetdetachstate); @@ -909,6 +997,7 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("4qGrR6eoP9Y", "libkernel", 1, "libkernel", 1, 1, scePthreadDetach); LIB_FUNCTION("aI+OeCz8xrQ", "libkernel", 1, "libkernel", 1, 1, scePthreadSelf); + LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", 1, 1, pthread_self); LIB_FUNCTION("3qxgM4ezETA", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetaffinity); LIB_FUNCTION("8+s5BzZjxSg", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrGetaffinity); LIB_FUNCTION("x1X76arYMxU", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrGet); @@ -927,10 +1016,14 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("1FGvU0i9saQ", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexattrSetprotocol); LIB_FUNCTION("9UK1vLZQft4", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexLock); LIB_FUNCTION("tn3VlD0hG60", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexUnlock); + LIB_FUNCTION("upoVrzMHFeE", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexTrylock); // cond calls LIB_FUNCTION("2Tb92quprl0", "libkernel", 1, "libkernel", 1, 1, scePthreadCondInit); LIB_FUNCTION("m5-2bsNfv7s", "libkernel", 1, "libkernel", 1, 1, scePthreadCondattrInit); LIB_FUNCTION("JGgj7Uvrl+A", "libkernel", 1, "libkernel", 1, 1, scePthreadCondBroadcast); + 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); // 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/libc_internal/libc_internal.cpp b/src/core/libraries/libc_internal/libc_internal.cpp new file mode 100644 index 00000000..9fd7906a --- /dev/null +++ b/src/core/libraries/libc_internal/libc_internal.cpp @@ -0,0 +1,60 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include "common/logging/log.h" +#include "core/libraries/error_codes.h" +#include "core/libraries/libs.h" +#include "libc_internal.h" + +namespace Libraries::LibcInternal { + +void* PS4_SYSV_ABI internal_memset(void* s, int c, size_t n) { + return std::memset(s, c, n); +} + +void* PS4_SYSV_ABI internal_memcpy(void* dest, const void* src, size_t n) { + return std::memcpy(dest, src, n); +} + +int PS4_SYSV_ABI internal_memcpy_s(void* dest, rsize_t destsz, const void* src, rsize_t count) { +#ifdef _WIN64 + return memcpy_s(dest, destsz, src, count); +#else + std::memcpy(dest, src, count); + return 0; // ALL OK +#endif +} + +int PS4_SYSV_ABI internal_strcpy_s(char* dest, rsize_t dest_size, const char* src) { +#ifdef _WIN64 + return strcpy_s(dest, dest_size, src); +#else + std::strcpy(dest, src); + return 0; // ALL OK +#endif +} + +int PS4_SYSV_ABI internal_memcmp(const void* s1, const void* s2, size_t n) { + return std::memcmp(s1, s2, n); +} + +float PS4_SYSV_ABI internal_expf(float x) { + return expf(x); +} + +void RegisterlibSceLibcInternal(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("NFLs+dRJGNg", "libSceLibcInternal", 1, "libSceLibcInternal", 1, 1, + internal_memcpy_s); + LIB_FUNCTION("Q3VBxCXhUHs", "libSceLibcInternal", 1, "libSceLibcInternal", 1, 1, + internal_memcpy); + LIB_FUNCTION("8zTFvBIAIN8", "libSceLibcInternal", 1, "libSceLibcInternal", 1, 1, + internal_memset); + LIB_FUNCTION("5Xa2ACNECdo", "libSceLibcInternal", 1, "libSceLibcInternal", 1, 1, + internal_strcpy_s); + LIB_FUNCTION("DfivPArhucg", "libSceLibcInternal", 1, "libSceLibcInternal", 1, 1, + internal_memcmp); + LIB_FUNCTION("8zsu04XNsZ4", "libSceLibcInternal", 1, "libSceLibcInternal", 1, 1, internal_expf); +}; + +} // namespace Libraries::LibcInternal \ No newline at end of file diff --git a/src/core/libraries/libc_internal/libc_internal.h b/src/core/libraries/libc_internal/libc_internal.h new file mode 100644 index 00000000..e154eff6 --- /dev/null +++ b/src/core/libraries/libc_internal/libc_internal.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/types.h" + +namespace Core::Loader { +class SymbolsResolver; +} + +namespace Libraries::LibcInternal { +void* PS4_SYSV_ABI internal_memset(void* s, int c, size_t n); +void* PS4_SYSV_ABI internal_memcpy(void* dest, const void* src, size_t n); +int PS4_SYSV_ABI internal_memcpy_s(void* dest, rsize_t destsz, const void* src, rsize_t count); +int PS4_SYSV_ABI internal_strcpy_s(char* dest, rsize_t dest_size, const char* src); +int PS4_SYSV_ABI internal_memcmp(const void* s1, const void* s2, size_t n); +float PS4_SYSV_ABI internal_expf(float x); + +void RegisterlibSceLibcInternal(Core::Loader::SymbolsResolver* sym); +} // namespace Libraries::LibcInternal \ No newline at end of file diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index 30d1fa6b..61f4878f 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -7,6 +7,7 @@ #include "core/libraries/gnmdriver/gnmdriver.h" #include "core/libraries/kernel/libkernel.h" #include "core/libraries/libc/libc.h" +#include "core/libraries/libc_internal/libc_internal.h" #include "core/libraries/libs.h" #include "core/libraries/network/http.h" #include "core/libraries/network/net.h" @@ -57,6 +58,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) { Libraries::NpScore::RegisterlibSceNpScore(sym); Libraries::NpTrophy::RegisterlibSceNpTrophy(sym); Libraries::ScreenShot::RegisterlibSceScreenShot(sym); + Libraries::LibcInternal::RegisterlibSceLibcInternal(sym); } } // namespace Libraries diff --git a/src/main.cpp b/src/main.cpp index b37702b2..ce93bca5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -70,6 +70,14 @@ int main(int argc, char* argv[]) { Libraries::InitHLELibs(&linker->getHLESymbols()); linker->LoadModule(path); + // check if we have system modules to load + const auto& sys_module_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir); + for (const auto& entry : std::filesystem::directory_iterator(sys_module_path)) { + if (entry.path().filename() == "libSceNgs2.sprx") { + LOG_INFO(Loader, "Loading {}", entry.path().string().c_str()); + linker->LoadModule(entry.path().string().c_str()); + } + } // Check if there is a libc.prx in sce_module folder bool found = false; if (Config::isLleLibc()) {