diff --git a/rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp b/rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp new file mode 100644 index 0000000000..4e6046bd25 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp @@ -0,0 +1,8 @@ +#include "stdafx.h" +#include "Emu/Memory/Memory.h" +#include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/ARMv7/PSVObjectList.h" +#include "sceLibKernel.h" +#include "psv_sema_object.h" + +psv_object_list_t g_psv_sema_list; diff --git a/rpcs3/Emu/ARMv7/Modules/psv_sema_object.h b/rpcs3/Emu/ARMv7/Modules/psv_sema_object.h new file mode 100644 index 0000000000..ee643cab4c --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_sema_object.h @@ -0,0 +1,11 @@ +#pragma once + +struct psv_sema_t +{ + char name[32]; + u32 attr; + s32 initCount; + s32 maxCount; +}; + +extern psv_object_list_t g_psv_sema_list; diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index ac2600dc4b..fd852feae7 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -1,12 +1,14 @@ #include "stdafx.h" #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/ARMv7/PSVObjectList.h" #include "Emu/CPU/CPUThreadManager.h" #include "Emu/SysCalls/Callback.h" #include "Emu/ARMv7/ARMv7Thread.h" #include "sceLibKernel.h" +#include "psv_sema_object.h" #define RETURN_ERROR(code) { Emu.Pause(); sceLibKernel.Error("%s() failed: %s", __FUNCTION__, #code); return code; } @@ -450,7 +452,18 @@ s32 sceKernelCreateSema(vm::psv::ptr pName, u32 attr, s32 initCount, { sceLibKernel.Error("sceKernelCreateSema(pName=0x%x, attr=0x%x, initCount=%d, maxCount=%d, pOptParam=0x%x)", pName, attr, initCount, maxCount, pOptParam); - throw __FUNCTION__; + std::shared_ptr sema(new psv_sema_t); + + strcpy_trunc(sema->name, pName.get_ptr()); + sema->attr = attr; + sema->initCount = initCount; + sema->maxCount = maxCount; + + const s32 id = g_psv_sema_list.add(sema); + + sceLibKernel.Error("*** semaphore created -> id=0x%x", id); + + return id; } s32 sceKernelDeleteSema(s32 semaId) diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.h b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.h index dca20547c1..186c470b1c 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.h +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.h @@ -251,6 +251,20 @@ enum SCE_KERNEL_ERROR_NO_AUTH = 0x8002F001, }; +enum psv_object_class_t : u32 +{ + SCE_KERNEL_UID_CLASS_PROCESS = 0, + SCE_KERNEL_THREADMGR_UID_CLASS_THREAD = 1, + SCE_KERNEL_THREADMGR_UID_CLASS_SEMA = 2, + SCE_KERNEL_THREADMGR_UID_CLASS_EVENT_FLAG = 3, + SCE_KERNEL_THREADMGR_UID_CLASS_MUTEX = 4, + SCE_KERNEL_THREADMGR_UID_CLASS_COND = 5, + SCE_KERNEL_THREADMGR_UID_CLASS_TIMER = 6, + SCE_KERNEL_THREADMGR_UID_CLASS_MSG_PIPE = 7, + SCE_KERNEL_THREADMGR_UID_CLASS_CALLBACK = 8, + SCE_KERNEL_THREADMGR_UID_CLASS_THREAD_EVENT = 9, +}; + union SceKernelSysClock { struct diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.cpp b/rpcs3/Emu/ARMv7/PSVObjectList.cpp new file mode 100644 index 0000000000..d9cb43aeef --- /dev/null +++ b/rpcs3/Emu/ARMv7/PSVObjectList.cpp @@ -0,0 +1,3 @@ +#include "stdafx.h" +#include "PSVObjectList.h" + diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.h b/rpcs3/Emu/ARMv7/PSVObjectList.h new file mode 100644 index 0000000000..16d026f21e --- /dev/null +++ b/rpcs3/Emu/ARMv7/PSVObjectList.h @@ -0,0 +1,96 @@ +#pragma once + +union uid_t +{ + // true UID format is partially unknown + s32 uid; + + struct + { + u32 oddness : 1; // always 1 for UIDs (to not mess it up with addresses) + u32 number : 15; // ID from 0 to 2^15-1 + u32 type : 15; // UID class (psv_object_class_t) + u32 sign : 1; // UIDs are positive, error codes are negative + }; + + static uid_t make(s32 uid) + { + uid_t result; + result.uid = uid; + return result; + } +}; + +template +class psv_object_list_t // Class for managing object data +{ + std::array, 0x8000> m_data; + +public: + static const u32 uid_class = type; + + // check if UID is potentially valid (will return true if the object doesn't exist) + bool check(s32 uid) + { + const uid_t id = uid_t::make(uid); + + // check sign bit, uid class and ensure that value is odd + return !id.sign && id.type == uid_class && id.oddness == 1; + } + + // share object with UID specified (will return empty pointer if the object doesn't exist or the UID is invalid) + std::shared_ptr find(s32 uid) + { + if (!check(uid)) + { + return nullptr; + } + + return m_data[uid_t::make(uid).number]; + } + + std::shared_ptr operator [](s32 uid) + { + return find(uid); + } + + // generate UID for newly created object (will return zero if the limit exceeded) + s32 add(std::shared_ptr& data) + { + for (auto& value : m_data) + { + // find an empty position and move the pointer + std::shared_ptr old_ptr = nullptr; + if (std::atomic_compare_exchange_strong(&value, &old_ptr, data)) + { + uid_t id = uid_t::make(1); // odd number + id.type = uid_class; // set type + id.number = &value - m_data.data(); // set position + return id.uid; + } + } + + return 0; + } + + // remove object with UID specified and share it for the last time (will return empty pointer if the object doesn't exists or the UID is invalid) + std::shared_ptr remove(s32 uid) + { + if (!check(uid)) + { + return nullptr; + } + + return std::atomic_exchange(&m_data[uid_t::make(uid).number], nullptr); + } + + // remove all objects + void clear() + { + for (auto& value : m_data) + { + value = nullptr; + } + } +}; + diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 4b4a2d6539..da233b2c30 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -56,11 +56,13 @@ + + @@ -274,8 +276,10 @@ + + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index fdd71b410a..887600c974 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -87,6 +87,9 @@ {1d6abf72-0f18-43ec-9351-1fed1a3d1a1e} + + {368770cf-c8d9-4f4a-9ac3-5bdf48101ffe} + @@ -665,6 +668,12 @@ Emu\CPU\ARMv7 + + Emu\CPU\ARMv7\Thread Manager + + + Emu\CPU\ARMv7 + @@ -1294,5 +1303,11 @@ Emu\CPU\ARMv7\Modules + + Emu\CPU\ARMv7\Thread Manager + + + Emu\CPU\ARMv7 + \ No newline at end of file