diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e123f3d9..5f388c970 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -494,6 +494,8 @@ set(HLE_LIBC_INTERNAL_LIB src/core/libraries/libc_internal/libc_internal.cpp src/core/libraries/libc_internal/libc_internal_str.h src/core/libraries/libc_internal/libc_internal_math.cpp src/core/libraries/libc_internal/libc_internal_math.h + src/core/libraries/libc_internal/libc_internal_threads.cpp + src/core/libraries/libc_internal/libc_internal_threads.h src/core/libraries/libc_internal/printf.h ) diff --git a/src/core/libraries/kernel/threads.h b/src/core/libraries/kernel/threads.h index bcccf1695..42ab0b13f 100644 --- a/src/core/libraries/kernel/threads.h +++ b/src/core/libraries/kernel/threads.h @@ -28,6 +28,16 @@ int PS4_SYSV_ABI posix_pthread_create(PthreadT* thread, const PthreadAttrT* attr int PS4_SYSV_ABI posix_pthread_join(PthreadT pthread, void** thread_return); +int PS4_SYSV_ABI posix_pthread_mutexattr_init(PthreadMutexAttrT* attr); +int PS4_SYSV_ABI posix_pthread_mutexattr_settype(PthreadMutexAttrT* attr, PthreadMutexType type); +int PS4_SYSV_ABI posix_pthread_mutexattr_destroy(PthreadMutexAttrT* attr); + +int PS4_SYSV_ABI scePthreadMutexInit(PthreadMutexT* mutex, const PthreadMutexAttrT* mutex_attr, + const char* name); +int PS4_SYSV_ABI posix_pthread_mutex_lock(PthreadMutexT* mutex); +int PS4_SYSV_ABI posix_pthread_mutex_unlock(PthreadMutexT* mutex); +int PS4_SYSV_ABI posix_pthread_mutex_destroy(PthreadMutexT* mutex); + void RegisterThreads(Core::Loader::SymbolsResolver* sym); class Thread { diff --git a/src/core/libraries/libc_internal/libc_internal.cpp b/src/core/libraries/libc_internal/libc_internal.cpp index 9434d438d..6a92d2317 100644 --- a/src/core/libraries/libc_internal/libc_internal.cpp +++ b/src/core/libraries/libc_internal/libc_internal.cpp @@ -11,6 +11,7 @@ #include "libc_internal_math.h" #include "libc_internal_memory.h" #include "libc_internal_str.h" +#include "libc_internal_threads.h" #include "printf.h" namespace Libraries::LibcInternal { @@ -20,6 +21,7 @@ void RegisterLib(Core::Loader::SymbolsResolver* sym) { RegisterlibSceLibcInternalStr(sym); RegisterlibSceLibcInternalMemory(sym); RegisterlibSceLibcInternalIo(sym); + RegisterlibSceLibcInternalThreads(sym); } void ForceRegisterLib(Core::Loader::SymbolsResolver* sym) { diff --git a/src/core/libraries/libc_internal/libc_internal_io.cpp b/src/core/libraries/libc_internal/libc_internal_io.cpp index 60750282f..fa9de6fcd 100644 --- a/src/core/libraries/libc_internal/libc_internal_io.cpp +++ b/src/core/libraries/libc_internal/libc_internal_io.cpp @@ -11,21 +11,18 @@ #include "core/libraries/kernel/file_system.h" #include "core/libraries/kernel/kernel.h" #include "core/libraries/kernel/posix_error.h" +#include "core/libraries/kernel/threads.h" #include "core/libraries/libs.h" #include "libc_internal_io.h" #include "printf.h" namespace Libraries::LibcInternal { -s32 PS4_SYSV_ABI internal_snprintf(char* s, size_t n, VA_ARGS) { +s32 PS4_SYSV_ABI internal_snprintf(char* s, u64 n, VA_ARGS) { VA_CTX(ctx); return snprintf_ctx(s, n, &ctx); } -void RegisterlibSceLibcInternalIo(Core::Loader::SymbolsResolver* sym) { - LIB_FUNCTION("eLdDw6l0-bU", "libSceLibcInternal", 1, "libSceLibcInternal", internal_snprintf); -} - std::vector g_files{}; // Constants for tracking accurate file indexes. // Since the file struct is exposed to the application, accuracy is important. @@ -88,7 +85,14 @@ s32 PS4_SYSV_ABI internal_fclose(OrbisFILE* stream) { return 0; } +void RegisterlibSceLibcInternalIo(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("eLdDw6l0-bU", "libSceLibcInternal", 1, "libSceLibcInternal", internal_snprintf); + LIB_FUNCTION("xGT4Mc55ViQ", "libSceLibcInternal", 1, "libSceLibcInternal", internal__Fofind); + LIB_FUNCTION("dREVnZkAKRE", "libSceLibcInternal", 1, "libSceLibcInternal", internal__Foprep); +} + void ForceRegisterlibSceLibcInternalIo(Core::Loader::SymbolsResolver* sym) { + // Goal is to be minimally intrusive here to allow LLE for printf/stdout writes. LIB_FUNCTION("xeYO4u7uyJ0", "libSceLibcInternal", 1, "libSceLibcInternal", internal_fopen); LIB_FUNCTION("rQFVBXp-Cxg", "libSceLibcInternal", 1, "libSceLibcInternal", internal_fseek); LIB_FUNCTION("lbB+UlZqVG0", "libSceLibcInternal", 1, "libSceLibcInternal", internal_fread); diff --git a/src/core/libraries/libc_internal/libc_internal_io.h b/src/core/libraries/libc_internal/libc_internal_io.h index 81ea53940..1319d652d 100644 --- a/src/core/libraries/libc_internal/libc_internal_io.h +++ b/src/core/libraries/libc_internal/libc_internal_io.h @@ -39,18 +39,16 @@ struct OrbisFILE { u16 _Mode; u8 _Idx; s32 _Handle; - u8 *_Buf, *_Bend, *_Next; u8 *_Rend, *_Wend, *_Rback; - u16 *_WRback, _WBack[2]; + u16 unk1; u8 *_Rsave, *_WRend, *_WWend; - Orbis_Mbstatet _Wstate; u8* _Tmpnam; u8 _Back[6], _Cbuf; + u8 unk2; void* _Mutex; - u8* _p; s32 _r; s32 _w; @@ -58,25 +56,19 @@ struct OrbisFILE { s16 _file; Orbis__sbuf _bf; s32 _lbfsize; - void* _cookie; s32 PS4_SYSV_ABI (*_close)(void*); s32 PS4_SYSV_ABI (*_read)(void*, char*, s32); Orbisfpos_t PS4_SYSV_ABI (*_seek)(void*, Orbisfpos_t, s32); s32 (*_write)(void*, const char*, s32); - Orbis__sbuf _ub; u8* _up; s32 _ur; - u8 _ubuf[3]; u8 _nbuf[1]; - Orbis__sbuf _lb; - s32 _blksize; Orbisfpos_t _offset; - void* _fl_mutex; void* _fl_owner; s32 _fl_count; @@ -84,6 +76,15 @@ struct OrbisFILE { Orbis__mbstate_t _mbstate; }; +s32 PS4_SYSV_ABI internal_snprintf(char* s, u64 n, VA_ARGS); +OrbisFILE* PS4_SYSV_ABI internal__Fofind(); +OrbisFILE* PS4_SYSV_ABI internal__Foprep(const char* path, const char* mode, OrbisFILE* file, + s32 fd, s32 flag1, s32 flag2); +OrbisFILE* PS4_SYSV_ABI internal_fopen(const char* path, const char* mode); +s32 PS4_SYSV_ABI internal_fseek(OrbisFILE* stream, s64 offset, s32 whence); +u64 PS4_SYSV_ABI internal_fread(void* ptr, u64 size, u64 nmemb, OrbisFILE* stream); +s32 PS4_SYSV_ABI internal_fclose(OrbisFILE* stream); + void RegisterlibSceLibcInternalIo(Core::Loader::SymbolsResolver* sym); void ForceRegisterlibSceLibcInternalIo(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::LibcInternal \ No newline at end of file diff --git a/src/core/libraries/libc_internal/libc_internal_threads.cpp b/src/core/libraries/libc_internal/libc_internal_threads.cpp new file mode 100644 index 000000000..9a463a1e2 --- /dev/null +++ b/src/core/libraries/libc_internal/libc_internal_threads.cpp @@ -0,0 +1,64 @@ +// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/libraries/kernel/threads.h" +#include "core/libraries/libc_internal/libc_internal_threads.h" +#include "core/libraries/libs.h" + +namespace Libraries::LibcInternal { + +void getMutexName(char* buf, u64 size, const char* name) { + if (name != nullptr) { + std::snprintf(buf, size, "SceLibcI_%s", name); + } + std::snprintf(buf, size, "SceLibcI"); +} + +s32 PS4_SYSV_ABI internal__Mtxinit(Libraries::Kernel::PthreadMutexT* mtx, const char* name) { + char mtx_name[0x20]; + getMutexName(mtx_name, sizeof(mtx_name), name); + + Libraries::Kernel::PthreadMutexAttrT attr{}; + s32 result = Libraries::Kernel::posix_pthread_mutexattr_init(&attr); + if (result != 0) { + return 1; + } + + result = Libraries::Kernel::posix_pthread_mutexattr_settype( + &attr, Libraries::Kernel::PthreadMutexType::Recursive); + if (result != 0) { + s32 mtx_init_result = Libraries::Kernel::scePthreadMutexInit(mtx, &attr, mtx_name); + result = Libraries::Kernel::posix_pthread_mutexattr_destroy(&attr); + if (mtx_init_result == 0 && result == 0) { + return 0; + } + } else { + Libraries::Kernel::posix_pthread_mutexattr_destroy(&attr); + } + + return 1; +} + +s32 PS4_SYSV_ABI internal__Mtxlock(Libraries::Kernel::PthreadMutexT* mtx) { + s32 result = Libraries::Kernel::posix_pthread_mutex_lock(mtx); + return result != 0; +} + +s32 PS4_SYSV_ABI internal__Mtxunlock(Libraries::Kernel::PthreadMutexT* mtx) { + s32 result = Libraries::Kernel::posix_pthread_mutex_unlock(mtx); + return result != 0; +} + +s32 PS4_SYSV_ABI internal__Mtxdst(Libraries::Kernel::PthreadMutexT* mtx) { + s32 result = Libraries::Kernel::posix_pthread_mutex_destroy(mtx); + return result != 0; +} + +void RegisterlibSceLibcInternalThreads(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("z7STeF6abuU", "libSceLibcInternal", 1, "libSceLibcInternal", internal__Mtxinit); + LIB_FUNCTION("pE4Ot3CffW0", "libSceLibcInternal", 1, "libSceLibcInternal", internal__Mtxlock); + LIB_FUNCTION("cMwgSSmpE5o", "libSceLibcInternal", 1, "libSceLibcInternal", internal__Mtxunlock); + LIB_FUNCTION("LaPaA6mYA38", "libSceLibcInternal", 1, "libSceLibcInternal", internal__Mtxdst); +} + +} // namespace Libraries::LibcInternal \ No newline at end of file diff --git a/src/core/libraries/libc_internal/libc_internal_threads.h b/src/core/libraries/libc_internal/libc_internal_threads.h new file mode 100644 index 000000000..1e5b3ac84 --- /dev/null +++ b/src/core/libraries/libc_internal/libc_internal_threads.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include "common/types.h" + +namespace Core::Loader { +class SymbolsResolver; +} + +namespace Libraries::LibcInternal { + +void RegisterlibSceLibcInternalThreads(Core::Loader::SymbolsResolver* sym); +} \ No newline at end of file