From 4b186604524c252359bf526e904e04bae56a1d37 Mon Sep 17 00:00:00 2001 From: Nokk Date: Tue, 9 Jul 2024 14:04:40 +1000 Subject: [PATCH 1/3] Started implementing Ult library --- CMakeLists.txt | 2 + src/common/logging/filter.cpp | 1 + src/common/logging/types.h | 1 + src/core/libraries/error_codes.h | 7 ++ src/core/libraries/libs.cpp | 2 + src/core/libraries/ult/ult.cpp | 127 +++++++++++++++++++++++++++++++ src/core/libraries/ult/ult.h | 94 +++++++++++++++++++++++ 7 files changed, 234 insertions(+) create mode 100644 src/core/libraries/ult/ult.cpp create mode 100644 src/core/libraries/ult/ult.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 89b1f03e..8c197f0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -214,6 +214,8 @@ set(NP_LIBS src/core/libraries/np_manager/np_manager.cpp ) set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp src/core/libraries/screenshot/screenshot.h + src/core/libraries/ult/ult.cpp + src/core/libraries/ult/ult.h ) set(COMMON src/common/logging/backend.cpp diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 35159bf1..313a3e3f 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, Ult) \ SUB(Lib, LibCInternal) \ SUB(Lib, AppContent) \ SUB(Lib, Rtc) \ diff --git a/src/common/logging/types.h b/src/common/logging/types.h index d415335b..45f51cc5 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_Ult, ///< The LibSceUlt implementation Lib_LibCInternal, ///< The LibCInternal implementation. Lib_AppContent, ///< The LibSceAppContent implementation. Lib_Rtc, ///< The LibSceRtc implementation. diff --git a/src/core/libraries/error_codes.h b/src/core/libraries/error_codes.h index 63016213..fe1e7e05 100644 --- a/src/core/libraries/error_codes.h +++ b/src/core/libraries/error_codes.h @@ -456,3 +456,10 @@ constexpr int ORBIS_NP_TROPHY_ERROR_CONTEXT_EXCEEDS_MAX = 0x80551622; // AppContent library constexpr int ORBIS_APP_CONTENT_ERROR_PARAMETER = 0x80D90002; + +// Ult Library +constexpr int ORBIS_ULT_ERROR_STATE = 0x80810006; +constexpr int ORBIS_ULT_ERROR_NULL = 0x80810001; +constexpr int ORBIS_ULT_ERROR_ALIGNMENT = 0x80810002; +constexpr int ORBIS_ULT_ERROR_INVALID = 0x80810004; +constexpr int ORBIS_ULT_ERROR_NOT_INITIALIZE = 0x8081000A; \ No newline at end of file diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index 00df4ddf..494df7d4 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -23,6 +23,7 @@ #include "core/libraries/rtc/rtc.h" #include "core/libraries/save_data/savedata.h" #include "core/libraries/screenshot/screenshot.h" +#include "core/libraries/ult/ult.h" #include "core/libraries/system/commondialog.h" #include "core/libraries/system/msgdialog.h" #include "core/libraries/system/posix.h" @@ -65,6 +66,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) { Libraries::NpScore::RegisterlibSceNpScore(sym); Libraries::NpTrophy::RegisterlibSceNpTrophy(sym); Libraries::ScreenShot::RegisterlibSceScreenShot(sym); + Libraries::Ult::RegisterlibSceUlt(sym); Libraries::AppContent::RegisterlibSceAppContent(sym); Libraries::PngDec::RegisterlibScePngDec(sym); Libraries::PlayGo::RegisterlibScePlayGo(sym); diff --git a/src/core/libraries/ult/ult.cpp b/src/core/libraries/ult/ult.cpp new file mode 100644 index 00000000..91cee321 --- /dev/null +++ b/src/core/libraries/ult/ult.cpp @@ -0,0 +1,127 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "core/libraries/error_codes.h" +#include "core/libraries/libs.h" +#include "ult.h" + +namespace Libraries::Ult { + +bool isUltInitialized = false; +int PS4_SYSV_ABI sceUltInitialize() { + LOG_INFO(Lib_Ult, "called"); + if (isUltInitialized) { + return ORBIS_ULT_ERROR_STATE; + } + + isUltInitialized = true; + return ORBIS_OK; +} +int PS4_SYSV_ABI _sceUltUlthreadRuntimeCreate(OrbisUltUlthreadRuntime* runtime, const char* name, + uint32_t maxNumUlthread, uint32_t numWorkerThread, + void* workArea, + OrbisUltUlthreadRuntimeOptParam* optParam) { + LOG_ERROR(Lib_Ult, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI _sceUltUlthreadCreate(OrbisUltUlthread* ulthread, const char* name, + OrbisUltUlthreadEntry entry, uint64_t arg, void* context, + uint64_t sizeContext, OrbisUltUlthreadRuntime* runtime, + OrbisUltUlthreadOptParam* optParam) { + LOG_ERROR(Lib_Ult, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI _sceUltWaitingQueueResourcePoolCreate( + OrbisUltWaitingQueueResourcePool* pool, const char* name, + uint32_t numThreads, uint32_t numSyncObjects, + void* workArea, + OrbisUltWaitingQueueResourcePoolOptParam* optParam) +{ + LOG_ERROR(Lib_Ult, "(STUBBED) called"); + + if (pool == nullptr) + return ORBIS_ULT_ERROR_NULL; + + if (name != nullptr) + LOG_INFO(Lib_Ult, "Creating WaitingQueueResourcePool for {}", name); + + // TODO: Check memory alignment + // TODO: Set ORBIS_ULT_ERROR_NOT_INITIALIZE + + if (optParam != nullptr) + { + // TODO: Check memory alignment + // TODO: FUN_0100678(optParam) + } + + // TODO: FUN_01011b10(&pool->field41_0x30,numThreads,numSyncObjects,(long)workArea); + + if (numThreads > 0 && numSyncObjects > 0 && workArea != nullptr) + { + pool->workArea = workArea; + void* w = (void*)((long)workArea + 0x20); + } + + // IF NO ERROR + //FUN_0101e800((char *)pool,name) + pool->field32_0x20 = 0x100; // ?? + pool->field33_0x22 = '\x06'; // ?? + pool->numThreads = numThreads * 2; + pool->numSyncObjects = numSyncObjects; + //BG26hBGiNlw(pool, 0x16, &pool->field178_0xc0); + // ENDIF + + return ORBIS_OK; +} + +int PS4_SYSV_ABI _sceUltQueueDataResourcePoolCreate( + OrbisUltQueueDataResourcePool* pool, const char* name, + uint32_t numData, uint64_t dataSize, + uint32_t numQueueObjects, + OrbisUltWaitingQueueResourcePool* waitingQueueResourcePool, + void* workArea, + OrbisUltQueueDataResourcePoolOptParam* optParam) +{ + + LOG_ERROR(Lib_Ult, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceUltQueueTryPush(OrbisUltQueue* queue, void* data) { + LOG_ERROR(Lib_Ult, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceUltQueuePush(OrbisUltQueue* queue, void* data) { + LOG_ERROR(Lib_Ult, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceUltQueueTryPop(OrbisUltQueue* queue, void* data) { + LOG_ERROR(Lib_Ult, "(STUBBED) called"); + return ORBIS_OK; +} + +int PS4_SYSV_ABI sceUltQueuePop(OrbisUltQueue* queue, void* data) { + LOG_ERROR(Lib_Ult, "(STUBBED) called"); + return ORBIS_OK; +} + +void RegisterlibSceUlt(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("hZIg1EWGsHM", "libSceUlt", 1, "libSceUlt", 1, 1, sceUltInitialize); + LIB_FUNCTION("jw9FkZBXo-g", "libSceUlt", 1, "libSceUlt", 1, 1, _sceUltUlthreadRuntimeCreate); + LIB_FUNCTION("uZz3ci7XYqc", "libSceUlt", 1, "libSceUlt", 1, 1, sceUltQueueTryPop); + LIB_FUNCTION("RVSq2tsm2yw", "libSceUlt", 1, "libSceUlt", 1, 1, sceUltQueuePop); + LIB_FUNCTION("znI3q8S7KQ4", "libSceUlt", 1, "libSceUlt", 1, 1, _sceUltUlthreadCreate); + LIB_FUNCTION("6Mc2Xs7pI1I", "libSceUlt", 1, "libSceUlt", 1, 1, sceUltQueueTryPush); + LIB_FUNCTION("dUwpX3e5NDE", "libSceUlt", 1, "libSceUlt", 1, 1, sceUltQueuePush); + LIB_FUNCTION("YiHujOG9vXY", "libSceUlt", 1, "libSceUlt", 1, 1, + _sceUltWaitingQueueResourcePoolCreate); + LIB_FUNCTION("TFHm6-N6vks", "libSceUlt", 1, "libSceUlt", 1, 1, + _sceUltQueueDataResourcePoolCreate); +}; + +} \ No newline at end of file diff --git a/src/core/libraries/ult/ult.h b/src/core/libraries/ult/ult.h new file mode 100644 index 00000000..6aaffea4 --- /dev/null +++ b/src/core/libraries/ult/ult.h @@ -0,0 +1,94 @@ +// 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::Ult { + +typedef int32_t (*OrbisUltUlthreadEntry)(uint64_t arg); + +struct OrbisUltQueue { + //private +}; + +struct OrbisUltUlthreadRuntimeOptParam { + uint64_t oneShotThreadStackSize; + u64 workerThreadCpuAffinityMask; + int32_t workerThreadPriority; + int inheritSched; + /* other members are private */ +}; + +struct OrbisUltUlthreadRuntime { + // private +}; + +struct OrbisUltUlthread { + // private +}; + +struct OrbisUltUlthreadOptParam { + uint32_t attribute; + // rest private +}; + +struct OrbisUltWaitingQueueResourcePool { + char unknown_padding1[30]; + char unknown_char; + u16 field32_0x20; + char field33_0x22; + char unknkown_char3; + u32 numThreads; + u32 numSyncObjects; + char unkown_padding2[4]; + void* workArea; + // More unkowns... +}; + +struct OrbisUltWaitingQueueResourcePoolOptParam { + // private +}; + +struct OrbisUltQueueDataResourcePool { + // private +}; + +struct OrbisUltQueueDataResourcePoolOptParam { + // private +}; + +int PS4_SYSV_ABI sceUltInitialize(); + +int PS4_SYSV_ABI _sceUltUlthreadRuntimeCreate(OrbisUltUlthreadRuntime* runtime, const char* name, + uint32_t maxNumUlthread, uint32_t numWorkerThread, + void* workArea, + OrbisUltUlthreadRuntimeOptParam* optParam); + +int PS4_SYSV_ABI _sceUltUlthreadCreate(OrbisUltUlthread* ulthread, const char* name, + OrbisUltUlthreadEntry entry, uint64_t arg, void* context, + uint64_t sizeContext, OrbisUltUlthreadRuntime* runtime, + OrbisUltUlthreadOptParam* optParam); + +int PS4_SYSV_ABI _sceUltWaitingQueueResourcePoolCreate( + OrbisUltWaitingQueueResourcePool* pool, const char* name, uint32_t numThreads, + uint32_t numSyncObjects, void* workArea, OrbisUltWaitingQueueResourcePoolOptParam* optParam); + +int PS4_SYSV_ABI _sceUltQueueDataResourcePoolCreate( + OrbisUltQueueDataResourcePool* pool, const char* name, uint32_t numData, uint64_t dataSize, + uint32_t numQueueObjects, OrbisUltWaitingQueueResourcePool* waitingQueueResourcePool, + void* workArea, OrbisUltQueueDataResourcePoolOptParam* optParam); + +int PS4_SYSV_ABI sceUltQueueTryPush(OrbisUltQueue* queue, void* data); +int PS4_SYSV_ABI sceUltQueuePush(OrbisUltQueue* queue, void* data); + +int PS4_SYSV_ABI sceUltQueueTryPop(OrbisUltQueue* queue, void* data); +int PS4_SYSV_ABI sceUltQueuePop(OrbisUltQueue* queue, void* data); + +void RegisterlibSceUlt(Core::Loader::SymbolsResolver* sym); +} // namespace Libraries::Ult \ No newline at end of file From 822ec64db6bae25558ff852ae6d86e31ae3b94af Mon Sep 17 00:00:00 2001 From: Nokk Date: Tue, 9 Jul 2024 17:22:13 +1000 Subject: [PATCH 2/3] Added more functions. WorkArea for WaitingPool being wiped for some reason. --- src/core/libraries/ult/ult.cpp | 114 ++++++++++++++++++++++++++------- src/core/libraries/ult/ult.h | 37 ++++++++++- 2 files changed, 127 insertions(+), 24 deletions(-) diff --git a/src/core/libraries/ult/ult.cpp b/src/core/libraries/ult/ult.cpp index 91cee321..5df8631e 100644 --- a/src/core/libraries/ult/ult.cpp +++ b/src/core/libraries/ult/ult.cpp @@ -35,13 +35,10 @@ int PS4_SYSV_ABI _sceUltUlthreadCreate(OrbisUltUlthread* ulthread, const char* n } int PS4_SYSV_ABI _sceUltWaitingQueueResourcePoolCreate( - OrbisUltWaitingQueueResourcePool* pool, const char* name, - uint32_t numThreads, uint32_t numSyncObjects, - void* workArea, - OrbisUltWaitingQueueResourcePoolOptParam* optParam) -{ + OrbisUltWaitingQueueResourcePool* pool, const char* name, uint32_t numThreads, + uint32_t numSyncObjects, void* workArea, OrbisUltWaitingQueueResourcePoolOptParam* optParam) { LOG_ERROR(Lib_Ult, "(STUBBED) called"); - + if (pool == nullptr) return ORBIS_ULT_ERROR_NULL; @@ -51,41 +48,86 @@ int PS4_SYSV_ABI _sceUltWaitingQueueResourcePoolCreate( // TODO: Check memory alignment // TODO: Set ORBIS_ULT_ERROR_NOT_INITIALIZE - if (optParam != nullptr) - { + if (optParam != nullptr) { // TODO: Check memory alignment // TODO: FUN_0100678(optParam) } // TODO: FUN_01011b10(&pool->field41_0x30,numThreads,numSyncObjects,(long)workArea); - if (numThreads > 0 && numSyncObjects > 0 && workArea != nullptr) - { + if (numThreads > 0 && numSyncObjects > 0 && workArea != nullptr) { pool->workArea = workArea; void* w = (void*)((long)workArea + 0x20); } // IF NO ERROR - //FUN_0101e800((char *)pool,name) - pool->field32_0x20 = 0x100; // ?? + // FUN_0101e800((char *)pool,name) + pool->field32_0x20 = 0x100; // ?? pool->field33_0x22 = '\x06'; // ?? pool->numThreads = numThreads * 2; pool->numSyncObjects = numSyncObjects; - //BG26hBGiNlw(pool, 0x16, &pool->field178_0xc0); - // ENDIF + // BG26hBGiNlw(pool, 0x16, &pool->field178_0xc0); + // ENDIF return ORBIS_OK; } int PS4_SYSV_ABI _sceUltQueueDataResourcePoolCreate( - OrbisUltQueueDataResourcePool* pool, const char* name, - uint32_t numData, uint64_t dataSize, - uint32_t numQueueObjects, - OrbisUltWaitingQueueResourcePool* waitingQueueResourcePool, - void* workArea, - OrbisUltQueueDataResourcePoolOptParam* optParam) -{ + OrbisUltQueueDataResourcePool* pool, const char* name, uint32_t numData, uint64_t dataSize, + uint32_t numQueueObjects, OrbisUltWaitingQueueResourcePool* waitingQueueResourcePool, + void* workArea, OrbisUltQueueDataResourcePoolOptParam* optParam) { + LOG_ERROR(Lib_Ult, "(STUBBED) called"); + + if (pool == nullptr) + return ORBIS_ULT_ERROR_NULL; + + // TODO: Check 8 bit alignment + + strncpy((char*)pool, name, 0x1f); + + pool->uk_200 = 0x200; // TODO: Why? + pool->uk_a = '\a'; // TODO: Why? + pool->numData = numData; + pool->numQueueObjects = numQueueObjects; + pool->waitingPool = waitingQueueResourcePool; + + // TODO: BG26hBGiNlw(pool,0x17,&pool->field347_0x170); + + return ORBIS_OK; +} + +int PS4_SYSV_ABI _sceUltQueueCreate(OrbisUltQueue* queue, const char* name, uint64_t dataSize, + OrbisUltQueueDataResourcePool* queueDataResourcePool, + OrbisUltWaitingQueueResourcePool* waitingQueueResourcePool, + OrbisUltQueueOptParam* optParam) { + LOG_ERROR(Lib_Ult, "(STUBBED) called"); + + // TODO: Put data pool + Waiting Pool into Queue + + if (queue != nullptr && name != nullptr && waitingQueueResourcePool->workArea != nullptr) { + // TODO: Check 8bit alignment + if (optParam == nullptr) { + // TODO: Check 8bit alignment + // TODO: Handle default args. It looks like it just sets everything to 0. + } else { + // TODO: Handle optional params + } + + // TODO: Do this in a more readable way + strncpy((char*)queue, name, 0x1f); + + queue->waitingWorkArea = waitingQueueResourcePool->workArea; + queue->dataWorkArea = queueDataResourcePool->workArea; + + } else { + return ORBIS_ULT_ERROR_NULL; + } + + return ORBIS_OK; +} + +int PS4_SYSV_ABI _sceUltQueueOptParamInitialize(OrbisUltQueueOptParam* optParam) { LOG_ERROR(Lib_Ult, "(STUBBED) called"); return ORBIS_OK; } @@ -97,6 +139,10 @@ int PS4_SYSV_ABI sceUltQueueTryPush(OrbisUltQueue* queue, void* data) { int PS4_SYSV_ABI sceUltQueuePush(OrbisUltQueue* queue, void* data) { LOG_ERROR(Lib_Ult, "(STUBBED) called"); + + if (queue == nullptr || data == nullptr) + return ORBIS_ULT_ERROR_NULL; + return ORBIS_OK; } @@ -107,9 +153,27 @@ int PS4_SYSV_ABI sceUltQueueTryPop(OrbisUltQueue* queue, void* data) { int PS4_SYSV_ABI sceUltQueuePop(OrbisUltQueue* queue, void* data) { LOG_ERROR(Lib_Ult, "(STUBBED) called"); + + if (queue == nullptr || data == nullptr) + return ORBIS_ULT_ERROR_NULL; + return ORBIS_OK; } +u64 PS4_SYSV_ABI sceUltWaitingQueueResourcePoolGetWorkAreaSize(uint32_t numThreads, + uint32_t numSyncObjects) { + u64 size = (numSyncObjects + 2 + numThreads * 2) << 5; + LOG_INFO(Lib_Ult, "WaitingQueueResourcePoolSize: {}", size); + return size; +} + +u64 PS4_SYSV_ABI sceUltQueueDataResourcePoolGetWorkAreaSize(uint32_t numData, uint64_t dataSize, + uint32_t numQueueObjects) { + u64 size = numData * dataSize + (numQueueObjects + 3 + numData * 2) * 0x20; + LOG_INFO(Lib_Ult, "QueueDataResourcePoolSize: {}", size); + return size; +} + void RegisterlibSceUlt(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("hZIg1EWGsHM", "libSceUlt", 1, "libSceUlt", 1, 1, sceUltInitialize); LIB_FUNCTION("jw9FkZBXo-g", "libSceUlt", 1, "libSceUlt", 1, 1, _sceUltUlthreadRuntimeCreate); @@ -122,6 +186,12 @@ void RegisterlibSceUlt(Core::Loader::SymbolsResolver* sym) { _sceUltWaitingQueueResourcePoolCreate); LIB_FUNCTION("TFHm6-N6vks", "libSceUlt", 1, "libSceUlt", 1, 1, _sceUltQueueDataResourcePoolCreate); + LIB_FUNCTION("9Y5keOvb6ok", "libSceUlt", 1, "libSceUlt", 1, 1, _sceUltQueueCreate); + LIB_FUNCTION("TkASc9I-xX0", "libSceUlt", 1, "libSceUlt", 1, 1, _sceUltQueueOptParamInitialize); + LIB_FUNCTION("WIWV1Qd7PFU", "libSceUlt", 1, "libSceUlt", 1, 1, + sceUltWaitingQueueResourcePoolGetWorkAreaSize); + LIB_FUNCTION("evj9YPkS8s4", "libSceUlt", 1, "libSceUlt", 1, 1, + sceUltQueueDataResourcePoolGetWorkAreaSize); }; -} \ No newline at end of file +} // namespace Libraries::Ult \ No newline at end of file diff --git a/src/core/libraries/ult/ult.h b/src/core/libraries/ult/ult.h index 6aaffea4..d8d5163a 100644 --- a/src/core/libraries/ult/ult.h +++ b/src/core/libraries/ult/ult.h @@ -14,7 +14,12 @@ namespace Libraries::Ult { typedef int32_t (*OrbisUltUlthreadEntry)(uint64_t arg); struct OrbisUltQueue { - //private + char unknown[208]; + void* waitingWorkArea; + void* dataWorkArea; + char unknown2[24]; + size_t datasize; + // private }; struct OrbisUltUlthreadRuntimeOptParam { @@ -39,7 +44,7 @@ struct OrbisUltUlthreadOptParam { }; struct OrbisUltWaitingQueueResourcePool { - char unknown_padding1[30]; + char unknown_padding1[31]; char unknown_char; u16 field32_0x20; char field33_0x22; @@ -56,6 +61,17 @@ struct OrbisUltWaitingQueueResourcePoolOptParam { }; struct OrbisUltQueueDataResourcePool { + char unknown_padding1[31]; + short uk_200; + char uk_a; + char unknown_char; + u32 numData; + u32 numQueueObjects; + char unknkown_char3[4]; + void* workArea; + char padd[130]; + char unkown_padding2[4]; + OrbisUltWaitingQueueResourcePool* waitingPool; // private }; @@ -63,6 +79,10 @@ struct OrbisUltQueueDataResourcePoolOptParam { // private }; +struct OrbisUltQueueOptParam { + // Private +}; + int PS4_SYSV_ABI sceUltInitialize(); int PS4_SYSV_ABI _sceUltUlthreadRuntimeCreate(OrbisUltUlthreadRuntime* runtime, const char* name, @@ -84,11 +104,24 @@ int PS4_SYSV_ABI _sceUltQueueDataResourcePoolCreate( uint32_t numQueueObjects, OrbisUltWaitingQueueResourcePool* waitingQueueResourcePool, void* workArea, OrbisUltQueueDataResourcePoolOptParam* optParam); +int PS4_SYSV_ABI _sceUltQueueCreate(OrbisUltQueue* queue, const char* name, uint64_t dataSize, + OrbisUltQueueDataResourcePool* queueDataResourcePool, + OrbisUltWaitingQueueResourcePool* waitingQueueResourcePool, + OrbisUltQueueOptParam* optParam); + +int PS4_SYSV_ABI _sceUltQueueOptParamInitialize(OrbisUltQueueOptParam* optParam); + int PS4_SYSV_ABI sceUltQueueTryPush(OrbisUltQueue* queue, void* data); int PS4_SYSV_ABI sceUltQueuePush(OrbisUltQueue* queue, void* data); int PS4_SYSV_ABI sceUltQueueTryPop(OrbisUltQueue* queue, void* data); int PS4_SYSV_ABI sceUltQueuePop(OrbisUltQueue* queue, void* data); +u64 PS4_SYSV_ABI sceUltWaitingQueueResourcePoolGetWorkAreaSize(uint32_t numThreads, + uint32_t numSyncObjects); + +u64 PS4_SYSV_ABI sceUltQueueDataResourcePoolGetWorkAreaSize(uint32_t numData, uint64_t dataSize, + uint32_t numQueueObjects); + void RegisterlibSceUlt(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::Ult \ No newline at end of file From bb6c5de1fc8ebfa65d0559ce6c7511f98da06c0d Mon Sep 17 00:00:00 2001 From: Nokk Date: Tue, 9 Jul 2024 19:52:56 +1000 Subject: [PATCH 3/3] Naieve Queue --- src/core/libraries/error_codes.h | 3 ++- src/core/libraries/ult/ult.cpp | 29 +++++++++++++++++++++++++++-- src/core/libraries/ult/ult.h | 13 ++++++++++--- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/core/libraries/error_codes.h b/src/core/libraries/error_codes.h index fe1e7e05..9ad64fdd 100644 --- a/src/core/libraries/error_codes.h +++ b/src/core/libraries/error_codes.h @@ -462,4 +462,5 @@ constexpr int ORBIS_ULT_ERROR_STATE = 0x80810006; constexpr int ORBIS_ULT_ERROR_NULL = 0x80810001; constexpr int ORBIS_ULT_ERROR_ALIGNMENT = 0x80810002; constexpr int ORBIS_ULT_ERROR_INVALID = 0x80810004; -constexpr int ORBIS_ULT_ERROR_NOT_INITIALIZE = 0x8081000A; \ No newline at end of file +constexpr int ORBIS_ULT_ERROR_NOT_INITIALIZE = 0x8081000A; +constexpr int ORBIS_ULT_ERROR_PERMISSION = 0x80810005; \ No newline at end of file diff --git a/src/core/libraries/ult/ult.cpp b/src/core/libraries/ult/ult.cpp index 5df8631e..0219b7c0 100644 --- a/src/core/libraries/ult/ult.cpp +++ b/src/core/libraries/ult/ult.cpp @@ -57,11 +57,10 @@ int PS4_SYSV_ABI _sceUltWaitingQueueResourcePoolCreate( if (numThreads > 0 && numSyncObjects > 0 && workArea != nullptr) { pool->workArea = workArea; - void* w = (void*)((long)workArea + 0x20); } // IF NO ERROR - // FUN_0101e800((char *)pool,name) + strncpy((char*)pool, name, 0x1f); pool->field32_0x20 = 0x100; // ?? pool->field33_0x22 = '\x06'; // ?? pool->numThreads = numThreads * 2; @@ -91,6 +90,7 @@ int PS4_SYSV_ABI _sceUltQueueDataResourcePoolCreate( pool->numData = numData; pool->numQueueObjects = numQueueObjects; pool->waitingPool = waitingQueueResourcePool; + pool->workArea = workArea; // TODO: BG26hBGiNlw(pool,0x17,&pool->field347_0x170); @@ -119,6 +119,7 @@ int PS4_SYSV_ABI _sceUltQueueCreate(OrbisUltQueue* queue, const char* name, uint queue->waitingWorkArea = waitingQueueResourcePool->workArea; queue->dataWorkArea = queueDataResourcePool->workArea; + queue->datasize = dataSize; } else { return ORBIS_ULT_ERROR_NULL; @@ -142,6 +143,17 @@ int PS4_SYSV_ABI sceUltQueuePush(OrbisUltQueue* queue, void* data) { if (queue == nullptr || data == nullptr) return ORBIS_ULT_ERROR_NULL; + + // If there is no data in the queue when sceUltQueuePop() is executed, the thread is in the wait + // state until data is added to the queue. + void* addr = (char*)queue->waitingWorkArea + (queue->datasize) * (queue->uk5); + + if (!addr) // Empty + return ORBIS_OK; + + memcpy(addr, data, queue->datasize); + + queue->uk5++; return ORBIS_OK; } @@ -157,6 +169,19 @@ int PS4_SYSV_ABI sceUltQueuePop(OrbisUltQueue* queue, void* data) { if (queue == nullptr || data == nullptr) return ORBIS_ULT_ERROR_NULL; + if (queue->uk5 < 1) // Thread should wait + return ORBIS_OK; + + // If there is no data in the queue when sceUltQueuePop() is executed, the thread is in the wait state until data is added to the queue. + void* addr = (char*)queue->waitingWorkArea + (queue->datasize) * (queue->uk5 - 1); + + if (!addr) // Empty + return ORBIS_OK; + + memcpy(data, addr, queue->datasize); + + queue->uk5--; + return ORBIS_OK; } diff --git a/src/core/libraries/ult/ult.h b/src/core/libraries/ult/ult.h index d8d5163a..94e289e4 100644 --- a/src/core/libraries/ult/ult.h +++ b/src/core/libraries/ult/ult.h @@ -14,7 +14,14 @@ namespace Libraries::Ult { typedef int32_t (*OrbisUltUlthreadEntry)(uint64_t arg); struct OrbisUltQueue { - char unknown[208]; + char queue_name[31]; + char uk[8]; + u64 uk2; + u64 uk3; + u64 uk4; + void* ukP; + u32 uk5; + char uk6[131]; void* waitingWorkArea; void* dataWorkArea; char unknown2[24]; @@ -44,7 +51,7 @@ struct OrbisUltUlthreadOptParam { }; struct OrbisUltWaitingQueueResourcePool { - char unknown_padding1[31]; + char queue_name[31]; char unknown_char; u16 field32_0x20; char field33_0x22; @@ -61,7 +68,7 @@ struct OrbisUltWaitingQueueResourcePoolOptParam { }; struct OrbisUltQueueDataResourcePool { - char unknown_padding1[31]; + char queue_name[31]; short uk_200; char uk_a; char unknown_char;