diff --git a/src/common/slot_vector.h b/src/common/slot_vector.h index 7f232920..f0982e29 100644 --- a/src/common/slot_vector.h +++ b/src/common/slot_vector.h @@ -12,7 +12,7 @@ #include "common/assert.h" #include "common/types.h" -namespace VideoCore { +namespace Common { struct SlotId { static constexpr u32 INVALID_INDEX = std::numeric_limits::max(); @@ -54,6 +54,10 @@ public: return values[id.index].object; } + bool is_allocated(SlotId id) const { + return ReadStorageBit(id.index); + } + template [[nodiscard]] SlotId insert(Args&&... args) noexcept { const u32 index = FreeValueIndex(); @@ -107,7 +111,7 @@ private: stored_bitset[index / 64] &= ~(u64(1) << (index % 64)); } - bool ReadStorageBit(u32 index) noexcept { + bool ReadStorageBit(u32 index) const noexcept { return ((stored_bitset[index / 64] >> (index % 64)) & 1) != 0; } @@ -162,11 +166,11 @@ private: std::vector free_list; }; -} // namespace VideoCore +} // namespace Common template <> -struct std::hash { - std::size_t operator()(const VideoCore::SlotId& id) const noexcept { +struct std::hash { + std::size_t operator()(const Common::SlotId& id) const noexcept { return std::hash{}(id.index); } }; diff --git a/src/core/libraries/error_codes.h b/src/core/libraries/error_codes.h index 321a9fba..c7732ad5 100644 --- a/src/core/libraries/error_codes.h +++ b/src/core/libraries/error_codes.h @@ -446,3 +446,10 @@ constexpr int ORBIS_USER_SERVICE_ERROR_BUFFER_TOO_SHORT = 0x8096000A; // SystemService library constexpr int ORBIS_SYSTEM_SERVICE_ERROR_PARAMETER = 0x80A10003; + +// NpTrophy library +constexpr int ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT = 0x80551604; +constexpr int ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE = 0x80551608; +constexpr int ORBIS_NP_TROPHY_ERROR_HANDLE_EXCEEDS_MAX = 0x80551624; +constexpr int ORBIS_NP_TROPHY_ERROR_CONTEXT_ALREADY_EXISTS = 0x80551613; +constexpr int ORBIS_NP_TROPHY_ERROR_CONTEXT_EXCEEDS_MAX = 0x80551622; diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index 3b4d310f..80901c0b 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -53,7 +53,7 @@ struct AscQueueInfo { u32* read_addr; u32 ring_size_dw; }; -static VideoCore::SlotVector asc_queues{}; +static Common::SlotVector asc_queues{}; static constexpr VAddr tessellation_factors_ring_addr = 0xFF0000000ULL; static void DumpCommandList(std::span cmd_list, const std::string& postfix) { diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 3aba1f78..d1187a87 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -1278,6 +1278,7 @@ int PS4_SYSV_ABI scePthreadOnce(int* once_control, void (*init_routine)(void)) { [[noreturn]] void PS4_SYSV_ABI scePthreadExit(void* value_ptr) { pthread_exit(value_ptr); + UNREACHABLE(); } void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { diff --git a/src/core/libraries/np_trophy/np_trophy.cpp b/src/core/libraries/np_trophy/np_trophy.cpp index f7fb6e09..4b1f4369 100644 --- a/src/core/libraries/np_trophy/np_trophy.cpp +++ b/src/core/libraries/np_trophy/np_trophy.cpp @@ -2,13 +2,33 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Generated By moduleGenerator +#include + #include "common/logging/log.h" +#include "common/slot_vector.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "np_trophy.h" namespace Libraries::NpTrophy { +static constexpr auto MaxTrophyHandles = 4u; +static constexpr auto MaxTrophyContexts = 8u; + +using ContextKey = std::pair; // +struct ContextKeyHash { + size_t operator()(const ContextKey& key) const { + return key.first + (u64(key.second) << 32u); + } +}; + +struct TrophyContext { + u32 context_id; +}; +static Common::SlotVector trophy_handles{}; +static Common::SlotVector trophy_contexts{}; +static std::unordered_map contexts_internal{}; + int PS4_SYSV_ABI sceNpTrophyAbortHandle() { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); return ORBIS_OK; @@ -64,14 +84,43 @@ int PS4_SYSV_ABI sceNpTrophyConfigHasGroupFeature() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNpTrophyCreateContext() { - LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); +s32 PS4_SYSV_ABI sceNpTrophyCreateContext(u32* context, u32 user_id, u32 service_label, + u64 options) { + ASSERT(options == 0ull); + if (!context) { + return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; + } + + if (trophy_contexts.size() >= MaxTrophyContexts) { + return ORBIS_NP_TROPHY_ERROR_CONTEXT_EXCEEDS_MAX; + } + + const auto& key = ContextKey{user_id, service_label}; + if (contexts_internal.contains(key)) { + return ORBIS_NP_TROPHY_ERROR_CONTEXT_ALREADY_EXISTS; + } + + const auto ctx_id = trophy_contexts.insert(user_id, service_label); + contexts_internal[key].context_id = ctx_id.index; + LOG_INFO(Lib_NpTrophy, "New context = {}, user_id = {} service label = {}", ctx_id.index, + user_id, service_label); + *context = ctx_id.index; return ORBIS_OK; } -int PS4_SYSV_ABI sceNpTrophyCreateHandle() { - LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); - return -1; +s32 PS4_SYSV_ABI sceNpTrophyCreateHandle(u32* handle) { + if (!handle) { + return ORBIS_NP_TROPHY_ERROR_INVALID_ARGUMENT; + } + + if (trophy_handles.size() >= MaxTrophyHandles) { + return ORBIS_NP_TROPHY_ERROR_HANDLE_EXCEEDS_MAX; + } + const auto handle_id = trophy_handles.insert(); + LOG_INFO(Lib_NpTrophy, "New handle = {}", handle_id.index); + + *handle = handle_id.index; + return ORBIS_OK; } int PS4_SYSV_ABI sceNpTrophyDestroyContext() { @@ -79,8 +128,13 @@ int PS4_SYSV_ABI sceNpTrophyDestroyContext() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNpTrophyDestroyHandle() { - LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); +s32 PS4_SYSV_ABI sceNpTrophyDestroyHandle(u32 handle) { + if (!trophy_handles.is_allocated({handle})) { + return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE; + } + + trophy_handles.erase({handle}); + LOG_INFO(Lib_NpTrophy, "Handle {} destroyed", handle); return ORBIS_OK; } @@ -114,8 +168,10 @@ int PS4_SYSV_ABI sceNpTrophyGetTrophyInfo() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNpTrophyGetTrophyUnlockState() { +s32 PS4_SYSV_ABI sceNpTrophyGetTrophyUnlockState(u32 context, u32 handle, u32* flags, u32* count) { LOG_ERROR(Lib_NpTrophy, "(STUBBED) called"); + *flags = 0u; + *count = 0; return ORBIS_OK; } diff --git a/src/core/libraries/np_trophy/np_trophy.h b/src/core/libraries/np_trophy/np_trophy.h index 91b9351b..d05d353f 100644 --- a/src/core/libraries/np_trophy/np_trophy.h +++ b/src/core/libraries/np_trophy/np_trophy.h @@ -22,17 +22,18 @@ int PS4_SYSV_ABI sceNpTrophyConfigGetTrophySetInfoInGroup(); int PS4_SYSV_ABI sceNpTrophyConfigGetTrophySetVersion(); int PS4_SYSV_ABI sceNpTrophyConfigGetTrophyTitleDetails(); int PS4_SYSV_ABI sceNpTrophyConfigHasGroupFeature(); -int PS4_SYSV_ABI sceNpTrophyCreateContext(); -int PS4_SYSV_ABI sceNpTrophyCreateHandle(); +s32 PS4_SYSV_ABI sceNpTrophyCreateContext(u32* context, u32 user_id, u32 service_label, + u64 options); +s32 PS4_SYSV_ABI sceNpTrophyCreateHandle(u32* handle); int PS4_SYSV_ABI sceNpTrophyDestroyContext(); -int PS4_SYSV_ABI sceNpTrophyDestroyHandle(); +s32 PS4_SYSV_ABI sceNpTrophyDestroyHandle(u32 handle); int PS4_SYSV_ABI sceNpTrophyGetGameIcon(); int PS4_SYSV_ABI sceNpTrophyGetGameInfo(); int PS4_SYSV_ABI sceNpTrophyGetGroupIcon(); int PS4_SYSV_ABI sceNpTrophyGetGroupInfo(); int PS4_SYSV_ABI sceNpTrophyGetTrophyIcon(); int PS4_SYSV_ABI sceNpTrophyGetTrophyInfo(); -int PS4_SYSV_ABI sceNpTrophyGetTrophyUnlockState(); +s32 PS4_SYSV_ABI sceNpTrophyGetTrophyUnlockState(u32 context, u32 handle, u32* flags, u32* count); int PS4_SYSV_ABI sceNpTrophyGroupArrayGetNum(); int PS4_SYSV_ABI sceNpTrophyIntAbortHandle(); int PS4_SYSV_ABI sceNpTrophyIntCheckNetSyncTitles(); diff --git a/src/video_core/texture_cache/image.h b/src/video_core/texture_cache/image.h index 2964379f..9d9022c6 100644 --- a/src/video_core/texture_cache/image.h +++ b/src/video_core/texture_cache/image.h @@ -100,7 +100,7 @@ private: vk::Image image{}; }; -constexpr SlotId NULL_IMAGE_ID{0}; +constexpr Common::SlotId NULL_IMAGE_ID{0}; struct Image { explicit Image(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler, diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 1d5aafa2..0ecd9faf 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -140,8 +140,8 @@ private: Vulkan::Scheduler& scheduler; Vulkan::StreamBuffer staging; TileManager tile_manager; - SlotVector slot_images; - SlotVector slot_image_views; + Common::SlotVector slot_images; + Common::SlotVector slot_image_views; tsl::robin_map samplers; tsl::robin_pg_map> page_table; boost::icl::interval_map cached_pages; diff --git a/src/video_core/texture_cache/types.h b/src/video_core/texture_cache/types.h index 335d6d83..fd646665 100644 --- a/src/video_core/texture_cache/types.h +++ b/src/video_core/texture_cache/types.h @@ -8,8 +8,8 @@ namespace VideoCore { -using ImageId = SlotId; -using ImageViewId = SlotId; +using ImageId = Common::SlotId; +using ImageViewId = Common::SlotId; struct Offset2D { s32 x;