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;