feat(libSceUlt): add underscore mutex and queue create exports

This commit is contained in:
Semir Kabir 2026-10-11 09:29:28 -07:00
parent a11c8f7f70
commit 54b9b93240
3 changed files with 44 additions and 1 deletions

View File

@ -580,6 +580,22 @@ int APS5_VABI _sceUltSemaphoreCreate(void* semaphore, const char* name, std::int
return sceUltSemaphoreCreate(semaphore, name, numInitialResource, waitingQueueResourcePool, optParam, buildVersion);
}
int APS5_VABI _sceUltMutexOptParamInitialize(UltMutexOptParam* optParam, std::uint32_t buildVersion) {
return sceUltMutexOptParamInitialize(optParam, buildVersion);
}
int APS5_VABI _sceUltMutexCreate(void* mutex, const char* name, void* waitingQueueResourcePool, const UltMutexOptParam* optParam, std::uint32_t buildVersion) {
return sceUltMutexCreate(mutex, name, waitingQueueResourcePool, optParam, buildVersion);
}
int APS5_VABI _sceUltQueueDataResourcePoolCreate(void* pool, const char* name, std::uint32_t numData, std::uint64_t dataSize, std::uint32_t numQueueObject, void* waitingQueueResourcePool, void* workArea, const void* optParam, std::uint32_t buildVersion) {
return sceUltQueueDataResourcePoolCreate(pool, name, numData, dataSize, numQueueObject, waitingQueueResourcePool, workArea, optParam, buildVersion);
}
int APS5_VABI _sceUltQueueCreate(void* queue, const char* name, std::uint64_t dataSize, void* waitingQueueResourcePool, void* queueDataResourcePool, const void* optParam, std::uint32_t buildVersion) {
return sceUltQueueCreate(queue, name, dataSize, waitingQueueResourcePool, queueDataResourcePool, optParam, buildVersion);
}
int APS5_VABI _sceUltUlthreadRuntimeOptParamInitialize(UltUlthreadRuntimeOptParam* optParam, std::uint32_t buildVersion) {
return sceUltUlthreadRuntimeOptParamInitialize(optParam, buildVersion);
}

View File

@ -22,6 +22,14 @@ int APS5_VABI _sceUltWaitingQueueResourcePoolCreate(void*, const char*, std::uin
int APS5_VABI _sceUltSemaphoreCreate(void*, const char*, std::int32_t, void*, const void*, std::uint32_t);
int APS5_VABI sceUltSemaphoreAcquire(void*, std::int32_t);
int APS5_VABI sceUltSemaphoreRelease(void*, std::int32_t);
int APS5_VABI _sceUltMutexOptParamInitialize(void*, std::uint32_t);
int APS5_VABI _sceUltMutexCreate(void*, const char*, void*, const void*, std::uint32_t);
int APS5_VABI sceUltMutexLock(void*);
int APS5_VABI sceUltMutexUnlock(void*);
int APS5_VABI _sceUltQueueDataResourcePoolCreate(void*, const char*, std::uint32_t, std::uint64_t, std::uint32_t, void*, void*, const void*, std::uint32_t);
int APS5_VABI _sceUltQueueCreate(void*, const char*, std::uint64_t, void*, void*, const void*, std::uint32_t);
int APS5_VABI sceUltQueuePush(void*, const void*);
int APS5_VABI sceUltQueuePop(void*, void*);
}
static constexpr int Ok = 0;
@ -150,6 +158,25 @@ static void UnderscoredCreate() {
CHECK(_sceUltSemaphoreCreate(semaphore, "semaphore", 2, pool, nullptr, 0) == State);
CHECK(sceUltSemaphoreAcquire(semaphore, 2) == Ok);
CHECK(sceUltSemaphoreRelease(semaphore, 2) == Ok);
alignas(8) static std::uint8_t mutexOptParam[128];
alignas(8) static std::uint8_t mutex[256];
std::memset(mutexOptParam, 0xFF, sizeof(mutexOptParam));
CHECK(_sceUltMutexOptParamInitialize(nullptr, 0) == Null);
CHECK(_sceUltMutexOptParamInitialize(mutexOptParam, 0) == Ok);
CHECK(mutexOptParam[8] == 0 && mutexOptParam[15] == 0);
CHECK(_sceUltMutexCreate(nullptr, "mutex", pool, mutexOptParam, 0) == Null);
CHECK(_sceUltMutexCreate(mutex, "mutex", pool, mutexOptParam, 0) == Ok);
CHECK(sceUltMutexLock(mutex) == Ok);
CHECK(sceUltMutexUnlock(mutex) == Ok);
alignas(8) static std::uint8_t dataPool[512];
alignas(8) static std::uint8_t queue[512];
CHECK(_sceUltQueueDataResourcePoolCreate(nullptr, "data", 1, 8, 1, pool, nullptr, nullptr, 0) == Null);
CHECK(_sceUltQueueDataResourcePoolCreate(dataPool, "data", 1, 8, 1, pool, nullptr, nullptr, 0) == Ok);
CHECK(_sceUltQueueCreate(nullptr, "queue", 8, pool, dataPool, nullptr, 0) == Null);
CHECK(_sceUltQueueCreate(queue, "queue", 8, pool, dataPool, nullptr, 0) == Ok);
std::uint64_t value = 0x1122334455667788ull, output = 0;
CHECK(sceUltQueuePush(queue, &value) == Ok);
CHECK(sceUltQueuePop(queue, &output) == Ok && output == value);
}
int main(int argc, char** argv) {

View File

@ -52,7 +52,7 @@ Throughout the project, every function at every stage either **does exactly what
- [sceNpGetSandboxInfo](../../core/libs/prx/libSceNpManager/Export.cpp) (libSceNpManager, NID `ZVZ++68nNI8`) - the name hashes to the imported NID (found with nidhunt, confirmed with `tools/nid_names.py`). STAR WARS: Galactic Racer (PPSA28416) imports it; its OnlineSubsystemPS5 calls it with one pointer to a 0x50-byte stack buffer and reads the buffer as a string (discussions/3086). The returned string, the exact parameter struct and console errors are unknown, so every call throws without reading or writing caller memory. A working implementation belongs with that title's bring-up.
- [sceKernelGetSystemSwVersion](../../core/libs/prx/libkernel/System/src/SystemConfiguration.cpp) (libkernel) reports baseline system software version `0x01000000` ("01.000.000") for ProsperoStore (PPSA99000). The 0x28-byte layout (`uint64_t size` at 0, `versionString` at 8 and `version` at 0x24) matches [ProsperoStore's caller](https://github.com/blackbearreloaded/ProsperoStore/blob/20584011/src/diag/trace.cpp#L20-L26), [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/811bfcd7d1/src/core/libraries/kernel/kernel.h#L45-L49), [fpPS4](https://github.com/red-prig/fpPS4/blob/04cefd43e6/kernel/ps4_libkernel.pas#L502-L506) and [OpenOrbis](https://github.com/OpenOrbis/OpenOrbis-PS4-Toolchain/blob/0a1aaf9dd4/include/orbis/_types/kernel.h#L256-L260). These sources support the structure layout, but not the reported version value: the console firmware version remains unverified. The checks are unverified too: a null pointer returns `SCE_KERNEL_ERROR_EFAULT` and a `size` other than 0x28 returns `SCE_KERNEL_ERROR_EINVAL`, while shadPS4 returns success for null and never reads `size`.
- [kern.rng_pseudo](../../core/libs/prx/libkernel/System/src/SystemConfiguration.cpp) (libkernel) - `sysctlbyname` fills the whole output buffer with bytes from the host's `std::random_device` and leaves the length unchanged; a write returns -1 with `EPERM` and a call without an output buffer throws. The only caller seen is mbedTLS's `mbedtls_hardware_poll` in the catalog's ProsperoLight boilerplate, which asks for 64-byte blocks and fails if fewer come back. The console's generator, its per-call maximum and its answer to a size query are unknown
- PPSA01530, PPSA23827 and PPSA13356 imports declared without parameters, signatures unknown, added without an implementation because the titles fail to load without them: [sceNetShowIfconfig](../../core/libs/prx/libSceNet/Export.cpp) (libSceNet), [sce::Json::Value::setNullAccessCallBack](../../core/libs/prx/libSceJson2/Export.cpp) (libSceJson2), [kqueue and kevent](../../core/libs/prx/libkernel/Equeue/Equeue.cpp) (libkernel), and [scePadUnknown_n3kSX62fgNo](../../core/libs/prx/libScePad/Export.cpp) (libScePad), whose real name is unknown. [_sceUltWaitingQueueResourcePoolCreate and _sceUltSemaphoreCreate](../../core/libs/prx/libSceUlt/Export.cpp) (libSceUlt) forward to `sceUltWaitingQueueResourcePoolCreate` and `sceUltSemaphoreCreate`; that their argument lists match is inferred from the other underscore Ult exports, not measured.
- PPSA01530, PPSA23827 and PPSA13356 imports declared without parameters, signatures unknown, added without an implementation because the titles fail to load without them: [sceNetShowIfconfig](../../core/libs/prx/libSceNet/Export.cpp) (libSceNet), [sce::Json::Value::setNullAccessCallBack](../../core/libs/prx/libSceJson2/Export.cpp) (libSceJson2), [kqueue and kevent](../../core/libs/prx/libkernel/Equeue/Equeue.cpp) (libkernel), and [scePadUnknown_n3kSX62fgNo](../../core/libs/prx/libScePad/Export.cpp) (libScePad), whose real name is unknown. [_sceUltWaitingQueueResourcePoolCreate, _sceUltSemaphoreCreate, _sceUltMutexOptParamInitialize, _sceUltMutexCreate, _sceUltQueueDataResourcePoolCreate and _sceUltQueueCreate](../../core/libs/prx/libSceUlt/Export.cpp) (libSceUlt) forward to the exports without the underscore; that their argument lists match is inferred from the other underscore Ult exports, not measured.
- [sceVideoOutGetOutputStatusWithVrr](../../core/libs/prx/libSceVideoOut/Unimplemented.cpp) (libSceVideoOut, NID `gWT7X8H0bYs`) - the name hashes to the imported NID. PPSA26344 version 02.002.000 passes a VideoOut handle and an output pointer at three call sites. It compares a 32-bit value at byte 4 with 2, tests bit 0x10 at byte 16, and, when set, compares low 16-bit values at bytes 48, 50 and 52 with 48, 60 and 120. The full output layout, size, field meanings and console errors are unknown. Every call throws without reading or writing caller memory.
- [sceHttp2WebSocketSetPingInterval](../../core/libs/prx/libSceHttp2/Export.cpp) (libSceHttp2, NID `YfaXPnc8PJE`) - imported by `libdiscord_partner_sdk.prx` of PPSA23126 (issue 2648). The parameters, the unit of the interval and the console errors are unknown. Every call throws.
- [sceKernelGetProsperoSystemSwVersion](../../core/libs/prx/libkernel/System/src/SoftwareVersion.cpp) (libkernel) reports system software version `0x01000000` ("01.000.000"); the console's firmware version is not modeled. The 0x28-byte block (a 64-bit size at 0, the version string at 8 and the packed version at 0x24) follows [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/main/src/SharpProspero/Interop/Kernel/KernelSystem.cs), which Prospero Multi Tools (PPSA99110) and Prospero Explorer (PPSA99109) are built with and which sets the size to 40, and the same fields in [etaHEN](https://github.com/etaHEN/etaHEN/blob/main/Source%20Code/daemon/include/ipc.hpp) and [shsrv](https://github.com/ps5-payload-dev/shsrv/blob/master/sh.c). A size other than 0x28 returns `SCE_KERNEL_ERROR_EINVAL` without writing; whether the console checks the size is unverified, since etaHEN and shsrv declare a 0x30-byte block and do not set it