From 3d9c8a670e273b1f02269ba8eba335815b1fa97e Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Tue, 14 May 2024 00:12:50 +0200 Subject: [PATCH] Implement old matching API --- 3rdparty/flatbuffers | 2 +- rpcs3/Emu/CMakeLists.txt | 2 + rpcs3/Emu/Cell/Modules/cellSysutilAvc.cpp | 106 ++ rpcs3/Emu/Cell/Modules/sceNp.cpp | 443 ++++--- rpcs3/Emu/Cell/Modules/sceNp.h | 97 +- rpcs3/Emu/Cell/Modules/sceNp2.cpp | 12 +- rpcs3/Emu/Cell/Modules/sceNpCommerce2.cpp | 8 +- rpcs3/Emu/Cell/Modules/sceNpMatchingInt.cpp | 76 +- rpcs3/Emu/NP/fb_helpers.cpp | 209 +++- rpcs3/Emu/NP/fb_helpers.h | 29 + rpcs3/Emu/NP/generated/np2_structs.fbs | 85 +- .../Emu/NP/generated/np2_structs_generated.h | 1068 ++++++++++++++++- rpcs3/Emu/NP/np_contexts.cpp | 54 +- rpcs3/Emu/NP/np_contexts.h | 40 +- rpcs3/Emu/NP/np_event_data.h | 8 +- rpcs3/Emu/NP/np_gui_cache.cpp | 113 ++ rpcs3/Emu/NP/np_gui_cache.h | 58 + rpcs3/Emu/NP/np_handler.cpp | 66 +- rpcs3/Emu/NP/np_handler.h | 113 +- rpcs3/Emu/NP/np_notifications.cpp | 144 ++- rpcs3/Emu/NP/np_requests.cpp | 107 +- rpcs3/Emu/NP/np_requests_gui.cpp | 777 ++++++++++++ rpcs3/Emu/NP/np_structs_extra.cpp | 119 +- rpcs3/Emu/NP/np_structs_extra.h | 9 + rpcs3/Emu/NP/rpcn_client.cpp | 285 ++++- rpcs3/Emu/NP/rpcn_client.h | 48 +- rpcs3/emucore.vcxproj | 2 + rpcs3/emucore.vcxproj.filters | 6 + 28 files changed, 3620 insertions(+), 466 deletions(-) create mode 100644 rpcs3/Emu/NP/fb_helpers.h create mode 100644 rpcs3/Emu/NP/np_gui_cache.cpp create mode 100644 rpcs3/Emu/NP/np_gui_cache.h create mode 100644 rpcs3/Emu/NP/np_requests_gui.cpp diff --git a/3rdparty/flatbuffers b/3rdparty/flatbuffers index 0100f6a577..595bf0007a 160000 --- a/3rdparty/flatbuffers +++ b/3rdparty/flatbuffers @@ -1 +1 @@ -Subproject commit 0100f6a5779831fa7a651e4b67ef389a8752bd9b +Subproject commit 595bf0007ab1929570c7671f091313c8fc20644e diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt index 5cd19b300f..0f4c32b54b 100644 --- a/rpcs3/Emu/CMakeLists.txt +++ b/rpcs3/Emu/CMakeLists.txt @@ -443,8 +443,10 @@ target_link_libraries(rpcs3_emu PRIVATE target_sources(rpcs3_emu PRIVATE NP/fb_helpers.cpp NP/np_cache.cpp + NP/np_gui_cache.cpp NP/np_contexts.cpp NP/np_dnshook.cpp + NP/np_requests_gui.cpp NP/np_handler.cpp NP/np_helpers.cpp NP/np_notifications.cpp diff --git a/rpcs3/Emu/Cell/Modules/cellSysutilAvc.cpp b/rpcs3/Emu/Cell/Modules/cellSysutilAvc.cpp index bf0e53fc9e..c336f0804e 100644 --- a/rpcs3/Emu/Cell/Modules/cellSysutilAvc.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSysutilAvc.cpp @@ -1,6 +1,8 @@ #include "stdafx.h" #include "Emu/Cell/PPUModule.h" #include "Emu/Cell/Modules/cellSysutilAvc.h" +#include "Emu/Cell/Modules/cellSysutil.h" +#include "Emu/IdManager.h" LOG_CHANNEL(cellSysutil); @@ -29,6 +31,79 @@ void fmt_class_string::format(std::string& out, u64 arg) }); } +// Callback handle tag type +struct avc_cb_handle_t{}; + +struct avc_settings +{ + avc_settings() = default; + + avc_settings(const avc_settings&) = delete; + avc_settings& operator=(const avc_settings&) = delete; + + SAVESTATE_INIT_POS(53); + + shared_mutex mutex_cb; + vm::ptr avc_cb{}; + vm::ptr avc_cb_arg{}; + + atomic_t req_id_cnt = 0; + + static bool saveable(bool /*is_writing*/) noexcept + { + return GET_SERIALIZATION_VERSION(cellSysutil) != 0; + } + + avc_settings(utils::serial& ar) noexcept + { + [[maybe_unused]] const s32 version = GET_SERIALIZATION_VERSION(cellSysutil); + + if (version == 0) + { + return; + } + + save(ar); + } + + void save(utils::serial& ar) + { + [[maybe_unused]] const s32 version = GET_OR_USE_SERIALIZATION_VERSION(ar.is_writing(), cellSysutil); + ar(avc_cb, avc_cb_arg); + } + + void register_cb_call(CellSysutilAvcRequestId req_id, CellSysutilAvcEvent event_id, CellSysUtilAvcEventParam param) + { + // This is equivalent to the dispatcher code + sysutil_register_cb_with_id([=, this](ppu_thread& cb_ppu) -> s32 + { + vm::ptr avc_cb{}; + vm::ptr avc_cb_arg{}; + + { + std::lock_guard lock(this->mutex_cb); + avc_cb = this->avc_cb; + avc_cb_arg = this->avc_cb_arg; + } + + if (avc_cb) + { + // TODO: lots of checks before calling the cb + if (event_id == CELL_AVC_EVENT_UNLOAD_SUCCEEDED) + { + std::lock_guard lock(this->mutex_cb); + this->avc_cb = {}; + this->avc_cb_arg = {}; + } + + avc_cb(cb_ppu, req_id, event_id, param, avc_cb_arg); + } + + return 0; + }); + } +}; + error_code cellSysutilAvcByeRequest(vm::ptr request_id) { cellSysutil.todo("cellSysutilAvcByeRequest(request_id=*0x%x)", request_id); @@ -36,6 +111,11 @@ error_code cellSysutilAvcByeRequest(vm::ptr request_id) if (!request_id) return CELL_AVC_ERROR_INVALID_ARGUMENT; + auto& settings = g_fxo->get(); + const CellSysutilAvcRequestId req_id = settings.req_id_cnt.fetch_add(1); + *request_id = req_id; + settings.register_cb_call(req_id, CELL_AVC_EVENT_BYE_SUCCEEDED, static_cast(0)); + return CELL_OK; } @@ -152,6 +232,11 @@ error_code cellSysutilAvcJoinRequest(u32 ctx_id, vm::cptr room_id, if (!room_id || !request_id) return CELL_AVC_ERROR_INVALID_ARGUMENT; + auto& settings = g_fxo->get(); + const CellSysutilAvcRequestId req_id = settings.req_id_cnt.fetch_add(1); + *request_id = req_id; + settings.register_cb_call(req_id, CELL_AVC_EVENT_JOIN_SUCCEEDED, static_cast(0)); + return CELL_OK; } @@ -181,6 +266,22 @@ error_code cellSysutilAvcLoadAsync(vm::ptr func, vm::ptr if (videoQuality != CELL_SYSUTIL_AVC_VIDEO_QUALITY_DEFAULT || voiceQuality != CELL_SYSUTIL_AVC_VOICE_QUALITY_DEFAULT) return CELL_AVC_ERROR_INVALID_ARGUMENT; + auto& settings = g_fxo->get(); + + { + std::lock_guard lock(settings.mutex_cb); + + if (settings.avc_cb) + return CELL_AVC_ERROR_ALREADY_INITIALIZED; + + settings.avc_cb = func; + settings.avc_cb_arg = userdata; + } + + const CellSysutilAvcRequestId req_id = settings.req_id_cnt.fetch_add(1); + *request_id = req_id; + settings.register_cb_call(req_id, CELL_AVC_EVENT_LOAD_SUCCEEDED, static_cast(0)); + return CELL_OK; } @@ -239,6 +340,11 @@ error_code cellSysutilAvcUnloadAsync(vm::ptr request_id if (!request_id) return CELL_AVC_ERROR_INVALID_ARGUMENT; + auto& settings = g_fxo->get(); + const CellSysutilAvcRequestId req_id = settings.req_id_cnt.fetch_add(1); + *request_id = req_id; + settings.register_cb_call(req_id, CELL_AVC_EVENT_UNLOAD_SUCCEEDED, static_cast(0)); + return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/sceNp.cpp b/rpcs3/Emu/Cell/Modules/sceNp.cpp index cedd5343f7..79f6feb8c9 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp.cpp @@ -1946,7 +1946,7 @@ error_code sceNpBasicAddPlayersHistoryAsync(vm::cptr npids, u32 count, error_code sceNpBasicGetPlayersHistoryEntryCount(u32 options, vm::ptr count) { - sceNp.todo("sceNpBasicGetPlayersHistoryEntryCount(options=%d, count=*0x%x)", options, count); + sceNp.warning("sceNpBasicGetPlayersHistoryEntryCount(options=%d, count=*0x%x)", options, count); if (options > SCE_NP_BASIC_PLAYERS_HISTORY_OPTIONS_ALL) { @@ -3176,7 +3176,7 @@ error_code sceNpLookupInit() error_code sceNpLookupTerm() { - sceNp.todo("sceNpLookupTerm()"); + sceNp.warning("sceNpLookupTerm()"); auto& nph = g_fxo->get>(); @@ -4450,141 +4450,166 @@ error_code check_text(vm::cptr text) error_code sceNpMatchingCreateCtx(vm::ptr npId, vm::ptr handler, vm::ptr arg, vm::ptr ctx_id) { - sceNp.todo("sceNpMatchingCreateCtx(npId=*0x%x, handler=*0x%x, arg=*0x%x, ctx_id=*0x%x)", npId, handler, arg, ctx_id); + sceNp.warning("sceNpMatchingCreateCtx(npId=*0x%x, handler=*0x%x, arg=*0x%x, ctx_id=*0x%x)", npId, handler, arg, ctx_id); - if (false) // TODO + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) + { return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; + } - if (false) // TODO + if (!nph.is_NP_init) + { return SCE_NP_MATCHING_ERROR_NOT_INITIALIZED; + } - if (false) // TODO + // assumed checks done on vsh + if (!npId || !handler || !ctx_id) + { + return SCE_NP_MATCHING_ERROR_INVALID_ARG; + } + + const s32 id = create_matching_context(npId, handler, arg); + + if (!id) + { return SCE_NP_MATCHING_ERROR_CTX_MAX; + } + nph.set_current_gui_ctx_id(id); + + *ctx_id = static_cast(id); return CELL_OK; } error_code sceNpMatchingDestroyCtx(u32 ctx_id) { - sceNp.todo("sceNpMatchingDestroyCtx(ctx_id=%d)", ctx_id); + sceNp.warning("sceNpMatchingDestroyCtx(ctx_id=%d)", ctx_id); - if (false) // TODO + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; - if (false) // TODO + if (!nph.is_NP_init) return SCE_NP_MATCHING_ERROR_NOT_INITIALIZED; - if (false) // TODO + if (!destroy_matching_context(ctx_id)) return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; + nph.set_current_gui_ctx_id(0); + return CELL_OK; } error_code sceNpMatchingGetResult(u32 ctx_id, u32 req_id, vm::ptr buf, vm::ptr size, vm::ptr event) { - sceNp.todo("sceNpMatchingGetResult(ctx_id=%d, req_id=%d, buf=*0x%x, size=*0x%x, event=*0x%x)", ctx_id, req_id, buf, size, event); + sceNp.warning("sceNpMatchingGetResult(ctx_id=%d, req_id=%d, buf=*0x%x, size=*0x%x, event=*0x%x)", ctx_id, req_id, buf, size, event); - if (false) // TODO + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; - if (false) // TODO + if (!nph.is_NP_init) return SCE_NP_MATCHING_ERROR_NOT_INITIALIZED; if (!size) return SCE_NP_MATCHING_ERROR_INVALID_ARG; - if (false) // TODO - return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; + return nph.get_matching_result(ctx_id, req_id, buf, size, event); - const u64 id_check = static_cast(static_cast(req_id)) >> 0x17 & 0x3f; - if (id_check > 32 || (1ULL << id_check & 0x1f89ad040U) == 0) - return SCE_NP_MATCHING_ERROR_INVALID_REQ_ID; - - if (buf) - { - // TODO: copy data to buf - } - else - { - constexpr u32 required_size = 0; // TODO - *size = required_size; - } - - if (event) - { - //*event = some_event; // TODO: example: SCE_NP_MATCHING_GUI_EVENT_CREATE_ROOM - } - - return CELL_OK; + // const u64 id_check = static_cast(static_cast(req_id)) >> 0x17 & 0x3f; + // if (id_check > 32 || (1ULL << id_check & 0x1f89ad040U) == 0) + // return SCE_NP_MATCHING_ERROR_INVALID_REQ_ID; } error_code sceNpMatchingGetResultGUI(vm::ptr buf, vm::ptr size, vm::ptr event) { - sceNp.todo("sceNpMatchingGetResultGUI(buf=*0x%x, size=*0x%x, event=*0x%x)", buf, size, event); + sceNp.warning("sceNpMatchingGetResultGUI(buf=*0x%x, size=*0x%x, event=*0x%x)", buf, size, event); - if (false) // TODO + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; if (!size) return SCE_NP_MATCHING_ERROR_INVALID_ARG; - if (buf) + return nph.get_result_gui(buf, size, event); +} + +error_code matching_set_room_info(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, vm::ptr attr, vm::ptr req_id, bool limit) +{ + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) + return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; + + if (!nph.is_NP_init) + return SCE_NP_MATCHING_ERROR_NOT_INITIALIZED; + + if (limit) { - // TODO: copy data to buf - } - else - { - constexpr u32 required_size = 0; // TODO - *size = required_size; + static u64 last_call = 0; + + if (last_call != 0 && (get_system_time() - last_call) < 30'000'000) + return SCE_NP_MATCHING_ERROR_BUSY; + + last_call = get_system_time(); } - if (event) - { - //*event = some_event; // TODO: example: SCE_NP_MATCHING_GUI_EVENT_CREATE_ROOM - } + if (!lobby_id || !room_id || !req_id || !attr) + return SCE_NP_MATCHING_ERROR_INVALID_ARG; + error_code err = check_attr_id_and_duplicate(attr); + if (err != CELL_OK) + return err; + + auto res = nph.set_room_info_gui(ctx_id, lobby_id, room_id, attr); + + if (res < 0) + return res; + + *req_id = res; return CELL_OK; } error_code sceNpMatchingSetRoomInfo(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, vm::ptr attr, vm::ptr req_id) { - sceNp.todo("sceNpMatchingSetRoomInfo(ctx_id=%d, lobby_id=*0x%x, room_id=*0x%x, attr=*0x%x, req_id=*0x%x)", ctx_id, lobby_id, room_id, attr, req_id); + sceNp.warning("sceNpMatchingSetRoomInfo(ctx_id=%d, lobby_id=*0x%x, room_id=*0x%x, attr=*0x%x, req_id=*0x%x)", ctx_id, lobby_id, room_id, attr, req_id); - if (false) // TODO - return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; - - if (false) // TODO - return SCE_NP_MATCHING_ERROR_NOT_INITIALIZED; - - if (false) // TODO: some timeout with 30000000 us ? - return SCE_NP_MATCHING_ERROR_BUSY; - - if (!lobby_id || !room_id || !req_id || !attr) - return SCE_NP_MATCHING_ERROR_INVALID_ARG; - - error_code err = check_attr_id_and_duplicate(attr); - if (err != CELL_OK) - return err; - - if (false) // TODO - return SCE_NP_MATCHING_ERROR_BUSY; - - if (false) // TODO - return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; - - return CELL_OK; + return matching_set_room_info(ctx_id, lobby_id, room_id, attr, req_id, true); } error_code sceNpMatchingSetRoomInfoNoLimit(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, vm::ptr attr, vm::ptr req_id) { - sceNp.todo("sceNpMatchingSetRoomInfoNoLimit(ctx_id=%d, lobby_id=*0x%x, room_id=*0x%x, attr=*0x%x, req_id=*0x%x)", ctx_id, lobby_id, room_id, attr, req_id); + sceNp.warning("sceNpMatchingSetRoomInfoNoLimit(ctx_id=%d, lobby_id=*0x%x, room_id=*0x%x, attr=*0x%x, req_id=*0x%x)", ctx_id, lobby_id, room_id, attr, req_id); - if (false) // TODO + return matching_set_room_info(ctx_id, lobby_id, room_id, attr, req_id, false); +} + +error_code matching_get_room_info(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, vm::ptr attr, vm::ptr req_id, bool limit) +{ + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; - if (false) // TODO + if (!nph.is_NP_init) return SCE_NP_MATCHING_ERROR_NOT_INITIALIZED; + if (limit) + { + static u64 last_call = 0; + + if (last_call != 0 && (get_system_time() - last_call) < 30'000'000) + return SCE_NP_MATCHING_ERROR_BUSY; + + last_call = get_system_time(); + } + if (!lobby_id || !room_id || !req_id || !attr) return SCE_NP_MATCHING_ERROR_INVALID_ARG; @@ -4592,131 +4617,98 @@ error_code sceNpMatchingSetRoomInfoNoLimit(u32 ctx_id, vm::ptr lob if (err != CELL_OK) return err; - if (false) // TODO - return SCE_NP_MATCHING_ERROR_BUSY; + auto res = nph.get_room_info_gui(ctx_id, lobby_id, room_id, attr); - if (false) // TODO - return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; + if (res < 0) + return res; + *req_id = res; return CELL_OK; } error_code sceNpMatchingGetRoomInfo(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, vm::ptr attr, vm::ptr req_id) { - sceNp.todo("sceNpMatchingGetRoomInfo(ctx_id=%d, lobby_id=*0x%x, room_id=*0x%x, attr=*0x%x, req_id=*0x%x)", ctx_id, lobby_id, room_id, attr, req_id); + sceNp.warning("sceNpMatchingGetRoomInfo(ctx_id=%d, lobby_id=*0x%x, room_id=*0x%x, attr=*0x%x, req_id=*0x%x)", ctx_id, lobby_id, room_id, attr, req_id); - if (false) // TODO - return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; - - if (false) // TODO - return SCE_NP_MATCHING_ERROR_NOT_INITIALIZED; - - if (false) // TODO: some timeout with 30000000 us ? - return SCE_NP_MATCHING_ERROR_BUSY; - - if (!lobby_id || !room_id || !req_id || !attr) - return SCE_NP_MATCHING_ERROR_INVALID_ARG; - - error_code err = check_attr_id_and_duplicate(attr); - if (err != CELL_OK) - return err; - - if (false) // TODO - return SCE_NP_MATCHING_ERROR_BUSY; - - if (false) // TODO - return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; - - return CELL_OK; + return matching_get_room_info(ctx_id, lobby_id, room_id, attr, req_id, true); } error_code sceNpMatchingGetRoomInfoNoLimit(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, vm::ptr attr, vm::ptr req_id) { - sceNp.todo("sceNpMatchingGetRoomInfoNoLimit(ctx_id=%d, lobby_id=*0x%x, room_id=*0x%x, attr=*0x%x, req_id=*0x%x)", ctx_id, lobby_id, room_id, attr, req_id); + sceNp.warning("sceNpMatchingGetRoomInfoNoLimit(ctx_id=%d, lobby_id=*0x%x, room_id=*0x%x, attr=*0x%x, req_id=*0x%x)", ctx_id, lobby_id, room_id, attr, req_id); - if (false) // TODO - return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; - - if (false) // TODO - return SCE_NP_MATCHING_ERROR_NOT_INITIALIZED; - - if (!lobby_id || !room_id || !req_id || !attr) - return SCE_NP_MATCHING_ERROR_INVALID_ARG; - - error_code err = check_attr_id_and_duplicate(attr); - if (err != CELL_OK) - return err; - - if (false) // TODO - return SCE_NP_MATCHING_ERROR_BUSY; - - if (false) // TODO - return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; - - return CELL_OK; + return matching_get_room_info(ctx_id, lobby_id, room_id, attr, req_id, false); } error_code sceNpMatchingSetRoomSearchFlag(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, s32 flag, vm::ptr req_id) { - sceNp.todo("sceNpMatchingSetRoomSearchFlag(ctx_id=%d, lobby_id=*0x%x, room_id=*0x%x, flag=%d, req_id=*0x%x)", ctx_id, lobby_id, room_id, flag, req_id); + sceNp.warning("sceNpMatchingSetRoomSearchFlag(ctx_id=%d, lobby_id=*0x%x, room_id=*0x%x, flag=%d, req_id=*0x%x)", ctx_id, lobby_id, room_id, flag, req_id); - if (false) // TODO + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; - if (false) // TODO + if (!nph.is_NP_init) return SCE_NP_MATCHING_ERROR_NOT_INITIALIZED; if (!lobby_id || !room_id || !req_id || (flag < SCE_NP_MATCHING_ROOM_SEARCH_FLAG_OPEN || flag > SCE_NP_MATCHING_ROOM_SEARCH_FLAG_STEALTH)) return SCE_NP_MATCHING_ERROR_INVALID_ARG; - if (false) // TODO - return SCE_NP_MATCHING_ERROR_BUSY; + auto res = nph.set_room_search_flag_gui(ctx_id, lobby_id, room_id, flag); - if (false) // TODO - return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; + if (res < 0) + return res; + *req_id = res; return CELL_OK; } error_code sceNpMatchingGetRoomSearchFlag(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, vm::ptr req_id) { - sceNp.todo("sceNpMatchingGetRoomSearchFlag(ctx_id=%d, lobby_id=*0x%x, room_id=*0x%x, req_id=*0x%x)", ctx_id, lobby_id, room_id, req_id); + sceNp.warning("sceNpMatchingGetRoomSearchFlag(ctx_id=%d, lobby_id=*0x%x, room_id=*0x%x, req_id=*0x%x)", ctx_id, lobby_id, room_id, req_id); - if (false) // TODO + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; - if (false) // TODO + if (!nph.is_NP_init) return SCE_NP_MATCHING_ERROR_NOT_INITIALIZED; if (!lobby_id || !room_id || !req_id) return SCE_NP_MATCHING_ERROR_INVALID_ARG; - if (false) // TODO - return SCE_NP_MATCHING_ERROR_BUSY; + auto res = nph.get_room_search_flag_gui(ctx_id, lobby_id, room_id); - if (false) // TODO - return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; + if (res < 0) + return res; + *req_id = res; return CELL_OK; } -error_code sceNpMatchingGetRoomMemberListLocal(u32 ctx_id, vm::ptr room_id, vm::ptr buflen, vm::ptr buf) +error_code matching_get_room_member_list(u32 ctx_id, vm::ptr room_id, vm::ptr buflen, vm::ptr buf) { - sceNp.todo("sceNpMatchingGetRoomMemberListLocal(ctx_id=%d, room_id=*0x%x, buflen=*0x%x, buf=*0x%x)", ctx_id, room_id, buflen, buf); + auto& nph = g_fxo->get>(); - if (false) // TODO + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; - if (false) // TODO + if (!nph.is_NP_init) return SCE_NP_MATCHING_ERROR_NOT_INITIALIZED; if (!buflen) return SCE_NP_MATCHING_ERROR_INVALID_ARG; - if (false) // TODO - return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; + return nph.get_room_member_list_local_gui(ctx_id, room_id, buflen, buf); +} - return CELL_OK; +error_code sceNpMatchingGetRoomMemberListLocal(u32 ctx_id, vm::ptr room_id, vm::ptr buflen, vm::ptr buf) +{ + sceNp.warning("sceNpMatchingGetRoomMemberListLocal(ctx_id=%d, room_id=*0x%x, buflen=*0x%x, buf=*0x%x)", ctx_id, room_id, buflen, buf); + + return matching_get_room_member_list(ctx_id, room_id, buflen, buf); } // FUN_00014bdc @@ -4788,41 +4780,42 @@ error_code check_room_list_params([[maybe_unused]] u32 ctx_id, vm::ptr communicationId, vm::ptr range, vm::ptr cond, - vm::ptr attr, vm::ptr handler, vm::ptr arg) +error_code matching_get_room_list(u32 ctx_id, vm::ptr communicationId, vm::ptr range, vm::ptr cond, + vm::ptr attr, vm::ptr handler, vm::ptr arg, bool limit) { - sceNp.todo("sceNpMatchingGetRoomListLimitGUI(ctx_id=%d, communicationId=*0x%x, range=*0x%x, cond=*0x%x, attr=*0x%x, handler=*0x%x, arg=*0x%x)", ctx_id, communicationId, range, cond, attr, handler, arg); + auto& nph = g_fxo->get>(); - if (false) // TODO + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; + // TODO: add limiter + // This check is used in all sceNpMatchingGetRoomList functions error_code err = check_room_list_params(ctx_id, communicationId, range, cond, attr, handler, 1, 0); if (err != CELL_OK) return err; - if (false) // TODO - return SCE_NP_MATCHING_ERROR_BUSY; + return nph.get_room_list_gui(ctx_id, communicationId, range, cond, attr, handler, arg, limit); +} - // TODO: set callback: handler + arg +error_code sceNpMatchingGetRoomListLimitGUI(u32 ctx_id, vm::ptr communicationId, vm::ptr range, vm::ptr cond, + vm::ptr attr, vm::ptr handler, vm::ptr arg) +{ + sceNp.warning("sceNpMatchingGetRoomListLimitGUI(ctx_id=%d, communicationId=*0x%x, range=*0x%x, cond=*0x%x, attr=*0x%x, handler=*0x%x, arg=*0x%x)", ctx_id, communicationId, range, cond, attr, handler, arg); - err = CELL_OK; // GetRoomListLimit - if (err != CELL_OK && static_cast(err) != SCE_NP_MATCHING_ERROR_BUSY) - { - // TODO ? - } - - return CELL_OK; + return matching_get_room_list(ctx_id, communicationId, range, cond, attr, handler, arg, true); } error_code sceNpMatchingKickRoomMember(u32 ctx_id, vm::cptr room_id, vm::cptr user_id, vm::ptr req_id) { sceNp.todo("sceNpMatchingKickRoomMember(ctx_id=%d, room_id=*0x%x, user_id=*0x%x, req_id=*0x%x)", ctx_id, room_id, user_id, req_id); - if (false) // TODO + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; - if (false) // TODO + if (!nph.is_NP_init) return SCE_NP_MATCHING_ERROR_NOT_INITIALIZED; if (!room_id || !user_id || !req_id) @@ -4841,10 +4834,12 @@ error_code sceNpMatchingKickRoomMemberWithOpt(u32 ctx_id, vm::cptr { sceNp.todo("sceNpMatchingKickRoomMemberWithOpt(ctx_id=%d, room_id=*0x%x, user_id=*0x%x, opt=*0x%x, opt_len=%d, req_id=*0x%x)", ctx_id, room_id, user_id, opt, opt_len, req_id); - if (false) // TODO + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; - if (false) // TODO + if (!nph.is_NP_init) return SCE_NP_MATCHING_ERROR_NOT_INITIALIZED; if (!room_id || !user_id || !req_id) @@ -4865,10 +4860,12 @@ error_code sceNpMatchingKickRoomMemberWithOpt(u32 ctx_id, vm::cptr error_code sceNpMatchingQuickMatchGUI(u32 ctx_id, vm::cptr communicationId, vm::cptr cond, s32 available_num, s32 timeout, vm::ptr handler, vm::ptr arg) { - sceNp.todo("sceNpMatchingQuickMatchGUI(ctx_id=%d, communicationId=*0x%x, cond=*0x%x, available_num=%d, timeout=%d, handler=*0x%x, arg=*0x%x)", ctx_id, communicationId, cond, available_num, timeout, + sceNp.warning("sceNpMatchingQuickMatchGUI(ctx_id=%d, communicationId=*0x%x, cond=*0x%x, available_num=%d, timeout=%d, handler=*0x%x, arg=*0x%x)", ctx_id, communicationId, cond, available_num, timeout, handler, arg); - if (false) // TODO + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; if (!communicationId || !handler || available_num < 2 || timeout < 1) @@ -4908,15 +4905,7 @@ error_code sceNpMatchingQuickMatchGUI(u32 ctx_id, vm::cptr } } - // TODO: set callback: handler + arg - - error_code err = CELL_OK; // QuickMatch - if (err != CELL_OK && static_cast(err) != SCE_NP_MATCHING_ERROR_BUSY) - { - // TODO ? - } - - return err; + return nph.quickmatch_gui(ctx_id, communicationId, cond, available_num, timeout, handler, arg); } error_code sceNpMatchingSendInvitationGUI(u32 ctx_id, vm::cptr room_id, vm::cptr communicationId, vm::cptr dsts, s32 num, s32 slot_type, @@ -4925,7 +4914,9 @@ error_code sceNpMatchingSendInvitationGUI(u32 ctx_id, vm::cptr room sceNp.todo("sceNpMatchingSendInvitationGUI(ctx_id=%d, room_id=*0x%x, communicationId=*0x%x, dsts=*0x%x, num=%d, slot_type=%d, subject=%s, body=%s, container=%d, handler=*0x%x, arg=*0x%x)", ctx_id, room_id, communicationId, dsts, num, slot_type, subject, body, container, handler, arg); - if (false) // TODO + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; if (!room_id || !communicationId || !subject || !body) // TODO: || (in_stack_0000007c != 0) @@ -4969,7 +4960,9 @@ error_code sceNpMatchingAcceptInvitationGUI(u32 ctx_id, vm::cptrget>(); + + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; if (!communicationId || !handler) @@ -5058,12 +5051,14 @@ error_code check_attr_create_room(vm::cptr attribute) return SCE_NP_MATCHING_ERROR_ATTR_NOT_SPECIFIED; } -error_code sceNpMatchingCreateRoomGUI(u32 ctx_id, vm::cptr communicationId, vm::cptr attr, vm::ptr handler, vm::ptr arg) +error_code matching_create_room(u32 ctx_id, vm::cptr communicationId, vm::cptr attr, vm::ptr handler, vm::ptr arg) { - sceNp.todo("sceNpMatchingCreateRoomGUI(ctx_id=%d, communicationId=*0x%x, attr=*0x%x, handler=*0x%x, arg=*0x%x)", ctx_id, communicationId, attr, handler, arg); + auto& nph = g_fxo->get>(); - if (false) // TODO + if (nph.is_NP2_Match2_init) + { return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; + } if (!communicationId || !handler) return SCE_NP_MATCHING_ERROR_INVALID_ARG; @@ -5073,69 +5068,66 @@ error_code sceNpMatchingCreateRoomGUI(u32 ctx_id, vm::cptr if (err != CELL_OK) return err; - if (false) // TODO - return SCE_NP_MATCHING_ERROR_BUSY; - - // TODO: set callback: handler + arg - - err = CELL_OK; // create_room - if (err != CELL_OK && static_cast(err) != SCE_NP_MATCHING_ERROR_BUSY) - { - // TODO ? - } - - return err; + return nph.create_room_gui(ctx_id, communicationId, attr, handler, arg); } -error_code sceNpMatchingJoinRoomGUI(u32 ctx_id, vm::ptr room_id, vm::ptr handler, vm::ptr arg) +error_code sceNpMatchingCreateRoomGUI(u32 ctx_id, vm::cptr communicationId, vm::cptr attr, vm::ptr handler, vm::ptr arg) { - sceNp.todo("sceNpMatchingJoinRoomGUI(ctx_id=%d, room_id=*0x%x, handler=*0x%x, arg=*0x%x)", ctx_id, room_id, handler, arg); + sceNp.warning("sceNpMatchingCreateRoomGUI(ctx_id=%d, communicationId=*0x%x, attr=*0x%x, handler=*0x%x, arg=*0x%x)", ctx_id, communicationId, attr, handler, arg); - if (false) // TODO + return matching_create_room(ctx_id, communicationId, attr, handler, arg); +} + +error_code matching_join_room(u32 ctx_id, vm::ptr room_id, vm::ptr handler, vm::ptr arg) +{ + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; if (!room_id || !handler) return SCE_NP_MATCHING_ERROR_INVALID_ARG; - if (false) // TODO - return SCE_NP_MATCHING_ERROR_BUSY; + return nph.join_room_gui(ctx_id, room_id, handler, arg); +} - // TODO: set callback: handler + arg +error_code sceNpMatchingJoinRoomGUI(u32 ctx_id, vm::ptr room_id, vm::ptr handler, vm::ptr arg) +{ + sceNp.warning("sceNpMatchingJoinRoomGUI(ctx_id=%d, room_id=*0x%x, handler=*0x%x, arg=*0x%x)", ctx_id, room_id, handler, arg); - error_code err = CELL_OK; // join_room - if (err != CELL_OK && static_cast(err) != SCE_NP_MATCHING_ERROR_BUSY) - { - // TODO ? - } - - return err; + return matching_join_room(ctx_id, room_id, handler, arg); } error_code sceNpMatchingLeaveRoom(u32 ctx_id, vm::cptr room_id, vm::ptr req_id) { - sceNp.todo("sceNpMatchingLeaveRoom(ctx_id=%d, room_id=*0x%x, req_id=*0x%x)", ctx_id, room_id, req_id); + sceNp.warning("sceNpMatchingLeaveRoom(ctx_id=%d, room_id=*0x%x, req_id=*0x%x)", ctx_id, room_id, req_id); - if (false) // TODO + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; - if (false) // TODO + if (!nph.is_NP_init) return SCE_NP_MATCHING_ERROR_NOT_INITIALIZED; - if (false) // TODO - return SCE_NP_MATCHING_ERROR_BUSY; + auto res = nph.leave_room_gui(ctx_id, room_id); - if (false) // TODO - return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; + if (res < 0) + return res; + + *req_id = res; return CELL_OK; } -error_code sceNpMatchingSearchJoinRoomGUI(u32 ctx_id, vm::cptr communicationId, vm::cptr cond, vm::cptr attribute, +error_code sceNpMatchingSearchJoinRoomGUI(u32 ctx_id, vm::cptr communicationId, vm::cptr cond, vm::cptr attr, vm::ptr handler, vm::ptr arg) { - sceNp.todo("sceNpMatchingSearchJoinRoomGUI(ctx_id=%d, communicationId=*0x%x, cond=*0x%x, attr=*0x%x, handler=*0x%x, arg=*0x%x)", ctx_id, communicationId, cond, attribute, handler, arg); + sceNp.warning("sceNpMatchingSearchJoinRoomGUI(ctx_id=%d, communicationId=*0x%x, cond=*0x%x, attr=*0x%x, handler=*0x%x, arg=*0x%x)", ctx_id, communicationId, cond, attr, handler, arg); - if (false) // TODO + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; if (!communicationId || !handler) @@ -5183,32 +5175,23 @@ error_code sceNpMatchingSearchJoinRoomGUI(u32 ctx_id, vm::cptr(err) != SCE_NP_MATCHING_ERROR_BUSY) - { - // TODO ? - } - - return err; + return nph.searchjoin_gui(ctx_id, communicationId, cond, attr, handler, arg); } error_code sceNpMatchingGrantOwnership(u32 ctx_id, vm::cptr room_id, vm::cptr user_id, vm::ptr req_id) { sceNp.todo("sceNpMatchingGrantOwnership(ctx_id=%d, room_id=*0x%x, user_id=*0x%x, req_id=*0x%x)", ctx_id, room_id, user_id, req_id); - if (false) // TODO + auto& nph = g_fxo->get>(); + + if (nph.is_NP2_Match2_init) return SCE_NP_MATCHING_ERROR_UTILITY_UNAVAILABLE; - if (false) // TODO + if (!nph.is_NP_init) return SCE_NP_MATCHING_ERROR_NOT_INITIALIZED; if (!room_id || !user_id || !req_id) @@ -6230,7 +6213,7 @@ error_code sceNpScoreGetRankingByNpIdPcIdAsync(s32 transId, SceNpScoreBoardId bo error_code sceNpScoreAbortTransaction(s32 transId) { - sceNp.todo("sceNpScoreAbortTransaction(transId=%d)", transId); + sceNp.warning("sceNpScoreAbortTransaction(transId=%d)", transId); auto& nph = g_fxo->get>(); diff --git a/rpcs3/Emu/Cell/Modules/sceNp.h b/rpcs3/Emu/Cell/Modules/sceNp.h index e32dba27b5..1adffccc5f 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp.h +++ b/rpcs3/Emu/Cell/Modules/sceNp.h @@ -677,6 +677,17 @@ enum SCE_NP_MATCHING_ATTR_TYPE_GAME_NUM = 4, }; +enum +{ + SCE_NP_MATCHING_ATTR_ID_MIN = 1, + SCE_NP_MATCHING_ATTR_ID_MAX = 16, + SCE_NP_MATCHING_ATTR_ID_FOR_SEARCH_CONDITION_MAX = 8, + SCE_NP_MATCHING_ATTR_ID_FOR_GRLGLIMIT_SRCH_COND_MAX = 8, + SCE_NP_MATCHING_ATTR_BIN_BIG_SIZE_ID_MAX = 2, + SCE_NP_MATCHING_ATTR_BIN_MAX_SIZE_SMALL = 64, + SCE_NP_MATCHING_ATTR_BIN_MAX_SIZE_BIG = 256, +}; + enum { SCE_NP_MATCHING_ROOM_ATTR_ID_TOTAL_SLOT = 1, @@ -686,6 +697,7 @@ enum SCE_NP_MATCHING_ROOM_ATTR_ID_CUR_PRIVATE_NUM = 5, SCE_NP_MATCHING_ROOM_ATTR_ID_PRIVILEGE_TYPE = 6, SCE_NP_MATCHING_ROOM_ATTR_ID_ROOM_SEARCH_FLAG = 7, + SCE_NP_MATCHING_ROOM_ATTR_ID_MAX = 8, }; enum @@ -706,6 +718,13 @@ enum SCE_NP_MATCHING_ROOM_SEARCH_FLAG_STEALTH = 1, }; +enum +{ + SCE_NP_MATCHING_COND_MAX = 9, + SCE_NP_MATCHING_GRLG_LIMIT_COND_MAX = 9, + SCE_NP_MATCHING_COMP_OP_INEQUALITY_MAX = 9, +}; + enum { SCE_NP_MATCHING_CONDITION_SEARCH_EQ = 0, @@ -714,6 +733,7 @@ enum SCE_NP_MATCHING_CONDITION_SEARCH_LE = 3, SCE_NP_MATCHING_CONDITION_SEARCH_GT = 4, SCE_NP_MATCHING_CONDITION_SEARCH_GE = 5, + SCE_NP_MATCHING_CONDITION_SEARCH_MAX = 6, }; enum @@ -724,6 +744,19 @@ enum enum { SCE_NP_MATCHING_INVITATION_DESTINATION_MAX = 12, + SCE_NP_MATCHING_INVITATION_SUBJECT_MAX_CHARS = 16, + SCE_NP_MATCHING_INVITATION_BODY_MAX_CHARS = 128, + + SCE_NP_MATCHING_KICK_OPT_MAX_LENGTH = 16, + + SCE_NP_MATCHING_ROOM_MAX_SLOT = 16, + SCE_NP_MATCHING_CTX_MAX = 8, +}; + +enum +{ + SCE_NP_MATCHING_SEND_INVITATION_MEMSIZE = 16 * 1024 * 1024, + SCE_NP_MATCHING_ACCEPT_INVITATION_MEMSIZE = 16 * 1024 * 1024, }; // Basic presence options @@ -1170,7 +1203,7 @@ enum SCE_NP_MATCHING_GUI_EVENT_ACCEPT_INVITATION = 0x0007, SCE_NP_MATCHING_GUI_EVENT_COMMON_LOAD = 0x0008, SCE_NP_MATCHING_GUI_EVENT_COMMON_UNLOAD = 0x0009, - SCE_NP_MATCHING_GUI_EVENT_RESERVED3 = 0x000a, + SCE_NP_MATCHING_GUI_EVENT_GET_ROOM_LIST = 0x000a, SCE_NP_MATCHING_GUI_EVENT_GET_ROOM_LIST_LIMIT = 0x000b }; @@ -1697,6 +1730,59 @@ struct SceNpScoreRecordOptParam vm::bptr reserved; }; +// Old GUI API structures + +struct SceNpMatchingRoomMember +{ + vm::bptr next; + SceNpUserInfo user_info; + be_t owner; +}; + +struct SceNpMatchingRoomStatus +{ + SceNpRoomId id; + vm::bptr members; + be_t num; + vm::bptr kick_actor; + vm::bptr opt; + be_t opt_len; +}; + +struct SceNpMatchingJoinedRoomInfo +{ + SceNpLobbyId lobbyid; + SceNpMatchingRoomStatus room_status; +}; + +struct SceNpMatchingRange +{ + be_t start; + be_t results; + be_t total; +}; + +struct SceNpMatchingRoom +{ + vm::bptr next; + SceNpRoomId id; + vm::bptr attr; +}; + +struct SceNpMatchingRoomList +{ + SceNpLobbyId lobbyid; + SceNpMatchingRange range; + vm::bptr head; +}; + +struct SceNpMatchingSearchJoinRoomInfo +{ + SceNpLobbyId lobbyid; + SceNpMatchingRoomStatus room_status; + vm::bptr attr; +}; + // NP callback functions using SceNpCustomMenuEventHandler = s32(s32 retCode, u32 index, vm::cptr npid, SceNpCustomMenuSelectedType type, vm::ptr arg); using SceNpBasicEventHandler = s32(s32 event, s32 retCode, u32 reqId, vm::ptr arg); @@ -1756,3 +1842,12 @@ public: protected: std::shared_ptr m_rpcn; }; + +// Generic functions, also used in SceNpMatchingInt.cpp +error_code matching_create_room(u32 ctx_id, vm::cptr communicationId, vm::cptr attr, vm::ptr handler, vm::ptr arg); +error_code matching_join_room(u32 ctx_id, vm::ptr room_id, vm::ptr handler, vm::ptr arg); +error_code matching_get_room_list(u32 ctx_id, vm::ptr communicationId, vm::ptr range, vm::ptr cond, + vm::ptr attr, vm::ptr handler, vm::ptr arg, bool limit); +error_code matching_set_room_info(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, vm::ptr attr, vm::ptr req_id, bool limit); +error_code matching_get_room_info(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, vm::ptr attr, vm::ptr req_id, bool limit); +error_code matching_get_room_member_list(u32 ctx_id, vm::ptr room_id, vm::ptr buflen, vm::ptr buf); diff --git a/rpcs3/Emu/Cell/Modules/sceNp2.cpp b/rpcs3/Emu/Cell/Modules/sceNp2.cpp index d9d7d74ebe..3398bb8157 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp2.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp2.cpp @@ -576,9 +576,9 @@ error_code sceNpMatching2ContextStart(SceNpMatching2ContextId ctxId) if (ctx->context_callback) { - sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32 + sysutil_register_cb([=, context_callback = ctx->context_callback, context_callback_param = ctx->context_callback_param](ppu_thread& cb_ppu) -> s32 { - ctx->context_callback(cb_ppu, ctxId, SCE_NP_MATCHING2_CONTEXT_EVENT_Start, SCE_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ACTION, 0, ctx->context_callback_param); + context_callback(cb_ppu, ctxId, SCE_NP_MATCHING2_CONTEXT_EVENT_Start, SCE_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ACTION, 0, context_callback_param); return 0; }); } @@ -1106,9 +1106,9 @@ error_code sceNpMatching2ContextStartAsync(SceNpMatching2ContextId ctxId, u32 ti if (ctx->context_callback) { - sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32 + sysutil_register_cb([=, context_callback = ctx->context_callback, context_callback_param = ctx->context_callback_param](ppu_thread& cb_ppu) -> s32 { - ctx->context_callback(cb_ppu, ctxId, SCE_NP_MATCHING2_CONTEXT_EVENT_Start, SCE_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ACTION, 0, ctx->context_callback_param); + context_callback(cb_ppu, ctxId, SCE_NP_MATCHING2_CONTEXT_EVENT_Start, SCE_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ACTION, 0, ctx->context_callback_param); return 0; }); } @@ -1709,9 +1709,9 @@ error_code sceNpMatching2ContextStop(SceNpMatching2ContextId ctxId) if (ctx->context_callback) { - sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32 + sysutil_register_cb([=, context_callback = ctx->context_callback, context_callback_param = ctx->context_callback_param](ppu_thread& cb_ppu) -> s32 { - ctx->context_callback(cb_ppu, ctxId, SCE_NP_MATCHING2_CONTEXT_EVENT_Stop, SCE_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ACTION, 0, ctx->context_callback_param); + context_callback(cb_ppu, ctxId, SCE_NP_MATCHING2_CONTEXT_EVENT_Stop, SCE_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ACTION, 0, context_callback_param); return 0; }); } diff --git a/rpcs3/Emu/Cell/Modules/sceNpCommerce2.cpp b/rpcs3/Emu/Cell/Modules/sceNpCommerce2.cpp index b86bab7055..d5f3f94f45 100644 --- a/rpcs3/Emu/Cell/Modules/sceNpCommerce2.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNpCommerce2.cpp @@ -220,9 +220,9 @@ error_code sceNpCommerce2EmptyStoreCheckStart(u32 ctx_id, s32 store_check_type, if (ctx->context_callback) { - sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32 + sysutil_register_cb([=, context_callback = ctx->context_callback, context_callback_param = ctx->context_callback_param](ppu_thread& cb_ppu) -> s32 { - ctx->context_callback(cb_ppu, ctx_id, 0, SCE_NP_COMMERCE2_EVENT_EMPTY_STORE_CHECK_DONE, 0, ctx->context_callback_param); + context_callback(cb_ppu, ctx_id, 0, SCE_NP_COMMERCE2_EVENT_EMPTY_STORE_CHECK_DONE, 0, context_callback_param); return 0; }); } @@ -276,9 +276,9 @@ error_code sceNpCommerce2CreateSessionStart(u32 ctx_id) if (ctx->context_callback) { - sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32 + sysutil_register_cb([=, context_callback = ctx->context_callback, context_callback_param = ctx->context_callback_param](ppu_thread& cb_ppu) -> s32 { - ctx->context_callback(cb_ppu, ctx_id, 0, SCE_NP_COMMERCE2_EVENT_CREATE_SESSION_DONE, 0, ctx->context_callback_param); + context_callback(cb_ppu, ctx_id, 0, SCE_NP_COMMERCE2_EVENT_CREATE_SESSION_DONE, 0, context_callback_param); return 0; }); } diff --git a/rpcs3/Emu/Cell/Modules/sceNpMatchingInt.cpp b/rpcs3/Emu/Cell/Modules/sceNpMatchingInt.cpp index 099f7997d6..d21f6f7fc0 100644 --- a/rpcs3/Emu/Cell/Modules/sceNpMatchingInt.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNpMatchingInt.cpp @@ -1,10 +1,6 @@ #include "stdafx.h" #include "Emu/Cell/PPUModule.h" - -// Temporarily -#ifndef _MSC_VER -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif +#include "sceNp.h" LOG_CHANNEL(sceNpMatchingInt); @@ -14,48 +10,55 @@ error_code sceNpMatchingCancelRequest() return CELL_OK; } -error_code sceNpMatchingGetRoomMemberList() +error_code sceNpMatchingGetRoomMemberList(u32 ctx_id, vm::ptr room_id, vm::ptr buflen, vm::ptr buf) { - UNIMPLEMENTED_FUNC(sceNpMatchingInt); - return CELL_OK; + sceNpMatchingInt.warning("sceNpMatchingGetRoomMemberList(ctx_id=%d, room_id=*0x%x, buflen=*0x%x, buf=*0x%x)", ctx_id, room_id, buflen, buf); + + return matching_get_room_member_list(ctx_id, room_id, buflen, buf); } -error_code sceNpMatchingJoinRoomWithoutGUI() +error_code sceNpMatchingJoinRoomWithoutGUI(u32 ctx_id, vm::ptr room_id, vm::ptr handler, vm::ptr arg) { - UNIMPLEMENTED_FUNC(sceNpMatchingInt); - return CELL_OK; + sceNpMatchingInt.warning("sceNpMatchingJoinRoomWithoutGUI(ctx_id=%d, room_id=*0x%x, handler=*0x%x, arg=*0x%x)", ctx_id, room_id, handler, arg); + + return matching_join_room(ctx_id, room_id, handler, arg); } -// Parameter "unknown" added to distinguish this function -// from the one in sceNp.cpp which has the same name -error_code sceNpMatchingJoinRoomGUI(vm::ptr unknown) +error_code OLD_sceNpMatchingJoinRoomGUI(u32 ctx_id, vm::ptr room_id, vm::ptr handler, vm::ptr arg) { - UNIMPLEMENTED_FUNC(sceNpMatchingInt); - return CELL_OK; + sceNpMatchingInt.warning("OLD_sceNpMatchingJoinRoomGUI(ctx_id=%d, room_id=*0x%x, handler=*0x%x, arg=*0x%x)", ctx_id, room_id, handler, arg); + + return matching_join_room(ctx_id, room_id, handler, arg); } -error_code sceNpMatchingSetRoomInfoNoLimit(vm::ptr unknown) +error_code OLD_sceNpMatchingSetRoomInfoNoLimit(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, vm::ptr attr, vm::ptr req_id) { - UNIMPLEMENTED_FUNC(sceNpMatchingInt); - return CELL_OK; + sceNpMatchingInt.warning("OLD_sceNpMatchingSetRoomInfoNoLimit(ctx_id=%d, lobby_id=*0x%x, room_id=*0x%x, attr=*0x%x, req_id=*0x%x)", ctx_id, lobby_id, room_id, attr, req_id); + + return matching_set_room_info(ctx_id, lobby_id, room_id, attr, req_id, false); } -error_code sceNpMatchingGetRoomListWithoutGUI() +error_code sceNpMatchingGetRoomListWithoutGUI(u32 ctx_id, vm::ptr communicationId, vm::ptr range, vm::ptr cond, + vm::ptr attr, vm::ptr handler, vm::ptr arg) { - UNIMPLEMENTED_FUNC(sceNpMatchingInt); - return CELL_OK; + sceNpMatchingInt.warning("sceNpMatchingGetRoomListWithoutGUI(ctx_id=%d, communicationId=*0x%x, range=*0x%x, cond=*0x%x, attr=*0x%x, handler=*0x%x, arg=*0x%x)", ctx_id, communicationId, range, cond, attr, handler, arg); + + return matching_get_room_list(ctx_id, communicationId, range, cond, attr, handler, arg, false); } -error_code sceNpMatchingGetRoomListGUI() +error_code sceNpMatchingGetRoomListGUI(u32 ctx_id, vm::ptr communicationId, vm::ptr range, vm::ptr cond, + vm::ptr attr, vm::ptr handler, vm::ptr arg) { - UNIMPLEMENTED_FUNC(sceNpMatchingInt); - return CELL_OK; + sceNpMatchingInt.warning("sceNpMatchingGetRoomListGUI(ctx_id=%d, communicationId=*0x%x, range=*0x%x, cond=*0x%x, attr=*0x%x, handler=*0x%x, arg=*0x%x)", ctx_id, communicationId, range, cond, attr, handler, arg); + + return matching_get_room_list(ctx_id, communicationId, range, cond, attr, handler, arg, false); } -error_code sceNpMatchingGetRoomInfoNoLimit(vm::ptr unknown) +error_code OLD_sceNpMatchingGetRoomInfoNoLimit(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, vm::ptr attr, vm::ptr req_id) { - UNIMPLEMENTED_FUNC(sceNpMatchingInt); - return CELL_OK; + sceNpMatchingInt.warning("OLD_sceNpMatchingGetRoomInfoNoLimit(ctx_id=%d, lobby_id=*0x%x, room_id=*0x%x, attr=*0x%x, req_id=*0x%x)", ctx_id, lobby_id, room_id, attr, req_id); + + return matching_get_room_info(ctx_id, lobby_id, room_id, attr, req_id, false); } error_code sceNpMatchingCancelRequestGUI() @@ -70,22 +73,27 @@ error_code sceNpMatchingSendRoomMessage() return CELL_OK; } -error_code sceNpMatchingCreateRoomWithoutGUI() +error_code sceNpMatchingCreateRoomWithoutGUI(u32 ctx_id, vm::cptr communicationId, vm::cptr attr, vm::ptr handler, vm::ptr arg) { - UNIMPLEMENTED_FUNC(sceNpMatchingInt); - return CELL_OK; + sceNpMatchingInt.warning("sceNpMatchingCreateRoomWithoutGUI(ctx_id=%d, communicationId=*0x%x, attr=*0x%x, handler=*0x%x, arg=*0x%x)", ctx_id, communicationId, attr, handler, arg); + + return matching_create_room(ctx_id, communicationId, attr, handler, arg); } +// This module has some conflicting function names with sceNp module, hence the REG_FNID DECLARE(ppu_module_manager::sceNpMatchingInt)("sceNpMatchingInt", []() { REG_FUNC(sceNpMatchingInt, sceNpMatchingCancelRequest); REG_FUNC(sceNpMatchingInt, sceNpMatchingGetRoomMemberList); REG_FUNC(sceNpMatchingInt, sceNpMatchingJoinRoomWithoutGUI); - REG_FUNC(sceNpMatchingInt, sceNpMatchingJoinRoomGUI); - REG_FUNC(sceNpMatchingInt, sceNpMatchingSetRoomInfoNoLimit); + // REG_FUNC(sceNpMatchingInt, sceNpMatchingJoinRoomGUI); + REG_FNID(sceNpMatchingInt, "sceNpMatchingJoinRoomGUI", OLD_sceNpMatchingJoinRoomGUI); + // REG_FUNC(sceNpMatchingInt, sceNpMatchingSetRoomInfoNoLimit); + REG_FNID(sceNpMatchingInt, "sceNpMatchingSetRoomInfoNoLimit", OLD_sceNpMatchingSetRoomInfoNoLimit); REG_FUNC(sceNpMatchingInt, sceNpMatchingGetRoomListWithoutGUI); REG_FUNC(sceNpMatchingInt, sceNpMatchingGetRoomListGUI); - REG_FUNC(sceNpMatchingInt, sceNpMatchingGetRoomInfoNoLimit); + // REG_FUNC(sceNpMatchingInt, sceNpMatchingGetRoomInfoNoLimit); + REG_FNID(sceNpMatchingInt, "sceNpMatchingGetRoomInfoNoLimit", OLD_sceNpMatchingGetRoomInfoNoLimit); REG_FUNC(sceNpMatchingInt, sceNpMatchingCancelRequestGUI); REG_FUNC(sceNpMatchingInt, sceNpMatchingSendRoomMessage); REG_FUNC(sceNpMatchingInt, sceNpMatchingCreateRoomWithoutGUI); diff --git a/rpcs3/Emu/NP/fb_helpers.cpp b/rpcs3/Emu/NP/fb_helpers.cpp index 35f4a86382..04a92d77ee 100644 --- a/rpcs3/Emu/NP/fb_helpers.cpp +++ b/rpcs3/Emu/NP/fb_helpers.cpp @@ -1,12 +1,13 @@ #include "stdafx.h" #include "np_handler.h" #include "Emu/Cell/lv2/sys_process.h" +#include "fb_helpers.h" LOG_CHANNEL(rpcn_log, "rpcn"); namespace np { - void np_handler::BinAttr_to_SceNpMatching2BinAttr(event_data& edata, const BinAttr* bin_attr, SceNpMatching2BinAttr* binattr_info) + void BinAttr_to_SceNpMatching2BinAttr(event_data& edata, const BinAttr* bin_attr, SceNpMatching2BinAttr* binattr_info) { binattr_info->id = bin_attr->id(); binattr_info->size = bin_attr->data()->size(); @@ -17,7 +18,7 @@ namespace np } } - void np_handler::BinAttrs_to_SceNpMatching2BinAttrs(event_data& edata, const flatbuffers::Vector>* fb_attr, SceNpMatching2BinAttr* binattr_info) + void BinAttrs_to_SceNpMatching2BinAttrs(event_data& edata, const flatbuffers::Vector>* fb_attr, SceNpMatching2BinAttr* binattr_info) { for (flatbuffers::uoffset_t i = 0; i < fb_attr->size(); i++) { @@ -28,20 +29,20 @@ namespace np } } - void np_handler::RoomMemberBinAttrInternal_to_SceNpMatching2RoomMemberBinAttrInternal(event_data& edata, const RoomMemberBinAttrInternal* fb_attr, SceNpMatching2RoomMemberBinAttrInternal* binattr_info) + void RoomMemberBinAttrInternal_to_SceNpMatching2RoomMemberBinAttrInternal(event_data& edata, const RoomMemberBinAttrInternal* fb_attr, SceNpMatching2RoomMemberBinAttrInternal* binattr_info) { binattr_info->updateDate.tick = fb_attr->updateDate(); BinAttr_to_SceNpMatching2BinAttr(edata, fb_attr->data(), &binattr_info->data); } - void np_handler::RoomBinAttrInternal_to_SceNpMatching2RoomBinAttrInternal(event_data& edata, const BinAttrInternal* fb_attr, SceNpMatching2RoomBinAttrInternal* binattr_info) + void RoomBinAttrInternal_to_SceNpMatching2RoomBinAttrInternal(event_data& edata, const BinAttrInternal* fb_attr, SceNpMatching2RoomBinAttrInternal* binattr_info) { binattr_info->updateDate.tick = fb_attr->updateDate(); binattr_info->updateMemberId = fb_attr->updateMemberId(); BinAttr_to_SceNpMatching2BinAttr(edata, fb_attr->data(), &binattr_info->data); } - void np_handler::RoomGroup_to_SceNpMatching2RoomGroup(const RoomGroup* fb_group, SceNpMatching2RoomGroup* sce_group) + void RoomGroup_to_SceNpMatching2RoomGroup(const RoomGroup* fb_group, SceNpMatching2RoomGroup* sce_group) { sce_group->groupId = fb_group->groupId(); sce_group->withPassword = fb_group->withPassword(); @@ -57,7 +58,7 @@ namespace np sce_group->curGroupMemberNum = fb_group->curGroupMemberNum(); } - void np_handler::RoomGroups_to_SceNpMatching2RoomGroups(const flatbuffers::Vector>* fb_groups, SceNpMatching2RoomGroup* sce_groups) + void RoomGroups_to_SceNpMatching2RoomGroups(const flatbuffers::Vector>* fb_groups, SceNpMatching2RoomGroup* sce_groups) { for (flatbuffers::uoffset_t i = 0; i < fb_groups->size(); i++) { @@ -67,7 +68,25 @@ namespace np } } - void np_handler::UserInfo2_to_SceNpUserInfo2(event_data& edata, const UserInfo2* user, SceNpUserInfo2* user_info, bool include_onlinename, bool include_avatarurl) + void UserInfo_to_SceNpUserInfo(const UserInfo* user, SceNpUserInfo* user_info) + { + if (const auto npid = user->npId(); npid) + { + std::memcpy(user_info->userId.handle.data, npid->c_str(), std::min(16, npid->size())); + } + + if (const auto online_name = user->onlineName(); online_name) + { + std::memcpy(user_info->name.data, online_name->c_str(), std::min(48, online_name->size())); + } + + if (const auto avatar_url = user->avatarUrl(); avatar_url) + { + std::memcpy(user_info->icon.data, avatar_url->c_str(), std::min(127, avatar_url->size())); + } + } + + void UserInfo_to_SceNpUserInfo2(event_data& edata, const UserInfo* user, SceNpUserInfo2* user_info, bool include_onlinename, bool include_avatarurl) { if (user->npId()) std::memcpy(user_info->npId.handle.data, user->npId()->c_str(), std::min(16, user->npId()->size())); @@ -84,7 +103,7 @@ namespace np } } - void np_handler::RoomDataExternal_to_SceNpMatching2RoomDataExternal(event_data& edata, const RoomDataExternal* room, SceNpMatching2RoomDataExternal* room_info, bool include_onlinename, bool include_avatarurl) + void RoomDataExternal_to_SceNpMatching2RoomDataExternal(event_data& edata, const RoomDataExternal* room, SceNpMatching2RoomDataExternal* room_info, bool include_onlinename, bool include_avatarurl) { room_info->serverId = room->serverId(); room_info->worldId = room->worldId(); @@ -116,7 +135,7 @@ namespace np if (auto owner = room->owner()) { auto* ptr_owner = edata.allocate(sizeof(SceNpUserInfo2), room_info->owner); - UserInfo2_to_SceNpUserInfo2(edata, owner, ptr_owner, include_onlinename, include_avatarurl); + UserInfo_to_SceNpUserInfo2(edata, owner, ptr_owner, include_onlinename, include_avatarurl); } if (room->roomGroup() && room->roomGroup()->size() != 0) @@ -155,30 +174,24 @@ namespace np } } - void np_handler::SearchRoomResponse_to_SceNpMatching2SearchRoomResponse(event_data& edata, const SearchRoomResponse* resp, SceNpMatching2SearchRoomResponse* search_resp) + void SearchRoomResponse_to_SceNpMatching2SearchRoomResponse(event_data& edata, const SearchRoomResponse* resp, SceNpMatching2SearchRoomResponse* search_resp) { - search_resp->range.size = resp->size(); + search_resp->range.size = resp->rooms() ? resp->rooms()->size() : 0; search_resp->range.startIndex = resp->startIndex(); search_resp->range.total = resp->total(); - if (resp->rooms() && resp->rooms()->size() != 0) + SceNpMatching2RoomDataExternal* prev_room = nullptr; + for (flatbuffers::uoffset_t i = 0; i < search_resp->range.size; i++) { - SceNpMatching2RoomDataExternal* prev_room = nullptr; - for (flatbuffers::uoffset_t i = 0; i < resp->rooms()->size(); i++) - { - auto* fb_room = resp->rooms()->Get(i); - SceNpMatching2RoomDataExternal* cur_room; - - cur_room = (i > 0) ? edata.allocate(sizeof(SceNpMatching2RoomDataExternal), prev_room->next) : - edata.allocate(sizeof(SceNpMatching2RoomDataExternal), search_resp->roomDataExternal); - - RoomDataExternal_to_SceNpMatching2RoomDataExternal(edata, fb_room, cur_room, true, true); - prev_room = cur_room; - } + auto* fb_room = resp->rooms()->Get(i); + SceNpMatching2RoomDataExternal* cur_room; + cur_room = edata.allocate(sizeof(SceNpMatching2RoomDataExternal), (i > 0) ? prev_room->next : search_resp->roomDataExternal); + RoomDataExternal_to_SceNpMatching2RoomDataExternal(edata, fb_room, cur_room, true, true); + prev_room = cur_room; } } - void np_handler::GetRoomDataExternalListResponse_to_SceNpMatching2GetRoomDataExternalListResponse(event_data& edata, const GetRoomDataExternalListResponse* resp, SceNpMatching2GetRoomDataExternalListResponse* get_resp, bool include_onlinename, bool include_avatarurl) + void GetRoomDataExternalListResponse_to_SceNpMatching2GetRoomDataExternalListResponse(event_data& edata, const GetRoomDataExternalListResponse* resp, SceNpMatching2GetRoomDataExternalListResponse* get_resp, bool include_onlinename, bool include_avatarurl) { get_resp->roomDataExternalNum = resp->rooms() ? resp->rooms()->size() : 0; @@ -188,15 +201,14 @@ namespace np auto* fb_room = resp->rooms()->Get(i); SceNpMatching2RoomDataExternal* cur_room; - cur_room = (i > 0) ? edata.allocate(sizeof(SceNpMatching2RoomDataExternal), prev_room->next) : - edata.allocate(sizeof(SceNpMatching2RoomDataExternal), get_resp->roomDataExternal); + cur_room = edata.allocate(sizeof(SceNpMatching2RoomDataExternal), (i > 0) ? prev_room->next : get_resp->roomDataExternal); RoomDataExternal_to_SceNpMatching2RoomDataExternal(edata, fb_room, cur_room, include_onlinename, include_avatarurl); prev_room = cur_room; } } - u16 np_handler::RoomDataInternal_to_SceNpMatching2RoomDataInternal(event_data& edata, const RoomDataInternal* resp, SceNpMatching2RoomDataInternal* room_info, const SceNpId& npid, bool include_onlinename, bool include_avatarurl) + u16 RoomDataInternal_to_SceNpMatching2RoomDataInternal(event_data& edata, const RoomDataInternal* resp, SceNpMatching2RoomDataInternal* room_info, const SceNpId& npid, bool include_onlinename, bool include_avatarurl) { u16 member_id = 0; room_info->serverId = resp->serverId(); @@ -279,9 +291,9 @@ namespace np return member_id; } - void np_handler::RoomMemberDataInternal_to_SceNpMatching2RoomMemberDataInternal(event_data& edata, const RoomMemberDataInternal* member_data, const SceNpMatching2RoomDataInternal* room_info, SceNpMatching2RoomMemberDataInternal* sce_member_data, bool include_onlinename, bool include_avatarurl) + void RoomMemberDataInternal_to_SceNpMatching2RoomMemberDataInternal(event_data& edata, const RoomMemberDataInternal* member_data, const SceNpMatching2RoomDataInternal* room_info, SceNpMatching2RoomMemberDataInternal* sce_member_data, bool include_onlinename, bool include_avatarurl) { - UserInfo2_to_SceNpUserInfo2(edata, member_data->userInfo(), &sce_member_data->userInfo, include_onlinename, include_avatarurl); + UserInfo_to_SceNpUserInfo2(edata, member_data->userInfo(), &sce_member_data->userInfo, include_onlinename, include_avatarurl); sce_member_data->joinDate.tick = member_data->joinDate(); sce_member_data->memberId = member_data->memberId(); sce_member_data->teamId = member_data->teamId(); @@ -325,7 +337,7 @@ namespace np } } - void np_handler::RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo(event_data& edata, const RoomMemberUpdateInfo* update_info, SceNpMatching2RoomMemberUpdateInfo* sce_update_info, bool include_onlinename, bool include_avatarurl) + void RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo(event_data& edata, const RoomMemberUpdateInfo* update_info, SceNpMatching2RoomMemberUpdateInfo* sce_update_info, bool include_onlinename, bool include_avatarurl) { sce_update_info->eventCause = 0; if (update_info->optData()) @@ -347,7 +359,7 @@ namespace np } } - void np_handler::RoomUpdateInfo_to_SceNpMatching2RoomUpdateInfo(const RoomUpdateInfo* update_info, SceNpMatching2RoomUpdateInfo* sce_update_info) + void RoomUpdateInfo_to_SceNpMatching2RoomUpdateInfo(const RoomUpdateInfo* update_info, SceNpMatching2RoomUpdateInfo* sce_update_info) { sce_update_info->errorCode = 0; sce_update_info->eventCause = 0; @@ -361,7 +373,7 @@ namespace np } } - void np_handler::RoomDataInternalUpdateInfo_to_SceNpMatching2RoomDataInternalUpdateInfo(event_data& edata, const RoomDataInternalUpdateInfo* update_info, SceNpMatching2RoomDataInternalUpdateInfo* sce_update_info, const SceNpId& npid, bool include_onlinename, bool include_avatarurl) + void RoomDataInternalUpdateInfo_to_SceNpMatching2RoomDataInternalUpdateInfo(event_data& edata, const RoomDataInternalUpdateInfo* update_info, SceNpMatching2RoomDataInternalUpdateInfo* sce_update_info, const SceNpId& npid, bool include_onlinename, bool include_avatarurl) { auto* sce_room_data = edata.allocate(sizeof(SceNpMatching2RoomDataInternal), sce_update_info->newRoomDataInternal); RoomDataInternal_to_SceNpMatching2RoomDataInternal(edata, update_info->newRoomDataInternal(), sce_room_data, npid, include_onlinename, include_avatarurl); @@ -417,7 +429,7 @@ namespace np } } - void np_handler::RoomMemberDataInternalUpdateInfo_to_SceNpMatching2RoomMemberDataInternalUpdateInfo(event_data& edata, const RoomMemberDataInternalUpdateInfo* update_info, SceNpMatching2RoomMemberDataInternalUpdateInfo* sce_update_info, bool include_onlinename, bool include_avatarurl) + void RoomMemberDataInternalUpdateInfo_to_SceNpMatching2RoomMemberDataInternalUpdateInfo(event_data& edata, const RoomMemberDataInternalUpdateInfo* update_info, SceNpMatching2RoomMemberDataInternalUpdateInfo* sce_update_info, bool include_onlinename, bool include_avatarurl) { auto* sce_room_member_data = edata.allocate(sizeof(SceNpMatching2RoomMemberDataInternal), sce_update_info->newRoomMemberDataInternal); RoomMemberDataInternal_to_SceNpMatching2RoomMemberDataInternal(edata, update_info->newRoomMemberDataInternal(), nullptr, sce_room_member_data, include_onlinename, include_avatarurl); @@ -461,7 +473,7 @@ namespace np } } - void np_handler::GetPingInfoResponse_to_SceNpMatching2SignalingGetPingInfoResponse(const GetPingInfoResponse* resp, SceNpMatching2SignalingGetPingInfoResponse* sce_resp) + void GetPingInfoResponse_to_SceNpMatching2SignalingGetPingInfoResponse(const GetPingInfoResponse* resp, SceNpMatching2SignalingGetPingInfoResponse* sce_resp) { sce_resp->serverId = resp->serverId(); sce_resp->worldId = resp->worldId(); @@ -469,7 +481,7 @@ namespace np sce_resp->rtt = resp->rtt(); } - void np_handler::RoomMessageInfo_to_SceNpMatching2RoomMessageInfo(event_data& edata, const RoomMessageInfo* mi, SceNpMatching2RoomMessageInfo* sce_mi, bool include_onlinename, bool include_avatarurl) + void RoomMessageInfo_to_SceNpMatching2RoomMessageInfo(event_data& edata, const RoomMessageInfo* mi, SceNpMatching2RoomMessageInfo* sce_mi, bool include_onlinename, bool include_avatarurl) { sce_mi->filtered = mi->filtered(); sce_mi->castType = mi->castType(); @@ -500,7 +512,7 @@ namespace np if (auto src_member = mi->srcMember()) { auto* ptr_sce_userinfo = edata.allocate(sizeof(SceNpUserInfo2), sce_mi->srcMember); - UserInfo2_to_SceNpUserInfo2(edata, src_member, ptr_sce_userinfo, include_onlinename, include_avatarurl); + UserInfo_to_SceNpUserInfo2(edata, src_member, ptr_sce_userinfo, include_onlinename, include_avatarurl); } if (auto msg = mi->msg()) @@ -513,4 +525,127 @@ namespace np } } } + + void MatchingRoomStatus_to_SceNpMatchingRoomStatus(event_data& edata, const MatchingRoomStatus* resp, SceNpMatchingRoomStatus* room_status) + { + const auto* vec_id = resp->id(); + ensure(vec_id && vec_id->size() == 28, "Invalid room id in MatchingRoomStatus"); + + for (flatbuffers::uoffset_t i = 0; i < 28; i++) + { + room_status->id.opt[i] = vec_id->Get(i); + } + + // In some events the member list can be empty + if (const auto* members = resp->members(); members && members->size()) + { + room_status->num = members->size(); + SceNpMatchingRoomMember* prev_member{}; + + for (flatbuffers::uoffset_t i = 0; i < members->size(); i++) + { + auto* cur_member = edata.allocate(sizeof(SceNpMatchingRoomMember), (i > 0) ? prev_member->next : room_status->members); + const auto* member = members->Get(i); + ensure(member && member->info(), "Invalid member in MatchingRoomStatus list"); + + cur_member->owner = member->owner() ? 1 : 0; + UserInfo_to_SceNpUserInfo(member->info(), &cur_member->user_info); + + prev_member = cur_member; + } + } + + if (const auto* kick_npid = resp->kick_actor(); kick_npid) + { + auto* npid = edata.allocate(sizeof(SceNpId), room_status->kick_actor); + std::memcpy(npid->handle.data, kick_npid->c_str(), std::min(16, kick_npid->size())); + } + + if (const auto* opt = resp->opt(); opt && opt->size()) + { + room_status->opt_len = opt->size(); + u8* opt_data = static_cast(edata.allocate(opt->size(), room_status->opt)); + + for (flatbuffers::uoffset_t i = 0; i < opt->size(); i++) + { + opt_data[i] = opt->Get(i); + } + } + } + + void MatchingRoomStatus_to_SceNpMatchingJoinedRoomInfo(event_data& edata, const MatchingRoomStatus* resp, SceNpMatchingJoinedRoomInfo* room_info) + { + // The use of SceNpLobbyId is unclear as it is never specified by the client except in further operations, so we always set it to a series of 0 and a 1 + room_info->lobbyid.opt[27] = 1; + MatchingRoomStatus_to_SceNpMatchingRoomStatus(edata, resp, &room_info->room_status); + } + + void MatchingAttr_to_SceNpMatchingAttr(event_data& edata, const flatbuffers::Vector>* attr_list, vm::bptr& first_attr) + { + if (attr_list) + { + SceNpMatchingAttr* cur_attr = nullptr; + + for (flatbuffers::uoffset_t i_attr = 0; i_attr < attr_list->size(); i_attr++) + { + const auto* attr = attr_list->Get(i_attr); + cur_attr = edata.allocate(sizeof(SceNpMatchingAttr), cur_attr ? cur_attr->next : first_attr); + + ensure(attr); + cur_attr->type = attr->attr_type(); + cur_attr->id = attr->attr_id(); + if (attr->data()) + { + if (attr->data()->size()) + { + cur_attr->value.data.size = attr->data()->size(); + u8* data_ptr = static_cast(edata.allocate(attr->data()->size(), cur_attr->value.data.ptr)); + memcpy(data_ptr, attr->data()->data(), attr->data()->size()); + } + } + else + { + cur_attr->value.num = attr->num(); + } + } + } + } + + void MatchingRoom_to_SceNpMatchingRoom(event_data& edata, const MatchingRoom* resp, SceNpMatchingRoom* room) + { + ensure(room && resp->id() && resp->id()->size() == sizeof(SceNpRoomId::opt)); + memcpy(room->id.opt, resp->id()->data(), sizeof(SceNpRoomId::opt)); + MatchingAttr_to_SceNpMatchingAttr(edata, resp->attr(), room->attr); + } + + void MatchingRoomList_to_SceNpMatchingRoomList(event_data& edata, const MatchingRoomList* resp, SceNpMatchingRoomList* room_list) + { + // The use of SceNpLobbyId is unclear as it is never specified by the client except in further operations, so we always set it to a series of 0 and a 1 + room_list->lobbyid.opt[27] = 1; + room_list->range.start = resp->start(); + room_list->range.total = resp->total(); + + if (auto rooms = resp->rooms(); rooms) + { + room_list->range.results = rooms->size(); + + SceNpMatchingRoom* cur_room = nullptr; + + for (flatbuffers::uoffset_t i = 0; i < rooms->size(); i++) + { + const auto* room = rooms->Get(i); + cur_room = edata.allocate(sizeof(SceNpMatchingRoom), cur_room ? cur_room->next : room_list->head); + MatchingRoom_to_SceNpMatchingRoom(edata, room, cur_room); + } + } + } + + void MatchingSearchJoinRoomInfo_to_SceNpMatchingSearchJoinRoomInfo(event_data& edata, const MatchingSearchJoinRoomInfo* resp, SceNpMatchingSearchJoinRoomInfo* room_info) + { + ensure(resp->room()); + room_info->lobbyid.opt[27] = 1; + MatchingRoomStatus_to_SceNpMatchingRoomStatus(edata, resp->room(), &room_info->room_status); + MatchingAttr_to_SceNpMatchingAttr(edata, resp->attr(), room_info->attr); + } + } // namespace np diff --git a/rpcs3/Emu/NP/fb_helpers.h b/rpcs3/Emu/NP/fb_helpers.h new file mode 100644 index 0000000000..82ab034ea2 --- /dev/null +++ b/rpcs3/Emu/NP/fb_helpers.h @@ -0,0 +1,29 @@ +#pragma once + +namespace np +{ + void BinAttr_to_SceNpMatching2BinAttr(event_data& edata, const BinAttr* bin_attr, SceNpMatching2BinAttr* binattr_info); + void BinAttrs_to_SceNpMatching2BinAttrs(event_data& edata, const flatbuffers::Vector>* fb_attr, SceNpMatching2BinAttr* binattr_info); + void RoomMemberBinAttrInternal_to_SceNpMatching2RoomMemberBinAttrInternal(event_data& edata, const RoomMemberBinAttrInternal* fb_attr, SceNpMatching2RoomMemberBinAttrInternal* binattr_info); + void RoomBinAttrInternal_to_SceNpMatching2RoomBinAttrInternal(event_data& edata, const BinAttrInternal* fb_attr, SceNpMatching2RoomBinAttrInternal* binattr_info); + void RoomGroup_to_SceNpMatching2RoomGroup(const RoomGroup* fb_group, SceNpMatching2RoomGroup* sce_group); + void RoomGroups_to_SceNpMatching2RoomGroups(const flatbuffers::Vector>* fb_groups, SceNpMatching2RoomGroup* sce_groups); + void UserInfo_to_SceNpUserInfo(const UserInfo* user, SceNpUserInfo* user_info); + void UserInfo_to_SceNpUserInfo2(event_data& edata, const UserInfo* user, SceNpUserInfo2* user_info, bool include_onlinename, bool include_avatarurl); + void RoomDataExternal_to_SceNpMatching2RoomDataExternal(event_data& edata, const RoomDataExternal* room, SceNpMatching2RoomDataExternal* room_info, bool include_onlinename, bool include_avatarurl); + void SearchRoomResponse_to_SceNpMatching2SearchRoomResponse(event_data& edata, const SearchRoomResponse* resp, SceNpMatching2SearchRoomResponse* search_resp); + void GetRoomDataExternalListResponse_to_SceNpMatching2GetRoomDataExternalListResponse(event_data& edata, const GetRoomDataExternalListResponse* resp, SceNpMatching2GetRoomDataExternalListResponse* get_resp, bool include_onlinename, bool include_avatarurl); + u16 RoomDataInternal_to_SceNpMatching2RoomDataInternal(event_data& edata, const RoomDataInternal* resp, SceNpMatching2RoomDataInternal* room_resp, const SceNpId& npid, bool include_onlinename, bool include_avatarurl); + void RoomMemberDataInternal_to_SceNpMatching2RoomMemberDataInternal(event_data& edata, const RoomMemberDataInternal* member_data, const SceNpMatching2RoomDataInternal* room_info, SceNpMatching2RoomMemberDataInternal* sce_member_data, bool include_onlinename, bool include_avatarurl); + void RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo(event_data& edata, const RoomMemberUpdateInfo* resp, SceNpMatching2RoomMemberUpdateInfo* room_info, bool include_onlinename, bool include_avatarurl); + void RoomUpdateInfo_to_SceNpMatching2RoomUpdateInfo(const RoomUpdateInfo* update_info, SceNpMatching2RoomUpdateInfo* sce_update_info); + void GetPingInfoResponse_to_SceNpMatching2SignalingGetPingInfoResponse(const GetPingInfoResponse* resp, SceNpMatching2SignalingGetPingInfoResponse* sce_resp); + void RoomMessageInfo_to_SceNpMatching2RoomMessageInfo(event_data& edata, const RoomMessageInfo* mi, SceNpMatching2RoomMessageInfo* sce_mi, bool include_onlinename, bool include_avatarurl); + void RoomDataInternalUpdateInfo_to_SceNpMatching2RoomDataInternalUpdateInfo(event_data& edata, const RoomDataInternalUpdateInfo* update_info, SceNpMatching2RoomDataInternalUpdateInfo* sce_update_info, const SceNpId& npid, bool include_onlinename, bool include_avatarurl); + void RoomMemberDataInternalUpdateInfo_to_SceNpMatching2RoomMemberDataInternalUpdateInfo(event_data& edata, const RoomMemberDataInternalUpdateInfo* update_info, SceNpMatching2RoomMemberDataInternalUpdateInfo* sce_update_info, bool include_onlinename, bool include_avatarurl); + void MatchingRoomStatus_to_SceNpMatchingRoomStatus(event_data& edata, const MatchingRoomStatus* resp, SceNpMatchingRoomStatus* room_status); + void MatchingRoomStatus_to_SceNpMatchingJoinedRoomInfo(event_data& edata, const MatchingRoomStatus* resp, SceNpMatchingJoinedRoomInfo* room_info); + void MatchingRoom_to_SceNpMatchingRoom(event_data& edata, const MatchingRoom* resp, SceNpMatchingRoom* room); + void MatchingRoomList_to_SceNpMatchingRoomList(event_data& edata, const MatchingRoomList* resp, SceNpMatchingRoomList* room_list); + void MatchingSearchJoinRoomInfo_to_SceNpMatchingSearchJoinRoomInfo(event_data& edata, const MatchingSearchJoinRoomInfo* resp, SceNpMatchingSearchJoinRoomInfo* room_info); +} // namespace np diff --git a/rpcs3/Emu/NP/generated/np2_structs.fbs b/rpcs3/Emu/NP/generated/np2_structs.fbs index acfb9b0cd5..634d3fe6b8 100644 --- a/rpcs3/Emu/NP/generated/np2_structs.fbs +++ b/rpcs3/Emu/NP/generated/np2_structs.fbs @@ -32,14 +32,14 @@ table GroupConfig { withPassword:bool; } -table UserInfo2 { +table UserInfo { npId:string; onlineName:string; avatarUrl:string; } table RoomMemberDataInternal { - userInfo:UserInfo2; + userInfo:UserInfo; joinDate:uint64; memberId:uint16; teamId:uint8; @@ -84,7 +84,7 @@ table RoomDataExternal { openPrivateSlotNum:uint16; curMemberNum:uint16; passwordSlotMask:uint64; - owner:UserInfo2; + owner:UserInfo; roomGroup:[RoomGroup]; flagAttr:uint32; roomSearchableIntAttrExternal:[IntAttr]; @@ -128,7 +128,6 @@ table SearchRoomRequest { table SearchRoomResponse { startIndex:uint32; total:uint32; - size:uint32; rooms:[RoomDataExternal]; } @@ -262,7 +261,7 @@ table RoomMessageInfo { filtered:bool; castType:uint8; dst:[uint16]; - srcMember:UserInfo2; + srcMember:UserInfo; msg:[uint8]; } @@ -483,3 +482,79 @@ table SetPresenceRequest { comment:string; data:[uint8]; } + +table MatchingSearchCondition { + attr_type:uint32; + attr_id:uint32; + comp_op:uint32; + comp_value:uint32; +} + +table MatchingAttr { + attr_type:uint32; + attr_id:uint32; + num:uint32; + data:[uint8]; +} + +table CreateRoomGUIRequest { + total_slots:uint32; + private_slots:uint32; + privilege_grant:bool; + stealth:bool; + game_attrs:[MatchingAttr]; +} + +table GUIUserInfo { + info:UserInfo; + owner:bool; +} + +table MatchingRoomStatus { + id:[uint8]; + members:[GUIUserInfo]; + kick_actor:string; + opt:[uint8]; +} + +table GetRoomListGUIRequest { + range_start:uint32; + range_max:uint32; + conds:[MatchingSearchCondition]; + attrs:[MatchingAttr]; +} + +table MatchingRoom { + id:[uint8]; + attr:[MatchingAttr]; +} + +table MatchingRoomList { + start:uint32; + total:uint32; + rooms:[MatchingRoom]; +} + +table MatchingGuiRoomId { + id:[uint8]; +} + +table SetRoomSearchFlagGUI { + roomid:[uint8]; + stealth:bool; +} + +table QuickMatchGUIRequest { + conds:[MatchingSearchCondition]; + available_num:uint32; +} + +table SearchJoinRoomGUIRequest { + conds:[MatchingSearchCondition]; + attrs:[MatchingAttr]; +} + +table MatchingSearchJoinRoomInfo { + room:MatchingRoomStatus; + attr:[MatchingAttr]; +} diff --git a/rpcs3/Emu/NP/generated/np2_structs_generated.h b/rpcs3/Emu/NP/generated/np2_structs_generated.h index a3a942b33a..a31fc0c9c4 100644 --- a/rpcs3/Emu/NP/generated/np2_structs_generated.h +++ b/rpcs3/Emu/NP/generated/np2_structs_generated.h @@ -8,9 +8,9 @@ // Ensure the included flatbuffers.h is the same version as when this file was // generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 23 && - FLATBUFFERS_VERSION_MINOR == 5 && - FLATBUFFERS_VERSION_REVISION == 26, +static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && + FLATBUFFERS_VERSION_MINOR == 3 && + FLATBUFFERS_VERSION_REVISION == 25, "Non-compatible flatbuffers version included"); struct BinAttr; @@ -31,8 +31,8 @@ struct OptParamBuilder; struct GroupConfig; struct GroupConfigBuilder; -struct UserInfo2; -struct UserInfo2Builder; +struct UserInfo; +struct UserInfoBuilder; struct RoomMemberDataInternal; struct RoomMemberDataInternalBuilder; @@ -217,6 +217,45 @@ struct TusDeleteMultiSlotDataRequestBuilder; struct SetPresenceRequest; struct SetPresenceRequestBuilder; +struct MatchingSearchCondition; +struct MatchingSearchConditionBuilder; + +struct MatchingAttr; +struct MatchingAttrBuilder; + +struct CreateRoomGUIRequest; +struct CreateRoomGUIRequestBuilder; + +struct GUIUserInfo; +struct GUIUserInfoBuilder; + +struct MatchingRoomStatus; +struct MatchingRoomStatusBuilder; + +struct GetRoomListGUIRequest; +struct GetRoomListGUIRequestBuilder; + +struct MatchingRoom; +struct MatchingRoomBuilder; + +struct MatchingRoomList; +struct MatchingRoomListBuilder; + +struct MatchingGuiRoomId; +struct MatchingGuiRoomIdBuilder; + +struct SetRoomSearchFlagGUI; +struct SetRoomSearchFlagGUIBuilder; + +struct QuickMatchGUIRequest; +struct QuickMatchGUIRequestBuilder; + +struct SearchJoinRoomGUIRequest; +struct SearchJoinRoomGUIRequestBuilder; + +struct MatchingSearchJoinRoomInfo; +struct MatchingSearchJoinRoomInfoBuilder; + struct BinAttr FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { typedef BinAttrBuilder Builder; enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { @@ -593,8 +632,8 @@ inline ::flatbuffers::Offset CreateGroupConfigDirect( withPassword); } -struct UserInfo2 FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef UserInfo2Builder Builder; +struct UserInfo FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef UserInfoBuilder Builder; enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_NPID = 4, VT_ONLINENAME = 6, @@ -621,43 +660,43 @@ struct UserInfo2 FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { } }; -struct UserInfo2Builder { - typedef UserInfo2 Table; +struct UserInfoBuilder { + typedef UserInfo Table; ::flatbuffers::FlatBufferBuilder &fbb_; ::flatbuffers::uoffset_t start_; void add_npId(::flatbuffers::Offset<::flatbuffers::String> npId) { - fbb_.AddOffset(UserInfo2::VT_NPID, npId); + fbb_.AddOffset(UserInfo::VT_NPID, npId); } void add_onlineName(::flatbuffers::Offset<::flatbuffers::String> onlineName) { - fbb_.AddOffset(UserInfo2::VT_ONLINENAME, onlineName); + fbb_.AddOffset(UserInfo::VT_ONLINENAME, onlineName); } void add_avatarUrl(::flatbuffers::Offset<::flatbuffers::String> avatarUrl) { - fbb_.AddOffset(UserInfo2::VT_AVATARURL, avatarUrl); + fbb_.AddOffset(UserInfo::VT_AVATARURL, avatarUrl); } - explicit UserInfo2Builder(::flatbuffers::FlatBufferBuilder &_fbb) + explicit UserInfoBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ::flatbuffers::Offset Finish() { + ::flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); + auto o = ::flatbuffers::Offset(end); return o; } }; -inline ::flatbuffers::Offset CreateUserInfo2( +inline ::flatbuffers::Offset CreateUserInfo( ::flatbuffers::FlatBufferBuilder &_fbb, ::flatbuffers::Offset<::flatbuffers::String> npId = 0, ::flatbuffers::Offset<::flatbuffers::String> onlineName = 0, ::flatbuffers::Offset<::flatbuffers::String> avatarUrl = 0) { - UserInfo2Builder builder_(_fbb); + UserInfoBuilder builder_(_fbb); builder_.add_avatarUrl(avatarUrl); builder_.add_onlineName(onlineName); builder_.add_npId(npId); return builder_.Finish(); } -inline ::flatbuffers::Offset CreateUserInfo2Direct( +inline ::flatbuffers::Offset CreateUserInfoDirect( ::flatbuffers::FlatBufferBuilder &_fbb, const char *npId = nullptr, const char *onlineName = nullptr, @@ -665,7 +704,7 @@ inline ::flatbuffers::Offset CreateUserInfo2Direct( auto npId__ = npId ? _fbb.CreateString(npId) : 0; auto onlineName__ = onlineName ? _fbb.CreateString(onlineName) : 0; auto avatarUrl__ = avatarUrl ? _fbb.CreateString(avatarUrl) : 0; - return CreateUserInfo2( + return CreateUserInfo( _fbb, npId__, onlineName__, @@ -684,8 +723,8 @@ struct RoomMemberDataInternal FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::T VT_FLAGATTR = 16, VT_ROOMMEMBERBINATTRINTERNAL = 18 }; - const UserInfo2 *userInfo() const { - return GetPointer(VT_USERINFO); + const UserInfo *userInfo() const { + return GetPointer(VT_USERINFO); } uint64_t joinDate() const { return GetField(VT_JOINDATE, 0); @@ -730,7 +769,7 @@ struct RoomMemberDataInternalBuilder { typedef RoomMemberDataInternal Table; ::flatbuffers::FlatBufferBuilder &fbb_; ::flatbuffers::uoffset_t start_; - void add_userInfo(::flatbuffers::Offset userInfo) { + void add_userInfo(::flatbuffers::Offset userInfo) { fbb_.AddOffset(RoomMemberDataInternal::VT_USERINFO, userInfo); } void add_joinDate(uint64_t joinDate) { @@ -767,7 +806,7 @@ struct RoomMemberDataInternalBuilder { inline ::flatbuffers::Offset CreateRoomMemberDataInternal( ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset userInfo = 0, + ::flatbuffers::Offset userInfo = 0, uint64_t joinDate = 0, uint16_t memberId = 0, uint8_t teamId = 0, @@ -789,7 +828,7 @@ inline ::flatbuffers::Offset CreateRoomMemberDataInterna inline ::flatbuffers::Offset CreateRoomMemberDataInternalDirect( ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset userInfo = 0, + ::flatbuffers::Offset userInfo = 0, uint64_t joinDate = 0, uint16_t memberId = 0, uint8_t teamId = 0, @@ -1153,8 +1192,8 @@ struct RoomDataExternal FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { uint64_t passwordSlotMask() const { return GetField(VT_PASSWORDSLOTMASK, 0); } - const UserInfo2 *owner() const { - return GetPointer(VT_OWNER); + const UserInfo *owner() const { + return GetPointer(VT_OWNER); } const ::flatbuffers::Vector<::flatbuffers::Offset> *roomGroup() const { return GetPointer> *>(VT_ROOMGROUP); @@ -1240,7 +1279,7 @@ struct RoomDataExternalBuilder { void add_passwordSlotMask(uint64_t passwordSlotMask) { fbb_.AddElement(RoomDataExternal::VT_PASSWORDSLOTMASK, passwordSlotMask, 0); } - void add_owner(::flatbuffers::Offset owner) { + void add_owner(::flatbuffers::Offset owner) { fbb_.AddOffset(RoomDataExternal::VT_OWNER, owner); } void add_roomGroup(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> roomGroup) { @@ -1282,7 +1321,7 @@ inline ::flatbuffers::Offset CreateRoomDataExternal( uint16_t openPrivateSlotNum = 0, uint16_t curMemberNum = 0, uint64_t passwordSlotMask = 0, - ::flatbuffers::Offset owner = 0, + ::flatbuffers::Offset owner = 0, ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> roomGroup = 0, uint32_t flagAttr = 0, ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> roomSearchableIntAttrExternal = 0, @@ -1322,7 +1361,7 @@ inline ::flatbuffers::Offset CreateRoomDataExternalDirect( uint16_t openPrivateSlotNum = 0, uint16_t curMemberNum = 0, uint64_t passwordSlotMask = 0, - ::flatbuffers::Offset owner = 0, + ::flatbuffers::Offset owner = 0, const std::vector<::flatbuffers::Offset> *roomGroup = nullptr, uint32_t flagAttr = 0, const std::vector<::flatbuffers::Offset> *roomSearchableIntAttrExternal = nullptr, @@ -1753,8 +1792,7 @@ struct SearchRoomResponse FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_STARTINDEX = 4, VT_TOTAL = 6, - VT_SIZE = 8, - VT_ROOMS = 10 + VT_ROOMS = 8 }; uint32_t startIndex() const { return GetField(VT_STARTINDEX, 0); @@ -1762,9 +1800,6 @@ struct SearchRoomResponse FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table uint32_t total() const { return GetField(VT_TOTAL, 0); } - uint32_t size() const { - return GetField(VT_SIZE, 0); - } const ::flatbuffers::Vector<::flatbuffers::Offset> *rooms() const { return GetPointer> *>(VT_ROOMS); } @@ -1772,7 +1807,6 @@ struct SearchRoomResponse FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table return VerifyTableStart(verifier) && VerifyField(verifier, VT_STARTINDEX, 4) && VerifyField(verifier, VT_TOTAL, 4) && - VerifyField(verifier, VT_SIZE, 4) && VerifyOffset(verifier, VT_ROOMS) && verifier.VerifyVector(rooms()) && verifier.VerifyVectorOfTables(rooms()) && @@ -1790,9 +1824,6 @@ struct SearchRoomResponseBuilder { void add_total(uint32_t total) { fbb_.AddElement(SearchRoomResponse::VT_TOTAL, total, 0); } - void add_size(uint32_t size) { - fbb_.AddElement(SearchRoomResponse::VT_SIZE, size, 0); - } void add_rooms(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> rooms) { fbb_.AddOffset(SearchRoomResponse::VT_ROOMS, rooms); } @@ -1811,11 +1842,9 @@ inline ::flatbuffers::Offset CreateSearchRoomResponse( ::flatbuffers::FlatBufferBuilder &_fbb, uint32_t startIndex = 0, uint32_t total = 0, - uint32_t size = 0, ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> rooms = 0) { SearchRoomResponseBuilder builder_(_fbb); builder_.add_rooms(rooms); - builder_.add_size(size); builder_.add_total(total); builder_.add_startIndex(startIndex); return builder_.Finish(); @@ -1825,14 +1854,12 @@ inline ::flatbuffers::Offset CreateSearchRoomResponseDirect( ::flatbuffers::FlatBufferBuilder &_fbb, uint32_t startIndex = 0, uint32_t total = 0, - uint32_t size = 0, const std::vector<::flatbuffers::Offset> *rooms = nullptr) { auto rooms__ = rooms ? _fbb.CreateVector<::flatbuffers::Offset>(*rooms) : 0; return CreateSearchRoomResponse( _fbb, startIndex, total, - size, rooms__); } @@ -3410,8 +3437,8 @@ struct RoomMessageInfo FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { const ::flatbuffers::Vector *dst() const { return GetPointer *>(VT_DST); } - const UserInfo2 *srcMember() const { - return GetPointer(VT_SRCMEMBER); + const UserInfo *srcMember() const { + return GetPointer(VT_SRCMEMBER); } const ::flatbuffers::Vector *msg() const { return GetPointer *>(VT_MSG); @@ -3443,7 +3470,7 @@ struct RoomMessageInfoBuilder { void add_dst(::flatbuffers::Offset<::flatbuffers::Vector> dst) { fbb_.AddOffset(RoomMessageInfo::VT_DST, dst); } - void add_srcMember(::flatbuffers::Offset srcMember) { + void add_srcMember(::flatbuffers::Offset srcMember) { fbb_.AddOffset(RoomMessageInfo::VT_SRCMEMBER, srcMember); } void add_msg(::flatbuffers::Offset<::flatbuffers::Vector> msg) { @@ -3465,7 +3492,7 @@ inline ::flatbuffers::Offset CreateRoomMessageInfo( bool filtered = false, uint8_t castType = 0, ::flatbuffers::Offset<::flatbuffers::Vector> dst = 0, - ::flatbuffers::Offset srcMember = 0, + ::flatbuffers::Offset srcMember = 0, ::flatbuffers::Offset<::flatbuffers::Vector> msg = 0) { RoomMessageInfoBuilder builder_(_fbb); builder_.add_msg(msg); @@ -3481,7 +3508,7 @@ inline ::flatbuffers::Offset CreateRoomMessageInfoDirect( bool filtered = false, uint8_t castType = 0, const std::vector *dst = nullptr, - ::flatbuffers::Offset srcMember = 0, + ::flatbuffers::Offset srcMember = 0, const std::vector *msg = nullptr) { auto dst__ = dst ? _fbb.CreateVector(*dst) : 0; auto msg__ = msg ? _fbb.CreateVector(*msg) : 0; @@ -6164,4 +6191,951 @@ inline ::flatbuffers::Offset CreateSetPresenceRequestDirect( data__); } +struct MatchingSearchCondition FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef MatchingSearchConditionBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ATTR_TYPE = 4, + VT_ATTR_ID = 6, + VT_COMP_OP = 8, + VT_COMP_VALUE = 10 + }; + uint32_t attr_type() const { + return GetField(VT_ATTR_TYPE, 0); + } + uint32_t attr_id() const { + return GetField(VT_ATTR_ID, 0); + } + uint32_t comp_op() const { + return GetField(VT_COMP_OP, 0); + } + uint32_t comp_value() const { + return GetField(VT_COMP_VALUE, 0); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_ATTR_TYPE, 4) && + VerifyField(verifier, VT_ATTR_ID, 4) && + VerifyField(verifier, VT_COMP_OP, 4) && + VerifyField(verifier, VT_COMP_VALUE, 4) && + verifier.EndTable(); + } +}; + +struct MatchingSearchConditionBuilder { + typedef MatchingSearchCondition Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_attr_type(uint32_t attr_type) { + fbb_.AddElement(MatchingSearchCondition::VT_ATTR_TYPE, attr_type, 0); + } + void add_attr_id(uint32_t attr_id) { + fbb_.AddElement(MatchingSearchCondition::VT_ATTR_ID, attr_id, 0); + } + void add_comp_op(uint32_t comp_op) { + fbb_.AddElement(MatchingSearchCondition::VT_COMP_OP, comp_op, 0); + } + void add_comp_value(uint32_t comp_value) { + fbb_.AddElement(MatchingSearchCondition::VT_COMP_VALUE, comp_value, 0); + } + explicit MatchingSearchConditionBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateMatchingSearchCondition( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t attr_type = 0, + uint32_t attr_id = 0, + uint32_t comp_op = 0, + uint32_t comp_value = 0) { + MatchingSearchConditionBuilder builder_(_fbb); + builder_.add_comp_value(comp_value); + builder_.add_comp_op(comp_op); + builder_.add_attr_id(attr_id); + builder_.add_attr_type(attr_type); + return builder_.Finish(); +} + +struct MatchingAttr FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef MatchingAttrBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ATTR_TYPE = 4, + VT_ATTR_ID = 6, + VT_NUM = 8, + VT_DATA = 10 + }; + uint32_t attr_type() const { + return GetField(VT_ATTR_TYPE, 0); + } + uint32_t attr_id() const { + return GetField(VT_ATTR_ID, 0); + } + uint32_t num() const { + return GetField(VT_NUM, 0); + } + const ::flatbuffers::Vector *data() const { + return GetPointer *>(VT_DATA); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_ATTR_TYPE, 4) && + VerifyField(verifier, VT_ATTR_ID, 4) && + VerifyField(verifier, VT_NUM, 4) && + VerifyOffset(verifier, VT_DATA) && + verifier.VerifyVector(data()) && + verifier.EndTable(); + } +}; + +struct MatchingAttrBuilder { + typedef MatchingAttr Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_attr_type(uint32_t attr_type) { + fbb_.AddElement(MatchingAttr::VT_ATTR_TYPE, attr_type, 0); + } + void add_attr_id(uint32_t attr_id) { + fbb_.AddElement(MatchingAttr::VT_ATTR_ID, attr_id, 0); + } + void add_num(uint32_t num) { + fbb_.AddElement(MatchingAttr::VT_NUM, num, 0); + } + void add_data(::flatbuffers::Offset<::flatbuffers::Vector> data) { + fbb_.AddOffset(MatchingAttr::VT_DATA, data); + } + explicit MatchingAttrBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateMatchingAttr( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t attr_type = 0, + uint32_t attr_id = 0, + uint32_t num = 0, + ::flatbuffers::Offset<::flatbuffers::Vector> data = 0) { + MatchingAttrBuilder builder_(_fbb); + builder_.add_data(data); + builder_.add_num(num); + builder_.add_attr_id(attr_id); + builder_.add_attr_type(attr_type); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateMatchingAttrDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t attr_type = 0, + uint32_t attr_id = 0, + uint32_t num = 0, + const std::vector *data = nullptr) { + auto data__ = data ? _fbb.CreateVector(*data) : 0; + return CreateMatchingAttr( + _fbb, + attr_type, + attr_id, + num, + data__); +} + +struct CreateRoomGUIRequest FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef CreateRoomGUIRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_TOTAL_SLOTS = 4, + VT_PRIVATE_SLOTS = 6, + VT_PRIVILEGE_GRANT = 8, + VT_STEALTH = 10, + VT_GAME_ATTRS = 12 + }; + uint32_t total_slots() const { + return GetField(VT_TOTAL_SLOTS, 0); + } + uint32_t private_slots() const { + return GetField(VT_PRIVATE_SLOTS, 0); + } + bool privilege_grant() const { + return GetField(VT_PRIVILEGE_GRANT, 0) != 0; + } + bool stealth() const { + return GetField(VT_STEALTH, 0) != 0; + } + const ::flatbuffers::Vector<::flatbuffers::Offset> *game_attrs() const { + return GetPointer> *>(VT_GAME_ATTRS); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_TOTAL_SLOTS, 4) && + VerifyField(verifier, VT_PRIVATE_SLOTS, 4) && + VerifyField(verifier, VT_PRIVILEGE_GRANT, 1) && + VerifyField(verifier, VT_STEALTH, 1) && + VerifyOffset(verifier, VT_GAME_ATTRS) && + verifier.VerifyVector(game_attrs()) && + verifier.VerifyVectorOfTables(game_attrs()) && + verifier.EndTable(); + } +}; + +struct CreateRoomGUIRequestBuilder { + typedef CreateRoomGUIRequest Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_total_slots(uint32_t total_slots) { + fbb_.AddElement(CreateRoomGUIRequest::VT_TOTAL_SLOTS, total_slots, 0); + } + void add_private_slots(uint32_t private_slots) { + fbb_.AddElement(CreateRoomGUIRequest::VT_PRIVATE_SLOTS, private_slots, 0); + } + void add_privilege_grant(bool privilege_grant) { + fbb_.AddElement(CreateRoomGUIRequest::VT_PRIVILEGE_GRANT, static_cast(privilege_grant), 0); + } + void add_stealth(bool stealth) { + fbb_.AddElement(CreateRoomGUIRequest::VT_STEALTH, static_cast(stealth), 0); + } + void add_game_attrs(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> game_attrs) { + fbb_.AddOffset(CreateRoomGUIRequest::VT_GAME_ATTRS, game_attrs); + } + explicit CreateRoomGUIRequestBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateCreateRoomGUIRequest( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t total_slots = 0, + uint32_t private_slots = 0, + bool privilege_grant = false, + bool stealth = false, + ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> game_attrs = 0) { + CreateRoomGUIRequestBuilder builder_(_fbb); + builder_.add_game_attrs(game_attrs); + builder_.add_private_slots(private_slots); + builder_.add_total_slots(total_slots); + builder_.add_stealth(stealth); + builder_.add_privilege_grant(privilege_grant); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateCreateRoomGUIRequestDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t total_slots = 0, + uint32_t private_slots = 0, + bool privilege_grant = false, + bool stealth = false, + const std::vector<::flatbuffers::Offset> *game_attrs = nullptr) { + auto game_attrs__ = game_attrs ? _fbb.CreateVector<::flatbuffers::Offset>(*game_attrs) : 0; + return CreateCreateRoomGUIRequest( + _fbb, + total_slots, + private_slots, + privilege_grant, + stealth, + game_attrs__); +} + +struct GUIUserInfo FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef GUIUserInfoBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_INFO = 4, + VT_OWNER = 6 + }; + const UserInfo *info() const { + return GetPointer(VT_INFO); + } + bool owner() const { + return GetField(VT_OWNER, 0) != 0; + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_INFO) && + verifier.VerifyTable(info()) && + VerifyField(verifier, VT_OWNER, 1) && + verifier.EndTable(); + } +}; + +struct GUIUserInfoBuilder { + typedef GUIUserInfo Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_info(::flatbuffers::Offset info) { + fbb_.AddOffset(GUIUserInfo::VT_INFO, info); + } + void add_owner(bool owner) { + fbb_.AddElement(GUIUserInfo::VT_OWNER, static_cast(owner), 0); + } + explicit GUIUserInfoBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateGUIUserInfo( + ::flatbuffers::FlatBufferBuilder &_fbb, + ::flatbuffers::Offset info = 0, + bool owner = false) { + GUIUserInfoBuilder builder_(_fbb); + builder_.add_info(info); + builder_.add_owner(owner); + return builder_.Finish(); +} + +struct MatchingRoomStatus FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef MatchingRoomStatusBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ID = 4, + VT_MEMBERS = 6, + VT_KICK_ACTOR = 8, + VT_OPT = 10 + }; + const ::flatbuffers::Vector *id() const { + return GetPointer *>(VT_ID); + } + const ::flatbuffers::Vector<::flatbuffers::Offset> *members() const { + return GetPointer> *>(VT_MEMBERS); + } + const ::flatbuffers::String *kick_actor() const { + return GetPointer(VT_KICK_ACTOR); + } + const ::flatbuffers::Vector *opt() const { + return GetPointer *>(VT_OPT); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_ID) && + verifier.VerifyVector(id()) && + VerifyOffset(verifier, VT_MEMBERS) && + verifier.VerifyVector(members()) && + verifier.VerifyVectorOfTables(members()) && + VerifyOffset(verifier, VT_KICK_ACTOR) && + verifier.VerifyString(kick_actor()) && + VerifyOffset(verifier, VT_OPT) && + verifier.VerifyVector(opt()) && + verifier.EndTable(); + } +}; + +struct MatchingRoomStatusBuilder { + typedef MatchingRoomStatus Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_id(::flatbuffers::Offset<::flatbuffers::Vector> id) { + fbb_.AddOffset(MatchingRoomStatus::VT_ID, id); + } + void add_members(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> members) { + fbb_.AddOffset(MatchingRoomStatus::VT_MEMBERS, members); + } + void add_kick_actor(::flatbuffers::Offset<::flatbuffers::String> kick_actor) { + fbb_.AddOffset(MatchingRoomStatus::VT_KICK_ACTOR, kick_actor); + } + void add_opt(::flatbuffers::Offset<::flatbuffers::Vector> opt) { + fbb_.AddOffset(MatchingRoomStatus::VT_OPT, opt); + } + explicit MatchingRoomStatusBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateMatchingRoomStatus( + ::flatbuffers::FlatBufferBuilder &_fbb, + ::flatbuffers::Offset<::flatbuffers::Vector> id = 0, + ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> members = 0, + ::flatbuffers::Offset<::flatbuffers::String> kick_actor = 0, + ::flatbuffers::Offset<::flatbuffers::Vector> opt = 0) { + MatchingRoomStatusBuilder builder_(_fbb); + builder_.add_opt(opt); + builder_.add_kick_actor(kick_actor); + builder_.add_members(members); + builder_.add_id(id); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateMatchingRoomStatusDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *id = nullptr, + const std::vector<::flatbuffers::Offset> *members = nullptr, + const char *kick_actor = nullptr, + const std::vector *opt = nullptr) { + auto id__ = id ? _fbb.CreateVector(*id) : 0; + auto members__ = members ? _fbb.CreateVector<::flatbuffers::Offset>(*members) : 0; + auto kick_actor__ = kick_actor ? _fbb.CreateString(kick_actor) : 0; + auto opt__ = opt ? _fbb.CreateVector(*opt) : 0; + return CreateMatchingRoomStatus( + _fbb, + id__, + members__, + kick_actor__, + opt__); +} + +struct GetRoomListGUIRequest FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef GetRoomListGUIRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_RANGE_START = 4, + VT_RANGE_MAX = 6, + VT_CONDS = 8, + VT_ATTRS = 10 + }; + uint32_t range_start() const { + return GetField(VT_RANGE_START, 0); + } + uint32_t range_max() const { + return GetField(VT_RANGE_MAX, 0); + } + const ::flatbuffers::Vector<::flatbuffers::Offset> *conds() const { + return GetPointer> *>(VT_CONDS); + } + const ::flatbuffers::Vector<::flatbuffers::Offset> *attrs() const { + return GetPointer> *>(VT_ATTRS); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_RANGE_START, 4) && + VerifyField(verifier, VT_RANGE_MAX, 4) && + VerifyOffset(verifier, VT_CONDS) && + verifier.VerifyVector(conds()) && + verifier.VerifyVectorOfTables(conds()) && + VerifyOffset(verifier, VT_ATTRS) && + verifier.VerifyVector(attrs()) && + verifier.VerifyVectorOfTables(attrs()) && + verifier.EndTable(); + } +}; + +struct GetRoomListGUIRequestBuilder { + typedef GetRoomListGUIRequest Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_range_start(uint32_t range_start) { + fbb_.AddElement(GetRoomListGUIRequest::VT_RANGE_START, range_start, 0); + } + void add_range_max(uint32_t range_max) { + fbb_.AddElement(GetRoomListGUIRequest::VT_RANGE_MAX, range_max, 0); + } + void add_conds(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> conds) { + fbb_.AddOffset(GetRoomListGUIRequest::VT_CONDS, conds); + } + void add_attrs(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> attrs) { + fbb_.AddOffset(GetRoomListGUIRequest::VT_ATTRS, attrs); + } + explicit GetRoomListGUIRequestBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateGetRoomListGUIRequest( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t range_start = 0, + uint32_t range_max = 0, + ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> conds = 0, + ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> attrs = 0) { + GetRoomListGUIRequestBuilder builder_(_fbb); + builder_.add_attrs(attrs); + builder_.add_conds(conds); + builder_.add_range_max(range_max); + builder_.add_range_start(range_start); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateGetRoomListGUIRequestDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t range_start = 0, + uint32_t range_max = 0, + const std::vector<::flatbuffers::Offset> *conds = nullptr, + const std::vector<::flatbuffers::Offset> *attrs = nullptr) { + auto conds__ = conds ? _fbb.CreateVector<::flatbuffers::Offset>(*conds) : 0; + auto attrs__ = attrs ? _fbb.CreateVector<::flatbuffers::Offset>(*attrs) : 0; + return CreateGetRoomListGUIRequest( + _fbb, + range_start, + range_max, + conds__, + attrs__); +} + +struct MatchingRoom FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef MatchingRoomBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ID = 4, + VT_ATTR = 6 + }; + const ::flatbuffers::Vector *id() const { + return GetPointer *>(VT_ID); + } + const ::flatbuffers::Vector<::flatbuffers::Offset> *attr() const { + return GetPointer> *>(VT_ATTR); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_ID) && + verifier.VerifyVector(id()) && + VerifyOffset(verifier, VT_ATTR) && + verifier.VerifyVector(attr()) && + verifier.VerifyVectorOfTables(attr()) && + verifier.EndTable(); + } +}; + +struct MatchingRoomBuilder { + typedef MatchingRoom Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_id(::flatbuffers::Offset<::flatbuffers::Vector> id) { + fbb_.AddOffset(MatchingRoom::VT_ID, id); + } + void add_attr(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> attr) { + fbb_.AddOffset(MatchingRoom::VT_ATTR, attr); + } + explicit MatchingRoomBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateMatchingRoom( + ::flatbuffers::FlatBufferBuilder &_fbb, + ::flatbuffers::Offset<::flatbuffers::Vector> id = 0, + ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> attr = 0) { + MatchingRoomBuilder builder_(_fbb); + builder_.add_attr(attr); + builder_.add_id(id); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateMatchingRoomDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *id = nullptr, + const std::vector<::flatbuffers::Offset> *attr = nullptr) { + auto id__ = id ? _fbb.CreateVector(*id) : 0; + auto attr__ = attr ? _fbb.CreateVector<::flatbuffers::Offset>(*attr) : 0; + return CreateMatchingRoom( + _fbb, + id__, + attr__); +} + +struct MatchingRoomList FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef MatchingRoomListBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_START = 4, + VT_TOTAL = 6, + VT_ROOMS = 8 + }; + uint32_t start() const { + return GetField(VT_START, 0); + } + uint32_t total() const { + return GetField(VT_TOTAL, 0); + } + const ::flatbuffers::Vector<::flatbuffers::Offset> *rooms() const { + return GetPointer> *>(VT_ROOMS); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_START, 4) && + VerifyField(verifier, VT_TOTAL, 4) && + VerifyOffset(verifier, VT_ROOMS) && + verifier.VerifyVector(rooms()) && + verifier.VerifyVectorOfTables(rooms()) && + verifier.EndTable(); + } +}; + +struct MatchingRoomListBuilder { + typedef MatchingRoomList Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_start(uint32_t start) { + fbb_.AddElement(MatchingRoomList::VT_START, start, 0); + } + void add_total(uint32_t total) { + fbb_.AddElement(MatchingRoomList::VT_TOTAL, total, 0); + } + void add_rooms(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> rooms) { + fbb_.AddOffset(MatchingRoomList::VT_ROOMS, rooms); + } + explicit MatchingRoomListBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateMatchingRoomList( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t start = 0, + uint32_t total = 0, + ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> rooms = 0) { + MatchingRoomListBuilder builder_(_fbb); + builder_.add_rooms(rooms); + builder_.add_total(total); + builder_.add_start(start); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateMatchingRoomListDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t start = 0, + uint32_t total = 0, + const std::vector<::flatbuffers::Offset> *rooms = nullptr) { + auto rooms__ = rooms ? _fbb.CreateVector<::flatbuffers::Offset>(*rooms) : 0; + return CreateMatchingRoomList( + _fbb, + start, + total, + rooms__); +} + +struct MatchingGuiRoomId FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef MatchingGuiRoomIdBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ID = 4 + }; + const ::flatbuffers::Vector *id() const { + return GetPointer *>(VT_ID); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_ID) && + verifier.VerifyVector(id()) && + verifier.EndTable(); + } +}; + +struct MatchingGuiRoomIdBuilder { + typedef MatchingGuiRoomId Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_id(::flatbuffers::Offset<::flatbuffers::Vector> id) { + fbb_.AddOffset(MatchingGuiRoomId::VT_ID, id); + } + explicit MatchingGuiRoomIdBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateMatchingGuiRoomId( + ::flatbuffers::FlatBufferBuilder &_fbb, + ::flatbuffers::Offset<::flatbuffers::Vector> id = 0) { + MatchingGuiRoomIdBuilder builder_(_fbb); + builder_.add_id(id); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateMatchingGuiRoomIdDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *id = nullptr) { + auto id__ = id ? _fbb.CreateVector(*id) : 0; + return CreateMatchingGuiRoomId( + _fbb, + id__); +} + +struct SetRoomSearchFlagGUI FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef SetRoomSearchFlagGUIBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ROOMID = 4, + VT_STEALTH = 6 + }; + const ::flatbuffers::Vector *roomid() const { + return GetPointer *>(VT_ROOMID); + } + bool stealth() const { + return GetField(VT_STEALTH, 0) != 0; + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_ROOMID) && + verifier.VerifyVector(roomid()) && + VerifyField(verifier, VT_STEALTH, 1) && + verifier.EndTable(); + } +}; + +struct SetRoomSearchFlagGUIBuilder { + typedef SetRoomSearchFlagGUI Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_roomid(::flatbuffers::Offset<::flatbuffers::Vector> roomid) { + fbb_.AddOffset(SetRoomSearchFlagGUI::VT_ROOMID, roomid); + } + void add_stealth(bool stealth) { + fbb_.AddElement(SetRoomSearchFlagGUI::VT_STEALTH, static_cast(stealth), 0); + } + explicit SetRoomSearchFlagGUIBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateSetRoomSearchFlagGUI( + ::flatbuffers::FlatBufferBuilder &_fbb, + ::flatbuffers::Offset<::flatbuffers::Vector> roomid = 0, + bool stealth = false) { + SetRoomSearchFlagGUIBuilder builder_(_fbb); + builder_.add_roomid(roomid); + builder_.add_stealth(stealth); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateSetRoomSearchFlagGUIDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *roomid = nullptr, + bool stealth = false) { + auto roomid__ = roomid ? _fbb.CreateVector(*roomid) : 0; + return CreateSetRoomSearchFlagGUI( + _fbb, + roomid__, + stealth); +} + +struct QuickMatchGUIRequest FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef QuickMatchGUIRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_CONDS = 4, + VT_AVAILABLE_NUM = 6 + }; + const ::flatbuffers::Vector<::flatbuffers::Offset> *conds() const { + return GetPointer> *>(VT_CONDS); + } + uint32_t available_num() const { + return GetField(VT_AVAILABLE_NUM, 0); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_CONDS) && + verifier.VerifyVector(conds()) && + verifier.VerifyVectorOfTables(conds()) && + VerifyField(verifier, VT_AVAILABLE_NUM, 4) && + verifier.EndTable(); + } +}; + +struct QuickMatchGUIRequestBuilder { + typedef QuickMatchGUIRequest Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_conds(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> conds) { + fbb_.AddOffset(QuickMatchGUIRequest::VT_CONDS, conds); + } + void add_available_num(uint32_t available_num) { + fbb_.AddElement(QuickMatchGUIRequest::VT_AVAILABLE_NUM, available_num, 0); + } + explicit QuickMatchGUIRequestBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateQuickMatchGUIRequest( + ::flatbuffers::FlatBufferBuilder &_fbb, + ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> conds = 0, + uint32_t available_num = 0) { + QuickMatchGUIRequestBuilder builder_(_fbb); + builder_.add_available_num(available_num); + builder_.add_conds(conds); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateQuickMatchGUIRequestDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + const std::vector<::flatbuffers::Offset> *conds = nullptr, + uint32_t available_num = 0) { + auto conds__ = conds ? _fbb.CreateVector<::flatbuffers::Offset>(*conds) : 0; + return CreateQuickMatchGUIRequest( + _fbb, + conds__, + available_num); +} + +struct SearchJoinRoomGUIRequest FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef SearchJoinRoomGUIRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_CONDS = 4, + VT_ATTRS = 6 + }; + const ::flatbuffers::Vector<::flatbuffers::Offset> *conds() const { + return GetPointer> *>(VT_CONDS); + } + const ::flatbuffers::Vector<::flatbuffers::Offset> *attrs() const { + return GetPointer> *>(VT_ATTRS); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_CONDS) && + verifier.VerifyVector(conds()) && + verifier.VerifyVectorOfTables(conds()) && + VerifyOffset(verifier, VT_ATTRS) && + verifier.VerifyVector(attrs()) && + verifier.VerifyVectorOfTables(attrs()) && + verifier.EndTable(); + } +}; + +struct SearchJoinRoomGUIRequestBuilder { + typedef SearchJoinRoomGUIRequest Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_conds(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> conds) { + fbb_.AddOffset(SearchJoinRoomGUIRequest::VT_CONDS, conds); + } + void add_attrs(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> attrs) { + fbb_.AddOffset(SearchJoinRoomGUIRequest::VT_ATTRS, attrs); + } + explicit SearchJoinRoomGUIRequestBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateSearchJoinRoomGUIRequest( + ::flatbuffers::FlatBufferBuilder &_fbb, + ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> conds = 0, + ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> attrs = 0) { + SearchJoinRoomGUIRequestBuilder builder_(_fbb); + builder_.add_attrs(attrs); + builder_.add_conds(conds); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateSearchJoinRoomGUIRequestDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + const std::vector<::flatbuffers::Offset> *conds = nullptr, + const std::vector<::flatbuffers::Offset> *attrs = nullptr) { + auto conds__ = conds ? _fbb.CreateVector<::flatbuffers::Offset>(*conds) : 0; + auto attrs__ = attrs ? _fbb.CreateVector<::flatbuffers::Offset>(*attrs) : 0; + return CreateSearchJoinRoomGUIRequest( + _fbb, + conds__, + attrs__); +} + +struct MatchingSearchJoinRoomInfo FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef MatchingSearchJoinRoomInfoBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ROOM = 4, + VT_ATTR = 6 + }; + const MatchingRoomStatus *room() const { + return GetPointer(VT_ROOM); + } + const ::flatbuffers::Vector<::flatbuffers::Offset> *attr() const { + return GetPointer> *>(VT_ATTR); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_ROOM) && + verifier.VerifyTable(room()) && + VerifyOffset(verifier, VT_ATTR) && + verifier.VerifyVector(attr()) && + verifier.VerifyVectorOfTables(attr()) && + verifier.EndTable(); + } +}; + +struct MatchingSearchJoinRoomInfoBuilder { + typedef MatchingSearchJoinRoomInfo Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_room(::flatbuffers::Offset room) { + fbb_.AddOffset(MatchingSearchJoinRoomInfo::VT_ROOM, room); + } + void add_attr(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> attr) { + fbb_.AddOffset(MatchingSearchJoinRoomInfo::VT_ATTR, attr); + } + explicit MatchingSearchJoinRoomInfoBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateMatchingSearchJoinRoomInfo( + ::flatbuffers::FlatBufferBuilder &_fbb, + ::flatbuffers::Offset room = 0, + ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> attr = 0) { + MatchingSearchJoinRoomInfoBuilder builder_(_fbb); + builder_.add_attr(attr); + builder_.add_room(room); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateMatchingSearchJoinRoomInfoDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + ::flatbuffers::Offset room = 0, + const std::vector<::flatbuffers::Offset> *attr = nullptr) { + auto attr__ = attr ? _fbb.CreateVector<::flatbuffers::Offset>(*attr) : 0; + return CreateMatchingSearchJoinRoomInfo( + _fbb, + room, + attr__); +} + #endif // FLATBUFFERS_GENERATED_NP2STRUCTS_H_ diff --git a/rpcs3/Emu/NP/np_contexts.cpp b/rpcs3/Emu/NP/np_contexts.cpp index d9acbc4396..8c047b7eb5 100644 --- a/rpcs3/Emu/NP/np_contexts.cpp +++ b/rpcs3/Emu/NP/np_contexts.cpp @@ -1,7 +1,9 @@ #include "stdafx.h" #include "np_contexts.h" +#include "Emu/Cell/PPUCallback.h" #include "Emu/IdManager.h" +#include "Emu/Cell/Modules/cellSysutil.h" LOG_CHANNEL(sceNp2); @@ -201,13 +203,13 @@ s32 create_commerce2_context(u32 version, vm::cptr npid, vm::ptr(idm::make(version, npid, handler, arg)); } -bool destroy_commerce2_context(s32 ctx_id) +bool destroy_commerce2_context(u32 ctx_id) { return idm::remove(static_cast(ctx_id)); } std::shared_ptr get_commerce2_context(u16 ctx_id) { - return idm::get_unlocked(ctx_id); + return idm::get(ctx_id); } signaling_ctx::signaling_ctx(vm::ptr npid, vm::ptr handler, vm::ptr arg) @@ -220,11 +222,55 @@ s32 create_signaling_context(vm::ptr npid, vm::ptr(idm::make(npid, handler, arg)); } -bool destroy_signaling_context(s32 ctx_id) +bool destroy_signaling_context(u32 ctx_id) { return idm::remove(static_cast(ctx_id)); } std::shared_ptr get_signaling_context(u32 ctx_id) { - return idm::get_unlocked(ctx_id); + return idm::get(ctx_id); +} + +matching_ctx::matching_ctx(vm::ptr npId, vm::ptr handler, vm::ptr arg) +{ + memcpy(&this->npid, npId.get_ptr(), sizeof(SceNpId)); + this->handler = handler; + this->arg = arg; +} +void matching_ctx::queue_callback(u32 req_id, s32 event, s32 error_code) +{ + if (handler) + { + sysutil_register_cb([=, handler = this->handler, ctx_id = this->ctx_id, arg = this->arg](ppu_thread& cb_ppu) -> s32 + { + handler(cb_ppu, ctx_id, req_id, event, error_code, arg); + return 0; + }); + } +} +void matching_ctx::queue_gui_callback(s32 event, s32 error_code) +{ + if (gui_handler) + { + sysutil_register_cb([=, gui_handler = this->gui_handler, ctx_id = this->ctx_id, gui_arg = this->gui_arg](ppu_thread& cb_ppu) -> s32 + { + gui_handler(cb_ppu, ctx_id, event, error_code, gui_arg); + return 0; + }); + } +} +s32 create_matching_context(vm::ptr npId, vm::ptr handler, vm::ptr arg) +{ + const u32 ctx_id = idm::make(npId, handler, arg); + auto ctx = get_matching_context(ctx_id); + ctx->ctx_id = ctx_id; + return static_cast(ctx_id); +} +std::shared_ptr get_matching_context(u32 ctx_id) +{ + return idm::get(ctx_id); +} +bool destroy_matching_context(u32 ctx_id) +{ + return idm::remove(static_cast(ctx_id)); } diff --git a/rpcs3/Emu/NP/np_contexts.h b/rpcs3/Emu/NP/np_contexts.h index 3a9b7e46f6..cb576f6e95 100644 --- a/rpcs3/Emu/NP/np_contexts.h +++ b/rpcs3/Emu/NP/np_contexts.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "Utilities/mutex.h" @@ -13,6 +14,8 @@ #include "Emu/Cell/Modules/sceNp2.h" #include "Emu/Cell/Modules/sceNpCommerce2.h" #include "Emu/Cell/Modules/sceNpTus.h" +#include "Emu/NP/np_event_data.h" +#include "Utilities/Thread.h" // Used By Score and Tus struct generic_async_transaction_context @@ -259,7 +262,7 @@ struct commerce2_ctx }; s32 create_commerce2_context(u32 version, vm::cptr npid, vm::ptr handler, vm::ptr arg); std::shared_ptr get_commerce2_context(u16 ctx_id); -bool destroy_commerce2_context(s32 ctx_id); +bool destroy_commerce2_context(u32 ctx_id); struct signaling_ctx { @@ -280,4 +283,37 @@ struct signaling_ctx }; s32 create_signaling_context(vm::ptr npid, vm::ptr handler, vm::ptr arg); std::shared_ptr get_signaling_context(u32 ctx_id); -bool destroy_signaling_context(s32 ctx_id); +bool destroy_signaling_context(u32 ctx_id); + +struct matching_ctx +{ + matching_ctx(vm::ptr npid, vm::ptr handler, vm::ptr arg); + + void queue_callback(u32 req_id, s32 event, s32 error_code); + void queue_gui_callback(s32 event, s32 error_code); + + static const u32 id_base = 0x9001; + static const u32 id_step = 1; + static const u32 id_count = 1; + SAVESTATE_INIT_POS(32); + + SceNpId npid{}; + vm::ptr handler{}; + vm::ptr arg{}; + + atomic_t busy = 0; + u32 ctx_id = 0; + vm::ptr gui_handler{}; + vm::ptr gui_arg{}; + + // Used by QuickMatchGUI + u64 timeout = 0; + std::unique_ptr>> thread; + atomic_t wakey = 0; + + // To keep track of which callback to use for sceNpMatchingGetRoomListWithoutGUI / sceNpMatchingGetRoomListGUI / sceNpMatchingGetRoomListLimitGUI + atomic_t get_room_limit_version = false; +}; +s32 create_matching_context(vm::ptr npid, vm::ptr handler, vm::ptr arg); +std::shared_ptr get_matching_context(u32 ctx_id); +bool destroy_matching_context(u32 ctx_id); diff --git a/rpcs3/Emu/NP/np_event_data.h b/rpcs3/Emu/NP/np_event_data.h index 5017d44c9d..ba6d975888 100644 --- a/rpcs3/Emu/NP/np_event_data.h +++ b/rpcs3/Emu/NP/np_event_data.h @@ -14,6 +14,10 @@ namespace np m_data_ptr.set(vm_addr); } + event_data() + { + } + u8* data() { return m_data_ptr.get_ptr(); @@ -99,8 +103,8 @@ namespace np } private: - vm::bptr m_data_ptr; - u32 m_max_size, m_cur_size; + vm::bptr m_data_ptr{}; + u32 m_max_size = 0, m_cur_size = 0; std::vector m_relocs; }; } // namespace np diff --git a/rpcs3/Emu/NP/np_gui_cache.cpp b/rpcs3/Emu/NP/np_gui_cache.cpp new file mode 100644 index 0000000000..fee08356d5 --- /dev/null +++ b/rpcs3/Emu/NP/np_gui_cache.cpp @@ -0,0 +1,113 @@ +#include "stdafx.h" +#include "util/asm.hpp" +#include "np_gui_cache.h" + +LOG_CHANNEL(np_gui_cache); + +namespace np +{ + void gui_cache_manager::add_room(const SceNpRoomId& room_id) + { + std::lock_guard lock(mutex); + const auto [room, inserted] = rooms.insert_or_assign(room_id, gui_room_cache{}); + + if (!inserted) + np_gui_cache.error("Cache mismatch: tried to insert room but it already existed"); + } + + void gui_cache_manager::del_room(const SceNpRoomId& room_id) + { + std::lock_guard lock(mutex); + + if (rooms.erase(room_id) != 1) + np_gui_cache.error("Cache mismatch: tried to delete a room that wasn't in the cache"); + } + + void gui_cache_manager::add_member(const SceNpRoomId& room_id, const SceNpMatchingRoomMember* user_info, bool new_member) + { + std::lock_guard lock(mutex); + + if (!rooms.contains(room_id)) + { + np_gui_cache.error("Cache mismatch: tried to add a member to a non-existing room"); + return; + } + + auto& room = ::at32(rooms, room_id); + const auto [_, inserted] = room.members.insert_or_assign(user_info->user_info.userId, gui_room_member{.info = user_info->user_info, .owner = !!user_info->owner}); + + if (new_member) + { + if (!inserted) + np_gui_cache.error("Cache mismatch: tried to add a member but it was already in the room"); + } + else + { + if (inserted) + np_gui_cache.error("Cache mismatch: tried to update a member but it wasn't already in the room"); + } + } + + void gui_cache_manager::del_member(const SceNpRoomId& room_id, const SceNpMatchingRoomMember* user_info) + { + std::lock_guard lock(mutex); + + if (!rooms.contains(room_id)) + { + np_gui_cache.error("Cache mismatch: tried to remove a member from a non-existing room"); + return; + } + + auto& room = ::at32(rooms, room_id); + if (room.members.erase(user_info->user_info.userId) != 1) + np_gui_cache.error("Cache mismatch: tried to remove a member but it wasn't in the room"); + } + + error_code gui_cache_manager::get_room_member_list(const SceNpRoomId& room_id, u32 buf_len, vm::ptr data) + { + std::lock_guard lock(mutex); + + if (!rooms.contains(room_id)) + return SCE_NP_MATCHING_ERROR_ROOM_NOT_FOUND; + + const auto& room = ::at32(rooms, room_id); + + const u32 room_size = ::narrow(utils::align(sizeof(SceNpMatchingRoomStatus), 8) + (utils::align(sizeof(SceNpMatchingRoomMember), 8) * room.members.size())); + + if (!data) + return not_an_error(room_size); + + if (buf_len < room_size) + return SCE_NP_MATCHING_ERROR_INSUFFICIENT_BUFFER; + + std::memset(data.get_ptr(), 0, buf_len); + + vm::ptr room_status = vm::cast(data.addr()); + std::memcpy(&room_status->id, &room_id, sizeof(SceNpRoomId)); + room_status->num = ::narrow(room.members.size()); + + if (!room.members.empty()) + { + vm::ptr cur_member_ptr{}; + + for (const auto& [_, member] : room.members) + { + if (!cur_member_ptr) + { + room_status->members = vm::cast(data.addr() + utils::align(sizeof(SceNpMatchingRoomStatus), 8)); + cur_member_ptr = room_status->members; + } + else + { + cur_member_ptr->next = vm::cast(cur_member_ptr.addr() + utils::align(sizeof(SceNpMatchingRoomMember), 8)); + cur_member_ptr = cur_member_ptr->next; + } + + cur_member_ptr->owner = member.owner ? 1 : 0; + std::memcpy(&cur_member_ptr->user_info, &member.info, sizeof(SceNpUserInfo)); + } + } + + return CELL_OK; + } +} // namespace np diff --git a/rpcs3/Emu/NP/np_gui_cache.h b/rpcs3/Emu/NP/np_gui_cache.h new file mode 100644 index 0000000000..f3c4125e2e --- /dev/null +++ b/rpcs3/Emu/NP/np_gui_cache.h @@ -0,0 +1,58 @@ +#pragma once + +#include +#include + +#include "Utilities/mutex.h" + +#include "Emu/Cell/Modules/sceNp.h" +#include "Emu/Cell/Modules/sceNp2.h" + +template <> +struct std::less +{ + bool operator()(const SceNpRoomId& a, const SceNpRoomId& b) const + { + return (std::memcmp(a.opt, b.opt, sizeof(a.opt)) < 0); + } +}; + +template <> +struct std::less +{ + bool operator()(const SceNpId& a, const SceNpId& b) const + { + return (std::memcmp(a.handle.data, b.handle.data, sizeof(a.handle.data)) < 0); + } +}; + +namespace np +{ + struct gui_room_member + { + SceNpUserInfo info; + bool owner; + }; + + struct gui_room_cache + { + std::map members; + }; + + class gui_cache_manager + { + public: + gui_cache_manager() = default; + + void add_room(const SceNpRoomId& room_id); + void del_room(const SceNpRoomId& room_id); + void add_member(const SceNpRoomId& room_id, const SceNpMatchingRoomMember* user_info, bool new_member); + void del_member(const SceNpRoomId& room_id, const SceNpMatchingRoomMember* user_info); + + error_code get_room_member_list(const SceNpRoomId& room_id, u32 buf_len, vm::ptr data); + + private: + shared_mutex mutex; + std::map rooms; + }; +} // namespace np diff --git a/rpcs3/Emu/NP/np_handler.cpp b/rpcs3/Emu/NP/np_handler.cpp index 499b6b9171..c8ac3799b1 100644 --- a/rpcs3/Emu/NP/np_handler.cpp +++ b/rpcs3/Emu/NP/np_handler.cpp @@ -1122,7 +1122,17 @@ namespace np case rpcn::CommandType::TusGetMultiUserDataStatus: reply_tus_get_multiuser_data_status(req_id, data); break; case rpcn::CommandType::TusGetFriendsDataStatus: reply_tus_get_friends_data_status(req_id, data); break; case rpcn::CommandType::TusDeleteMultiSlotData: reply_tus_delete_multislot_data(req_id, data); break; - default: rpcn_log.error("Unknown reply(%d) received!", command); break; + case rpcn::CommandType::CreateRoomGUI: reply_create_room_gui(req_id, data); break; + case rpcn::CommandType::JoinRoomGUI: reply_join_room_gui(req_id, data); break; + case rpcn::CommandType::LeaveRoomGUI: reply_leave_room_gui(req_id, data); break; + case rpcn::CommandType::GetRoomListGUI: reply_get_room_list_gui(req_id, data); break; + case rpcn::CommandType::SetRoomSearchFlagGUI: reply_set_room_search_flag_gui(req_id, data); break; + case rpcn::CommandType::GetRoomSearchFlagGUI: reply_get_room_search_flag_gui(req_id, data); break; + case rpcn::CommandType::SetRoomInfoGUI: reply_set_room_info_gui(req_id, data); break; + case rpcn::CommandType::GetRoomInfoGUI: reply_get_room_info_gui(req_id, data); break; + case rpcn::CommandType::QuickMatchGUI: reply_quickmatch_gui(req_id, data); break; + case rpcn::CommandType::SearchJoinRoomGUI: reply_searchjoin_gui(req_id, data); break; + default: fmt::throw_exception("Unknown reply(%d) received!", command); break; } } @@ -1139,7 +1149,13 @@ namespace np case rpcn::NotificationType::SignalP2PConnect: notif_p2p_connect(notif.second); break; case rpcn::NotificationType::RoomMessageReceived: notif_room_message_received(notif.second); break; case rpcn::NotificationType::SignalingInfo: notif_signaling_info(notif.second); break; - default: rpcn_log.error("Unknown notification(%d) received!", notif.first); break; + case rpcn::NotificationType::MemberJoinedRoomGUI: notif_member_joined_room_gui(notif.second); break; + case rpcn::NotificationType::MemberLeftRoomGUI: notif_member_left_room_gui(notif.second); break; + case rpcn::NotificationType::RoomDisappearedGUI: notif_room_disappeared_gui(notif.second); break; + case rpcn::NotificationType::RoomOwnerChangedGUI: notif_room_owner_changed_gui(notif.second); break; + case rpcn::NotificationType::UserKickedGUI: notif_user_kicked_gui(notif.second); break; + case rpcn::NotificationType::QuickMatchCompleteGUI: notif_quickmatch_complete_gui(notif.second); break; + default: fmt::throw_exception("Unknown notification(%d) received!", notif.first); break; } } @@ -1625,4 +1641,50 @@ namespace np return {include_onlinename, include_avatarurl}; } + + void np_handler::add_gui_request(u32 req_id, u32 ctx_id) + { + std::lock_guard lock(gui_requests.mutex); + ensure(gui_requests.list.insert({req_id, ctx_id}).second); + } + + void np_handler::remove_gui_request(u32 req_id) + { + std::lock_guard lock(gui_requests.mutex); + if (gui_requests.list.erase(req_id) != 1) + { + rpcn_log.error("Failed to erase gui request %d", req_id); + } + } + + u32 np_handler::take_gui_request(u32 req_id) + { + std::lock_guard lock(gui_requests.mutex); + + if (!gui_requests.list.contains(req_id)) + { + return 0; + } + + const u32 ctx_id = ::at32(gui_requests.list, req_id); + gui_requests.list.erase(req_id); + + return ctx_id; + } + + std::shared_ptr np_handler::take_pending_gui_request(u32 req_id) + { + const u32 ctx_id = take_gui_request(req_id); + + if (!ctx_id) + return {}; + + auto ctx = get_matching_context(ctx_id); + + if (!ctx) + return {}; + + return ctx; + } + } // namespace np diff --git a/rpcs3/Emu/NP/np_handler.h b/rpcs3/Emu/NP/np_handler.h index 1345cc0803..4bbfc5535a 100644 --- a/rpcs3/Emu/NP/np_handler.h +++ b/rpcs3/Emu/NP/np_handler.h @@ -14,17 +14,30 @@ #include "Emu/NP/signaling_handler.h" #include "Emu/NP/np_allocator.h" #include "Emu/NP/np_cache.h" +#include "Emu/NP/np_gui_cache.h" #include "Emu/NP/np_event_data.h" #include "Emu/NP/np_contexts.h" #include "Emu/NP/upnp_handler.h" namespace np { + constexpr usz MAX_SceNpMatchingAttr_list_SIZE = ((SCE_NP_MATCHING_ATTR_ID_MAX * 2) * sizeof(SceNpMatchingAttr)) + + (SCE_NP_MATCHING_ATTR_BIN_BIG_SIZE_ID_MAX * SCE_NP_MATCHING_ATTR_BIN_MAX_SIZE_BIG) + + + ((SCE_NP_MATCHING_ATTR_ID_MAX - SCE_NP_MATCHING_ATTR_BIN_BIG_SIZE_ID_MAX) * SCE_NP_MATCHING_ATTR_BIN_MAX_SIZE_SMALL); + constexpr usz MAX_MEMBERS_PER_ROOM = 64; + constexpr usz MAX_ROOMS_PER_GET_ROOM_LIST = 20; + constexpr usz MAX_SceNpMatchingRoomStatus_SIZE = sizeof(SceNpMatchingRoomStatus) + (MAX_MEMBERS_PER_ROOM * sizeof(SceNpMatchingRoomMember)) + sizeof(SceNpId); + constexpr usz MAX_SceNpMatchingJoinedRoomInfo_SIZE = sizeof(SceNpMatchingJoinedRoomInfo) + (MAX_MEMBERS_PER_ROOM * sizeof(SceNpMatchingRoomMember)) + sizeof(SceNpId); + constexpr usz MAX_SceNpMatchingRoomList_SIZE = sizeof(SceNpMatchingRoomList) + MAX_ROOMS_PER_GET_ROOM_LIST * (sizeof(SceNpMatchingRoom) + MAX_SceNpMatchingAttr_list_SIZE); + constexpr usz MAX_SceNpMatchingRoom_SIZE = sizeof(SceNpMatchingRoom) + MAX_SceNpMatchingAttr_list_SIZE; + constexpr usz MAX_SceNpMatchingSearchJoinRoomInfo_SIZE = sizeof(SceNpMatchingSearchJoinRoomInfo) + MAX_SceNpMatchingAttr_list_SIZE; + enum class REQUEST_ID_HIGH : u16 { MISC = 0x3333, SCORE = 0x3334, TUS = 0x3335, + GUI = 0x3336, }; struct ticket_data @@ -175,6 +188,22 @@ namespace np u32 get_match2_event(SceNpMatching2EventKey event_key, u32 dest_addr, u32 size); + // Old GUI Matching requests + error_code get_matching_result(u32 ctx_id, u32 req_id, vm::ptr buf, vm::ptr size, vm::ptr event); + error_code get_result_gui(vm::ptr buf, vm::ptr size, vm::ptr event); + error_code create_room_gui(u32 ctx_id, vm::cptr communicationId, vm::cptr attr, vm::ptr handler, vm::ptr arg); + error_code join_room_gui(u32 ctx_id, vm::ptr roomid, vm::ptr handler, vm::ptr arg); + error_code leave_room_gui(u32 ctx_id, vm::cptr roomid); + error_code get_room_list_gui(u32 ctx_id, vm::cptr communicationId, vm::ptr range, vm::ptr cond, vm::ptr attr, vm::ptr handler, vm::ptr arg, bool limit); + error_code set_room_search_flag_gui(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, s32 flag); + error_code get_room_search_flag_gui(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id); + error_code set_room_info_gui(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, vm::ptr attr); + error_code get_room_info_gui(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, vm::ptr attr); + error_code quickmatch_gui(u32 ctx_id, vm::cptr communicationId, vm::cptr cond, s32 available_num, s32 timeout, vm::ptr handler, vm::ptr arg); + error_code searchjoin_gui(u32 ctx_id, vm::cptr communicationId, vm::cptr cond, vm::cptr attr, vm::ptr handler, vm::ptr arg); + + void set_current_gui_ctx_id(u32 id); + // Score requests void transaction_async_handler(std::unique_lock lock, const std::shared_ptr& trans_ctx, u32 req_id, bool async); void get_board_infos(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, vm::ptr boardInfo, bool async); @@ -207,6 +236,9 @@ namespace np std::pair> local_get_room_memberids(SceNpMatching2RoomId room_id, s32 sort_method); error_code local_get_room_member_data(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id, const std::vector& binattrs_list, SceNpMatching2RoomMemberDataInternal* ptr_member, u32 addr_data, u32 size_data, u32 ctx_id); + // Local GUI functions + error_code get_room_member_list_local_gui(u32 ctx_id, vm::ptr room_id, vm::ptr buflen, vm::ptr buf); + // Friend stuff u32 get_num_friends(); u32 get_num_blocks(); @@ -271,6 +303,15 @@ namespace np void notif_signaling_info(std::vector& data); void notif_room_message_received(std::vector& data); + void generic_gui_notification_handler(std::vector& data, std::string_view name, s32 notification_type); + + void notif_member_joined_room_gui(std::vector& data); + void notif_member_left_room_gui(std::vector& data); + void notif_room_disappeared_gui(std::vector& data); + void notif_room_owner_changed_gui(std::vector& data); + void notif_user_kicked_gui(std::vector& data); + void notif_quickmatch_complete_gui(std::vector& data); + // Reply handlers bool reply_get_world_list(u32 req_id, std::vector& reply_data); bool reply_create_join_room(u32 req_id, std::vector& reply_data); @@ -308,27 +349,19 @@ namespace np bool reply_tus_get_multiuser_data_status(u32 req_id, std::vector& reply_data); bool reply_tus_get_friends_data_status(u32 req_id, std::vector& reply_data); bool reply_tus_delete_multislot_data(u32 req_id, std::vector& reply_data); + bool reply_create_room_gui(u32 req_id, std::vector& reply_data); + bool reply_join_room_gui(u32 req_id, std::vector& reply_data); + bool reply_leave_room_gui(u32 req_id, std::vector& reply_data); + bool reply_get_room_list_gui(u32 req_id, std::vector& reply_data); + bool reply_set_room_search_flag_gui(u32 req_id, std::vector& reply_data); + bool reply_get_room_search_flag_gui(u32 req_id, std::vector& reply_data); + bool reply_set_room_info_gui(u32 req_id, std::vector& reply_data); + bool reply_get_room_info_gui(u32 req_id, std::vector& reply_data); + bool reply_quickmatch_gui(u32 req_id, std::vector& reply_data); + bool reply_searchjoin_gui(u32 req_id, std::vector& reply_data); - // Helper functions(fb=>np2) + // Helper functions std::pair get_match2_context_options(u32 ctx_id); - void BinAttr_to_SceNpMatching2BinAttr(event_data& edata, const BinAttr* bin_attr, SceNpMatching2BinAttr* binattr_info); - void BinAttrs_to_SceNpMatching2BinAttrs(event_data& edata, const flatbuffers::Vector>* fb_attr, SceNpMatching2BinAttr* binattr_info); - void RoomMemberBinAttrInternal_to_SceNpMatching2RoomMemberBinAttrInternal(event_data& edata, const RoomMemberBinAttrInternal* fb_attr, SceNpMatching2RoomMemberBinAttrInternal* binattr_info); - void RoomBinAttrInternal_to_SceNpMatching2RoomBinAttrInternal(event_data& edata, const BinAttrInternal* fb_attr, SceNpMatching2RoomBinAttrInternal* binattr_info); - void RoomGroup_to_SceNpMatching2RoomGroup(const RoomGroup* fb_group, SceNpMatching2RoomGroup* sce_group); - void RoomGroups_to_SceNpMatching2RoomGroups(const flatbuffers::Vector>* fb_groups, SceNpMatching2RoomGroup* sce_groups); - void UserInfo2_to_SceNpUserInfo2(event_data& edata, const UserInfo2* user, SceNpUserInfo2* user_info, bool include_onlinename, bool include_avatarurl); - void RoomDataExternal_to_SceNpMatching2RoomDataExternal(event_data& edata, const RoomDataExternal* room, SceNpMatching2RoomDataExternal* room_info, bool include_onlinename, bool include_avatarurl); - void SearchRoomResponse_to_SceNpMatching2SearchRoomResponse(event_data& edata, const SearchRoomResponse* resp, SceNpMatching2SearchRoomResponse* search_resp); - void GetRoomDataExternalListResponse_to_SceNpMatching2GetRoomDataExternalListResponse(event_data& edata, const GetRoomDataExternalListResponse* resp, SceNpMatching2GetRoomDataExternalListResponse* get_resp, bool include_onlinename, bool include_avatarurl); - u16 RoomDataInternal_to_SceNpMatching2RoomDataInternal(event_data& edata, const RoomDataInternal* resp, SceNpMatching2RoomDataInternal* room_resp, const SceNpId& npid, bool include_onlinename, bool include_avatarurl); - void RoomMemberDataInternal_to_SceNpMatching2RoomMemberDataInternal(event_data& edata, const RoomMemberDataInternal* member_data, const SceNpMatching2RoomDataInternal* room_info, SceNpMatching2RoomMemberDataInternal* sce_member_data, bool include_onlinename, bool include_avatarurl); - void RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo(event_data& edata, const RoomMemberUpdateInfo* resp, SceNpMatching2RoomMemberUpdateInfo* room_info, bool include_onlinename, bool include_avatarurl); - void RoomUpdateInfo_to_SceNpMatching2RoomUpdateInfo(const RoomUpdateInfo* update_info, SceNpMatching2RoomUpdateInfo* sce_update_info); - void GetPingInfoResponse_to_SceNpMatching2SignalingGetPingInfoResponse(const GetPingInfoResponse* resp, SceNpMatching2SignalingGetPingInfoResponse* sce_resp); - void RoomMessageInfo_to_SceNpMatching2RoomMessageInfo(event_data& edata, const RoomMessageInfo* mi, SceNpMatching2RoomMessageInfo* sce_mi, bool include_onlinename, bool include_avatarurl); - void RoomDataInternalUpdateInfo_to_SceNpMatching2RoomDataInternalUpdateInfo(event_data& edata, const RoomDataInternalUpdateInfo* update_info, SceNpMatching2RoomDataInternalUpdateInfo* sce_update_info, const SceNpId& npid, bool include_onlinename, bool include_avatarurl); - void RoomMemberDataInternalUpdateInfo_to_SceNpMatching2RoomMemberDataInternalUpdateInfo(event_data& edata, const RoomMemberDataInternalUpdateInfo* update_info, SceNpMatching2RoomMemberDataInternalUpdateInfo* sce_update_info, bool include_onlinename, bool include_avatarurl); bool handle_GetScoreResponse(u32 req_id, std::vector& reply_data, bool simple_result = false); bool handle_tus_no_data(u32 req_id, std::vector& reply_data); bool handle_TusVarResponse(u32 req_id, std::vector& reply_data); @@ -346,7 +379,7 @@ namespace np { if (cb) { - sysutil_register_cb([=, *this](ppu_thread& cb_ppu) -> s32 + sysutil_register_cb([=, ctx_id = this->ctx_id, event_type = this->event_type, cb = this->cb, cb_arg = this->cb_arg](ppu_thread& cb_ppu) -> s32 { cb(cb_ppu, ctx_id, req_id, event_type, event_key, error_code, data_size, cb_arg); return 0; @@ -403,6 +436,7 @@ namespace np // Cache related std::optional cached_cj_password; cache_manager np_cache; + gui_cache_manager gui_cache; // Messages related std::optional selected_invite_id{}; @@ -432,6 +466,31 @@ namespace np } event_data& allocate_req_result(u32 event_key, u32 max_size, u32 initial_size); + // GUI result + struct + { + shared_mutex mutex; + s32 event = 0; + event_data data; + } gui_result; + + void set_gui_result(s32 event, event_data data); + + // GUI notifications + struct gui_notification + { + s32 event = 0; + event_data edata; + }; + + struct + { + shared_mutex mutex; + std::map, gui_notification> list; // (ctx_id, req_id), notif + u32 counter_req_id = 1; + u32 current_gui_ctx_id = 0; + } gui_notifications; + // Async transaction threads shared_mutex mutex_async_transactions; std::unordered_map> async_transactions; // (req_id, transaction_ctx) @@ -459,5 +518,19 @@ namespace np shared_mutex mutex_history; std::map players_history; // npid / history + + struct + { + shared_mutex mutex; + std::map list; // req_id / ctx_id + } gui_requests; + + void add_gui_request(u32 req_id, u32 ctx_id); + void remove_gui_request(u32 req_id); + u32 take_gui_request(u32 req_id); + std::shared_ptr take_pending_gui_request(u32 req_id); + + shared_mutex mutex_quickmatching; + std::map pending_quickmatching; }; } // namespace np diff --git a/rpcs3/Emu/NP/np_notifications.cpp b/rpcs3/Emu/NP/np_notifications.cpp index e1e3753628..7d18133bd4 100644 --- a/rpcs3/Emu/NP/np_notifications.cpp +++ b/rpcs3/Emu/NP/np_notifications.cpp @@ -5,6 +5,7 @@ #include "Emu/NP/np_handler.h" #include "Emu/NP/np_helpers.h" #include "Emu/NP/np_structs_extra.h" +#include "Emu/NP/fb_helpers.h" LOG_CHANNEL(rpcn_log, "rpcn"); @@ -14,7 +15,7 @@ namespace np { vec_stream noti(data); u64 room_id = noti.get(); - auto* update_info = noti.get_flatbuffer(); + const auto* update_info = noti.get_flatbuffer(); if (noti.is_error()) { @@ -50,7 +51,7 @@ namespace np { vec_stream noti(data); u64 room_id = noti.get(); - auto* update_info = noti.get_flatbuffer(); + const auto* update_info = noti.get_flatbuffer(); if (noti.is_error()) { @@ -86,7 +87,7 @@ namespace np { vec_stream noti(data); u64 room_id = noti.get(); - auto* update_info = noti.get_flatbuffer(); + const auto* update_info = noti.get_flatbuffer(); if (noti.is_error()) { @@ -120,7 +121,7 @@ namespace np { vec_stream noti(data); SceNpMatching2RoomId room_id = noti.get(); - auto* update_info = noti.get_flatbuffer(); + const auto* update_info = noti.get_flatbuffer(); if (noti.is_error()) { @@ -156,7 +157,7 @@ namespace np { vec_stream noti(data); SceNpMatching2RoomId room_id = noti.get(); - auto* update_info = noti.get_flatbuffer(); + const auto* update_info = noti.get_flatbuffer(); if (noti.is_error()) { @@ -193,7 +194,7 @@ namespace np vec_stream noti(data); u64 room_id = noti.get(); u16 member_id = noti.get(); - auto* message_info = noti.get_flatbuffer(); + const auto* message_info = noti.get_flatbuffer(); if (noti.is_error()) { @@ -266,4 +267,135 @@ namespace np auto& sigh = g_fxo->get>(); sigh.send_information_packets(addr_p2p, port_p2p, npid_p2p); } + + void np_handler::generic_gui_notification_handler(std::vector& data, std::string_view name, s32 notification_type) + { + vec_stream noti(data); + const auto* update_info = noti.get_flatbuffer(); + + if (noti.is_error()) + { + rpcn_log.error("Received faulty %s notification", name); + return; + } + + std::lock_guard lock(gui_notifications.mutex); + + if (!gui_notifications.current_gui_ctx_id) + return; + + // Should the callback signaled depend on the room id and should we track if the context is the one that created/joined/left/etc the room? + auto ctx = get_matching_context(gui_notifications.current_gui_ctx_id); + ensure(ctx); + const u32 req_id = gui_notifications.counter_req_id++; + + event_data edata(np_memory.allocate(MAX_SceNpMatchingRoomStatus_SIZE), sizeof(SceNpMatchingRoomStatus), MAX_SceNpMatchingRoomStatus_SIZE); + auto* room_status = reinterpret_cast(edata.data()); + MatchingRoomStatus_to_SceNpMatchingRoomStatus(edata, update_info, room_status); + np_memory.shrink_allocation(edata.addr(), edata.size()); + + extra_nps::print_SceNpMatchingRoomStatus(room_status); + + switch (notification_type) + { + case SCE_NP_MATCHING_EVENT_ROOM_UPDATE_NEW_MEMBER: + gui_cache.add_member(room_status->id, room_status->members.get_ptr(), true); + break; + case SCE_NP_MATCHING_EVENT_ROOM_UPDATE_MEMBER_LEAVE: + gui_cache.del_member(room_status->id, room_status->members.get_ptr()); + break; + case SCE_NP_MATCHING_EVENT_ROOM_DISAPPEARED: + gui_cache.del_room(room_status->id); + break; + case SCE_NP_MATCHING_EVENT_ROOM_UPDATE_OWNER_CHANGE: + gui_cache.add_member(room_status->id, room_status->members.get_ptr(), false); + gui_cache.add_member(room_status->id, room_status->members->next.get_ptr(), false); + break; + case SCE_NP_MATCHING_EVENT_ROOM_KICKED: + gui_cache.del_room(room_status->id); + break; + default: + fmt::throw_exception("Unexpected notification type in generic_gui_notification_handler: 0x%08X", notification_type); + break; + } + + gui_notifications.list.emplace(std::make_pair(gui_notifications.current_gui_ctx_id, req_id), gui_notification{.event = notification_type, .edata = std::move(edata)}); + ctx->queue_callback(req_id, notification_type, 0); + } + + void np_handler::notif_member_joined_room_gui(std::vector& data) + { + return generic_gui_notification_handler(data, "MemberJoinedRoomGUI", SCE_NP_MATCHING_EVENT_ROOM_UPDATE_NEW_MEMBER); + } + + void np_handler::notif_member_left_room_gui(std::vector& data) + { + return generic_gui_notification_handler(data, "MemberLeftRoomGUI", SCE_NP_MATCHING_EVENT_ROOM_UPDATE_MEMBER_LEAVE); + } + + void np_handler::notif_room_disappeared_gui(std::vector& data) + { + return generic_gui_notification_handler(data, "RoomDisappearedGUI", SCE_NP_MATCHING_EVENT_ROOM_DISAPPEARED); + } + + void np_handler::notif_room_owner_changed_gui(std::vector& data) + { + return generic_gui_notification_handler(data, "RoomOwnerChangedGUI", SCE_NP_MATCHING_EVENT_ROOM_UPDATE_OWNER_CHANGE); + } + + void np_handler::notif_user_kicked_gui(std::vector& data) + { + return generic_gui_notification_handler(data, "UserKickedGUI", SCE_NP_MATCHING_EVENT_ROOM_KICKED); + } + + void gui_epilog(const std::shared_ptr& ctx); + + void np_handler::notif_quickmatch_complete_gui(std::vector& data) + { + vec_stream noti(data); + const auto* update_info = noti.get_flatbuffer(); + + if (noti.is_error()) + { + rpcn_log.error("Received faulty QuickMatchCompleteGUI notification"); + return; + } + + std::lock_guard lock(mutex_quickmatching); + + event_data edata(np_memory.allocate(MAX_SceNpMatchingJoinedRoomInfo_SIZE), sizeof(SceNpMatchingJoinedRoomInfo), MAX_SceNpMatchingJoinedRoomInfo_SIZE); + auto* room_info = reinterpret_cast(edata.data()); + MatchingRoomStatus_to_SceNpMatchingJoinedRoomInfo(edata, update_info, room_info); + np_memory.shrink_allocation(edata.addr(), edata.size()); + + extra_nps::print_SceNpMatchingJoinedRoomInfo(room_info); + + if (!pending_quickmatching.contains(room_info->room_status.id)) + { + np_memory.free(edata.addr()); + return; + } + + const u32 ctx_id = ::at32(pending_quickmatching, room_info->room_status.id); + ensure(pending_quickmatching.erase(room_info->room_status.id) == 1); + + auto ctx = get_matching_context(ctx_id); + + if (!ctx) + return; + + gui_cache.add_room(room_info->room_status.id); + + for (auto cur_member = room_info->room_status.members; cur_member; cur_member = cur_member->next) + { + gui_cache.add_member(room_info->room_status.id, cur_member.get_ptr(), true); + } + + set_gui_result(SCE_NP_MATCHING_GUI_EVENT_QUICK_MATCH, std::move(edata)); + ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_QUICK_MATCH, 0); + gui_epilog(ctx); + + ctx->wakey = 1; + ctx->wakey.notify_one(); + } } // namespace np diff --git a/rpcs3/Emu/NP/np_requests.cpp b/rpcs3/Emu/NP/np_requests.cpp index 05cf8c675f..33026986fc 100644 --- a/rpcs3/Emu/NP/np_requests.cpp +++ b/rpcs3/Emu/NP/np_requests.cpp @@ -9,6 +9,7 @@ #include "np_contexts.h" #include "np_helpers.h" #include "np_structs_extra.h" +#include "fb_helpers.h" LOG_CHANNEL(rpcn_log, "rpcn"); @@ -62,7 +63,7 @@ namespace np u32 np_handler::get_server_status(SceNpMatching2ContextId ctx_id, vm::cptr optParam, u16 server_id) { // TODO: actually implement interaction with server for this? - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetServerInfo); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetServerInfo); u32 event_key = get_event_key(); auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_GetServerInfo, sizeof(SceNpMatching2GetServerInfoResponse)); @@ -80,7 +81,7 @@ namespace np u32 np_handler::create_server_context(SceNpMatching2ContextId ctx_id, vm::cptr optParam, u16 /*server_id*/) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_CreateServerContext); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_CreateServerContext); const auto cb_info_opt = take_pending_request(req_id); ensure(cb_info_opt); @@ -91,7 +92,7 @@ namespace np u32 np_handler::delete_server_context(SceNpMatching2ContextId ctx_id, vm::cptr optParam, u16 /*server_id*/) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_DeleteServerContext); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_DeleteServerContext); const auto cb_info_opt = take_pending_request(req_id); ensure(cb_info_opt); @@ -102,7 +103,7 @@ namespace np u32 np_handler::get_world_list(SceNpMatching2ContextId ctx_id, vm::cptr optParam, u16 server_id) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetWorldInfoList); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetWorldInfoList); if (!get_rpcn()->get_world_list(req_id, get_match2_context(ctx_id)->communicationId, server_id)) { @@ -157,7 +158,7 @@ namespace np u32 np_handler::create_join_room(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2CreateJoinRoomRequest* req) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_CreateJoinRoom); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_CreateJoinRoom); extra_nps::print_createjoinroom(req); @@ -181,7 +182,7 @@ namespace np return true; vec_stream reply(reply_data, 1); - auto* resp = reply.get_flatbuffer(); + const auto* resp = reply.get_flatbuffer(); if (reply.is_error()) return error_and_disconnect("Malformed reply to CreateRoom command"); @@ -207,7 +208,7 @@ namespace np u32 np_handler::join_room(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2JoinRoomRequest* req) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_JoinRoom); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_JoinRoom); extra_nps::print_joinroom(req); @@ -248,7 +249,7 @@ namespace np vec_stream reply(reply_data, 1); - auto* resp = reply.get_flatbuffer(); + const auto* resp = reply.get_flatbuffer(); if (reply.is_error()) return error_and_disconnect("Malformed reply to JoinRoom command"); @@ -273,7 +274,7 @@ namespace np u32 np_handler::leave_room(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2LeaveRoomRequest* req) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_LeaveRoom); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_LeaveRoom); if (!get_rpcn()->leave_room(req_id, get_match2_context(ctx_id)->communicationId, req)) { @@ -306,7 +307,7 @@ namespace np u32 np_handler::search_room(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SearchRoomRequest* req) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SearchRoom); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SearchRoom); extra_nps::print_search_room(req); @@ -327,7 +328,7 @@ namespace np return true; vec_stream reply(reply_data, 1); - auto* resp = reply.get_flatbuffer(); + const auto* resp = reply.get_flatbuffer(); if (reply.is_error()) return error_and_disconnect("Malformed reply to SearchRoom command"); @@ -348,7 +349,7 @@ namespace np u32 np_handler::get_roomdata_external_list(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2GetRoomDataExternalListRequest* req) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataExternalList); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataExternalList); extra_nps::print_get_roomdata_external_list_req(req); @@ -369,7 +370,7 @@ namespace np return true; vec_stream reply(reply_data, 1); - auto* resp = reply.get_flatbuffer(); + const auto* resp = reply.get_flatbuffer(); if (reply.is_error()) return error_and_disconnect("Malformed reply to GetRoomDataExternalList command"); @@ -391,7 +392,7 @@ namespace np u32 np_handler::set_roomdata_external(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SetRoomDataExternalRequest* req) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataExternal); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataExternal); extra_nps::print_set_roomdata_ext_req(req); @@ -418,7 +419,7 @@ namespace np u32 np_handler::get_roomdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2GetRoomDataInternalRequest* req) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataInternal); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataInternal); if (!get_rpcn()->get_roomdata_internal(req_id, get_match2_context(ctx_id)->communicationId, req)) { @@ -438,7 +439,7 @@ namespace np vec_stream reply(reply_data, 1); - auto* resp = reply.get_flatbuffer(); + const auto* resp = reply.get_flatbuffer(); if (reply.is_error()) return error_and_disconnect("Malformed reply to GetRoomDataInternal command"); @@ -463,7 +464,7 @@ namespace np u32 np_handler::set_roomdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SetRoomDataInternalRequest* req) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataInternal); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataInternal); extra_nps::print_set_roomdata_int_req(req); @@ -490,7 +491,7 @@ namespace np u32 np_handler::get_roommemberdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2GetRoomMemberDataInternalRequest* req) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomMemberDataInternal); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomMemberDataInternal); extra_nps::print_get_roommemberdata_int_req(req); if (!get_rpcn()->get_roommemberdata_internal(req_id, get_match2_context(ctx_id)->communicationId, req)) @@ -526,7 +527,7 @@ namespace np vec_stream reply(reply_data, 1); - auto* resp = reply.get_flatbuffer(); + const auto* resp = reply.get_flatbuffer(); if (reply.is_error()) return error_and_disconnect("Malformed reply to GetRoomMemberDataInternal command"); @@ -546,7 +547,7 @@ namespace np u32 np_handler::set_roommemberdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SetRoomMemberDataInternalRequest* req) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomMemberDataInternal); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomMemberDataInternal); extra_nps::print_set_roommemberdata_int_req(req); @@ -573,7 +574,7 @@ namespace np u32 np_handler::set_userinfo(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SetUserInfoRequest* req) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SetUserInfo); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SetUserInfo); if (!get_rpcn()->set_userinfo(req_id, get_match2_context(ctx_id)->communicationId, req)) { @@ -603,7 +604,7 @@ namespace np u32 np_handler::get_ping_info(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SignalingGetPingInfoRequest* req) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SignalingGetPingInfo); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SignalingGetPingInfo); if (!get_rpcn()->ping_room_owner(req_id, get_match2_context(ctx_id)->communicationId, req->roomId)) { @@ -623,7 +624,7 @@ namespace np vec_stream reply(reply_data, 1); - auto* resp = reply.get_flatbuffer(); + const auto* resp = reply.get_flatbuffer(); if (reply.is_error()) return error_and_disconnect("Malformed reply to PingRoomOwner command"); @@ -641,7 +642,7 @@ namespace np u32 np_handler::send_room_message(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SendRoomMessageRequest* req) { - u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SendRoomMessage); + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SendRoomMessage); if (!get_rpcn()->send_room_message(req_id, get_match2_context(ctx_id)->communicationId, req)) { @@ -666,7 +667,7 @@ namespace np void np_handler::req_sign_infos(const std::string& npid, u32 conn_id) { - u32 req_id = get_req_id(REQUEST_ID_HIGH::MISC); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::MISC); { std::lock_guard lock(mutex_pending_sign_infos_requests); pending_sign_infos_requests[req_id] = conn_id; @@ -719,7 +720,7 @@ namespace np void np_handler::req_ticket([[maybe_unused]] u32 version, [[maybe_unused]] const SceNpId* npid, const char* service_id, const u8* cookie, u32 cookie_size, [[maybe_unused]] const char* entitlement_id, [[maybe_unused]] u32 consumed_count) { - u32 req_id = get_req_id(REQUEST_ID_HIGH::MISC); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::MISC); std::string service_id_str(service_id); @@ -785,7 +786,7 @@ namespace np } // Only 2 cases should be timeout or caller setting result - ensure(trans_ctx->result, "transaction_async_handler: trans_ctx->result is no set"); + ensure(trans_ctx->result, "transaction_async_handler: trans_ctx->result is not set"); trans_ctx->completion_cond.notify_one(); }; @@ -810,7 +811,7 @@ namespace np { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); trans_ctx->tdata = tdata_get_board_infos{.boardInfo = boardInfo}; get_rpcn()->get_board_infos(req_id, trans_ctx->communicationId, boardId); @@ -821,7 +822,7 @@ namespace np { vec_stream reply(reply_data, 1); - auto* resp = reply.get_flatbuffer(); + const auto* resp = reply.get_flatbuffer(); if (reply.is_error()) return error_and_disconnect("Malformed reply to GetBoardInfos command"); @@ -859,7 +860,7 @@ namespace np void np_handler::record_score(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreValue score, vm::cptr scoreComment, const u8* data, u32 data_size, vm::ptr tmpRank, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); std::optional str_comment = scoreComment ? std::optional(std::string(reinterpret_cast(scoreComment->data))) : std::nullopt; std::optional> vec_data; @@ -942,7 +943,7 @@ namespace np if (tdata->game_data.size() == tdata->game_data_size) { trans_ctx->result = std::nullopt; - u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); get_rpcn()->record_score_data(req_id, trans_ctx->communicationId, trans_ctx->pcId, boardId, score, tdata->game_data); transaction_async_handler(std::move(lock), trans_ctx, req_id, async); } @@ -994,7 +995,7 @@ namespace np { trans_ctx->tdata = tdata_get_score_data{.totalSize = totalSize, .recvSize = recvSize, .score_data = score_data}; - u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); get_rpcn()->get_score_data(req_id, trans_ctx->communicationId, trans_ctx->pcId, boardId, npId); transaction_async_handler(std::move(lock), trans_ctx, req_id, async); return; @@ -1065,7 +1066,7 @@ namespace np void np_handler::get_score_range(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreRankNumber startSerialRank, vm::ptr rankArray, u32 rankArraySize, vm::ptr commentArray, [[maybe_unused]] u32 commentArraySize, vm::ptr infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr lastSortDate, vm::ptr totalRecord, bool async, bool deprecated) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); trans_ctx->tdata = tdata_get_score_generic{ .rankArray = rankArray, @@ -1126,7 +1127,7 @@ namespace np } vec_stream reply(reply_data, 1); - auto* resp = reply.get_flatbuffer(); + const auto* resp = reply.get_flatbuffer(); if (reply.is_error()) { @@ -1243,7 +1244,7 @@ namespace np void np_handler::get_score_friend(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, bool include_self, vm::ptr rankArray, u32 rankArraySize, vm::ptr commentArray, [[maybe_unused]] u32 commentArraySize, vm::ptr infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr lastSortDate, vm::ptr totalRecord, bool async, bool deprecated) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); trans_ctx->tdata = tdata_get_score_generic{ .rankArray = rankArray, .rankArraySize = rankArraySize, @@ -1272,7 +1273,7 @@ namespace np void np_handler::get_score_npid(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, const std::vector>& npid_vec, vm::ptr rankArray, u32 rankArraySize, vm::ptr commentArray, [[maybe_unused]] u32 commentArraySize, vm::ptr infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr lastSortDate, vm::ptr totalRecord, bool async, bool deprecated) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); trans_ctx->tdata = tdata_get_score_generic{ .rankArray = rankArray, .rankArraySize = rankArraySize, @@ -1356,7 +1357,7 @@ namespace np } vec_stream reply(reply_data, 1); - auto* resp = reply.get_flatbuffer(); + const auto* resp = reply.get_flatbuffer(); if (reply.is_error()) { @@ -1482,7 +1483,7 @@ namespace np } vec_stream reply(reply_data, 1); - auto* resp = reply.get_flatbuffer(); + const auto* resp = reply.get_flatbuffer(); if (reply.is_error()) { @@ -1531,7 +1532,7 @@ namespace np void np_handler::tus_set_multislot_variable(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, vm::cptr variableArray, s32 arrayNum, bool vuser, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); get_rpcn()->tus_set_multislot_variable(req_id, trans_ctx->communicationId, targetNpId, slotIdArray, variableArray, arrayNum, vuser); transaction_async_handler(std::move(lock), trans_ctx, req_id, async); @@ -1545,7 +1546,7 @@ namespace np void np_handler::tus_get_multislot_variable(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, vm::ptr variableArray, s32 arrayNum, bool vuser, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); trans_ctx->tdata = tdata_tus_get_variables_generic { .variableArray = variableArray, @@ -1564,7 +1565,7 @@ namespace np void np_handler::tus_get_multiuser_variable(std::shared_ptr& trans_ctx, std::vector targetNpIdArray, SceNpTusSlotId slotId, vm::ptr variableArray, s32 arrayNum, bool vuser, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); trans_ctx->tdata = tdata_tus_get_variables_generic { .variableArray = variableArray, @@ -1583,7 +1584,7 @@ namespace np void np_handler::tus_get_friends_variable(std::shared_ptr& trans_ctx, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr variableArray,s32 arrayNum, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); trans_ctx->tdata = tdata_tus_get_variables_generic { .variableArray = variableArray, @@ -1602,7 +1603,7 @@ namespace np void np_handler::tus_add_and_get_variable(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr outVariable, vm::ptr option, bool vuser, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); trans_ctx->tdata = tdata_tus_get_variable_generic { .outVariable = outVariable, @@ -1620,7 +1621,7 @@ namespace np void np_handler::tus_try_and_set_variable(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr resultVariable, vm::ptr option, bool vuser, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); trans_ctx->tdata = tdata_tus_get_variable_generic { .outVariable = resultVariable, @@ -1638,7 +1639,7 @@ namespace np void np_handler::tus_delete_multislot_variable(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); get_rpcn()->tus_delete_multislot_variable(req_id, trans_ctx->communicationId, targetNpId, slotIdArray, arrayNum, vuser); transaction_async_handler(std::move(lock), trans_ctx, req_id, async); @@ -1668,7 +1669,7 @@ namespace np if (tdata->tus_data.size() == tdata->tus_data_size) { trans_ctx->result = std::nullopt; - u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); get_rpcn()->tus_set_data(req_id, trans_ctx->communicationId, targetNpId, slotId, tdata->tus_data, info, option, vuser); transaction_async_handler(std::move(lock), trans_ctx, req_id, async); } @@ -1691,7 +1692,7 @@ namespace np if (!tdata) { trans_ctx->tdata = tdata_tus_get_data{.recvSize = recvSize, .dataStatus = dataStatus, .data = data}; - u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); get_rpcn()->tus_get_data(req_id, trans_ctx->communicationId, targetNpId, slotId, vuser); transaction_async_handler(std::move(lock), trans_ctx, req_id, async); return; @@ -1798,7 +1799,7 @@ namespace np void np_handler::tus_get_multislot_data_status(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, vm::ptr statusArray, s32 arrayNum, bool vuser, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); trans_ctx->tdata = tdata_tus_get_datastatus_generic { .statusArray = statusArray, @@ -1817,7 +1818,7 @@ namespace np void np_handler::tus_get_multiuser_data_status(std::shared_ptr& trans_ctx, std::vector targetNpIdArray, SceNpTusSlotId slotId, vm::ptr statusArray, s32 arrayNum, bool vuser, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); trans_ctx->tdata = tdata_tus_get_datastatus_generic { .statusArray = statusArray, @@ -1836,7 +1837,7 @@ namespace np void np_handler::tus_get_friends_data_status(std::shared_ptr& trans_ctx, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr statusArray, s32 arrayNum, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); trans_ctx->tdata = tdata_tus_get_datastatus_generic { .statusArray = statusArray, @@ -1855,7 +1856,7 @@ namespace np void np_handler::tus_delete_multislot_data(std::shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser, bool async) { std::unique_lock lock(trans_ctx->mutex); - u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); + const u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS); get_rpcn()->tus_delete_multislot_data(req_id, trans_ctx->communicationId, targetNpId, slotIdArray, arrayNum, vuser); transaction_async_handler(std::move(lock), trans_ctx, req_id, async); @@ -1865,8 +1866,4 @@ namespace np { return handle_tus_no_data(req_id, reply_data); } - - - - } // namespace np diff --git a/rpcs3/Emu/NP/np_requests_gui.cpp b/rpcs3/Emu/NP/np_requests_gui.cpp new file mode 100644 index 0000000000..ed099bc6d6 --- /dev/null +++ b/rpcs3/Emu/NP/np_requests_gui.cpp @@ -0,0 +1,777 @@ +#include "stdafx.h" +#include "Emu/Cell/PPUModule.h" +#include "Emu/Cell/lv2/sys_sync.h" +#include "Emu/Cell/Modules/cellSysutil.h" +#include "Emu/Memory/vm_ptr.h" +#include "Emu/IdManager.h" +#include "np_handler.h" +#include "np_contexts.h" +#include "np_helpers.h" +#include "np_structs_extra.h" +#include "fb_helpers.h" + +LOG_CHANNEL(rpcn_log, "rpcn"); + +namespace np +{ + std::pair> gui_prelude(u32 ctx_id, vm::ptr handler, vm::ptr arg) + { + auto ctx = get_matching_context(ctx_id); + + if (!ctx) + return {SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND, {}}; + + if (!ctx->busy.compare_and_swap_test(0, 1)) + return {SCE_NP_MATCHING_ERROR_CTX_STILL_RUNNING, {}}; + + ctx->ctx_id = ctx_id; + ctx->gui_handler = handler; + ctx->gui_arg = arg; + + ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_COMMON_LOAD, 0); + + return {CELL_OK, ctx}; + } + + void gui_epilog(const std::shared_ptr& ctx) + { + ensure(ctx->busy.compare_and_swap_test(1, 0), "Matching context wasn't busy in gui_epilog"); + ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_COMMON_UNLOAD, 0); + } + + void np_handler::set_current_gui_ctx_id(u32 id) + { + std::lock_guard lock(gui_notifications.mutex); + + gui_notifications.current_gui_ctx_id = id; + + if (id == 0) + { + for (const auto& [key, notif_data] : gui_notifications.list) + { + np_memory.free(notif_data.edata.addr()); + } + + gui_notifications.list.clear(); + } + } + + void np_handler::set_gui_result(s32 event, np::event_data data) + { + std::lock_guard lock(gui_result.mutex); + if (gui_result.event) + np_memory.free(gui_result.data.addr()); + + gui_result.data = std::move(data); + gui_result.event = event; + } + + error_code np_handler::get_matching_result(u32 ctx_id, u32 req_id, vm::ptr buf, vm::ptr size, vm::ptr event) + { + std::lock_guard lock(gui_notifications.mutex); + + auto ctx = get_matching_context(ctx_id); + + if (!gui_notifications.current_gui_ctx_id || !ctx) + { + return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; + } + + if (!gui_notifications.list.contains(std::make_pair(ctx_id, req_id))) + { + return SCE_NP_MATCHING_ERROR_INVALID_REQ_ID; + } + + const auto key = std::make_pair(ctx_id, req_id); + + auto& notif = ::at32(gui_notifications.list, key); + + if (event) + { + *event = notif.event; + } + + if (!buf) + { + *size = notif.edata.size(); + return CELL_OK; + } + + const u32 final_size = std::min(static_cast(*size), notif.edata.size()); + notif.edata.apply_relocations(buf.addr()); + memcpy(buf.get_ptr(), notif.edata.data(), final_size); + *size = final_size; + + np_memory.free(notif.edata.addr()); + gui_notifications.list.erase(key); + + return CELL_OK; + } + + error_code np_handler::get_result_gui(vm::ptr buf, vm::ptr size, vm::ptr event) + { + std::lock_guard lock(gui_result.mutex); + + if (!gui_result.event) + { + return SCE_NP_MATCHING_ERROR_RESULT_NOT_FOUND; + } + + if (event) + { + *event = gui_result.event; + } + + if (!buf) + { + *size = gui_result.data.size(); + return CELL_OK; + } + + const u32 final_size = std::min(static_cast(*size), gui_result.data.size()); + gui_result.data.apply_relocations(buf.addr()); + memcpy(buf.get_ptr(), gui_result.data.data(), final_size); + *size = final_size; + + np_memory.free(gui_result.data.addr()); + gui_result.event = 0; + + return CELL_OK; + } + + error_code np_handler::create_room_gui(u32 ctx_id, vm::cptr communicationId, vm::cptr attr, vm::ptr handler, vm::ptr arg) + { + const auto [error, ctx] = gui_prelude(ctx_id, handler, arg); + + if (error) + return error; + + for (auto cur_attr = attr; cur_attr; cur_attr = cur_attr->next) + { + extra_nps::print_SceNpMatchingAttr(cur_attr.get_ptr()); + } + + const u32 req_id = get_req_id(REQUEST_ID_HIGH::GUI); + add_gui_request(req_id, ctx_id); + + get_rpcn()->createjoin_room_gui(req_id, *communicationId, attr.get_ptr()); + + return CELL_OK; + } + + bool np_handler::reply_create_room_gui(u32 req_id, std::vector& reply_data) + { + auto ctx = take_pending_gui_request(req_id); + + if (!ctx) + return true; + + ensure(!rpcn::is_error(static_cast(reply_data[0])), "Unexpected error in CreateRoomGUI reply"); + + vec_stream reply(reply_data, 1); + const auto* resp = reply.get_flatbuffer(); + + if (reply.is_error()) + return error_and_disconnect("Malformed reply to CreateRoomGUI command"); + + event_data edata(np_memory.allocate(MAX_SceNpMatchingJoinedRoomInfo_SIZE), sizeof(SceNpMatchingJoinedRoomInfo), MAX_SceNpMatchingJoinedRoomInfo_SIZE); + auto* room_info = reinterpret_cast(edata.data()); + MatchingRoomStatus_to_SceNpMatchingJoinedRoomInfo(edata, resp, room_info); + np_memory.shrink_allocation(edata.addr(), edata.size()); + + gui_cache.add_room(room_info->room_status.id); + gui_cache.add_member(room_info->room_status.id, room_info->room_status.members.get_ptr(), true); + + set_gui_result(SCE_NP_MATCHING_GUI_EVENT_CREATE_ROOM, std::move(edata)); + ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_CREATE_ROOM, 0); + gui_epilog(ctx); + + return true; + } + + error_code np_handler::join_room_gui(u32 ctx_id, vm::ptr roomid, vm::ptr handler, vm::ptr arg) + { + auto [error, ctx] = gui_prelude(ctx_id, handler, arg); + + if (error) + return error; + + const u32 req_id = get_req_id(REQUEST_ID_HIGH::GUI); + add_gui_request(req_id, ctx_id); + + get_rpcn()->join_room_gui(req_id, *roomid); + + return CELL_OK; + } + + bool np_handler::reply_join_room_gui(u32 req_id, std::vector& reply_data) + { + auto ctx = take_pending_gui_request(req_id); + + if (!ctx) + return true; + + if (rpcn::is_error(static_cast(reply_data[0]))) + { + s32 error = -1; + + switch (static_cast(reply_data[0])) + { + case rpcn::ErrorType::RoomMissing: + error = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM; + break; + case rpcn::ErrorType::RoomFull: + // Might also be SCE_NP_MATCHING_SERVER_ERROR_ACCESS_FORBIDDEN or SCE_NP_MATCHING_SERVER_ERROR_NOT_ALLOWED ? + error = SCE_NP_MATCHING_SERVER_ERROR_ROOM_CLOSED; + break; + case rpcn::ErrorType::RoomAlreadyJoined: + error = SCE_NP_MATCHING_SERVER_ERROR_ACCESS_FORBIDDEN; + break; + default: + fmt::throw_exception("Unexpected error in JoinRoomGUI reply: %d", reply_data[0]); + break; + } + + ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_JOIN_ROOM, error); + gui_epilog(ctx); + return true; + } + + vec_stream reply(reply_data, 1); + const auto* resp = reply.get_flatbuffer(); + + if (reply.is_error()) + return error_and_disconnect("Malformed reply to JoinRoomGUI command"); + + event_data edata(np_memory.allocate(MAX_SceNpMatchingJoinedRoomInfo_SIZE), sizeof(SceNpMatchingJoinedRoomInfo), MAX_SceNpMatchingJoinedRoomInfo_SIZE); + auto* room_info = reinterpret_cast(edata.data()); + MatchingRoomStatus_to_SceNpMatchingJoinedRoomInfo(edata, resp, room_info); + np_memory.shrink_allocation(edata.addr(), edata.size()); + + extra_nps::print_SceNpMatchingJoinedRoomInfo(room_info); + + gui_cache.add_room(room_info->room_status.id); + + for (auto cur_member = room_info->room_status.members; cur_member; cur_member = cur_member->next) + { + gui_cache.add_member(room_info->room_status.id, cur_member.get_ptr(), true); + } + + set_gui_result(SCE_NP_MATCHING_GUI_EVENT_JOIN_ROOM, std::move(edata)); + ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_JOIN_ROOM, 0); + gui_epilog(ctx); + + return true; + } + + error_code np_handler::leave_room_gui(u32 ctx_id, vm::cptr roomid) + { + auto ctx = get_matching_context(ctx_id); + + if (!ctx) + return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; + + const u32 req_id = get_req_id(REQUEST_ID_HIGH::GUI); + add_gui_request(req_id, ctx_id); + + ensure(roomid); + extra_nps::print_SceNpRoomId(*roomid); + get_rpcn()->leave_room_gui(req_id, *roomid); + + return not_an_error(req_id); + } + + bool np_handler::reply_leave_room_gui(u32 req_id, std::vector& reply_data) + { + auto ctx = take_pending_gui_request(req_id); + + if (!ctx) + return true; + + if (rpcn::is_error(static_cast(reply_data[0]))) + { + s32 error = -1; + + switch (static_cast(reply_data[0])) + { + case rpcn::ErrorType::NotFound: + error = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM; + break; + default: + fmt::throw_exception("Unexpected error in LeaveRoomGUI reply: %d", reply_data[0]); + break; + } + + ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_LEAVE_ROOM_DONE, error); + return true; + } + + vec_stream reply(reply_data, 1); + const auto* resp = reply.get_flatbuffer(); + + if (reply.is_error()) + return error_and_disconnect("Malformed reply to LeaveRoomGUI command"); + + event_data edata(np_memory.allocate(MAX_SceNpMatchingRoomStatus_SIZE), sizeof(SceNpMatchingRoomStatus), MAX_SceNpMatchingRoomStatus_SIZE); + auto* room_status = reinterpret_cast(edata.data()); + MatchingRoomStatus_to_SceNpMatchingRoomStatus(edata, resp, room_status); + np_memory.shrink_allocation(edata.addr(), edata.size()); + + extra_nps::print_SceNpMatchingRoomStatus(room_status); + + gui_cache.del_room(room_status->id); + + gui_notifications.list.emplace(std::make_pair(gui_notifications.current_gui_ctx_id, req_id), gui_notification{.event = SCE_NP_MATCHING_EVENT_LEAVE_ROOM_DONE, .edata = std::move(edata)}); + ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_LEAVE_ROOM_DONE, 0); + return true; + } + + error_code np_handler::get_room_list_gui(u32 ctx_id, vm::cptr communicationId, vm::ptr range, vm::ptr cond, vm::ptr attr, vm::ptr handler, vm::ptr arg, bool limit) + { + auto [error, ctx] = gui_prelude(ctx_id, handler, arg); + + if (error) + return error; + + for (auto cur_cond = cond; cur_cond; cur_cond = cur_cond->next) + { + extra_nps::print_SceNpMatchingSearchCondition(cur_cond.get_ptr()); + } + + for (auto cur_attr = attr; cur_attr; cur_attr = cur_attr->next) + { + extra_nps::print_SceNpMatchingAttr(cur_attr.get_ptr()); + } + + ctx->get_room_limit_version = limit; + + const u32 req_id = get_req_id(REQUEST_ID_HIGH::GUI); + add_gui_request(req_id, ctx_id); + + ensure(range); + get_rpcn()->get_room_list_gui(req_id, *communicationId, range.get_ptr(), cond, attr); + + return CELL_OK; + } + + bool np_handler::reply_get_room_list_gui(u32 req_id, std::vector& reply_data) + { + auto ctx = take_pending_gui_request(req_id); + + if (!ctx) + return true; + + ensure(!rpcn::is_error(static_cast(reply_data[0])), "Unexpected error in GetRoomListGUI reply"); + + vec_stream reply(reply_data, 1); + const auto* resp = reply.get_flatbuffer(); + + if (reply.is_error()) + return error_and_disconnect("Malformed reply to GetRoomListGUI command"); + + event_data edata(np_memory.allocate(MAX_SceNpMatchingRoomList_SIZE), sizeof(SceNpMatchingRoomList), MAX_SceNpMatchingRoomList_SIZE); + auto* room_list = reinterpret_cast(edata.data()); + MatchingRoomList_to_SceNpMatchingRoomList(edata, resp, room_list); + np_memory.shrink_allocation(edata.addr(), edata.size()); + + extra_nps::print_SceNpMatchingRoomList(room_list); + + if (ctx->get_room_limit_version) + { + set_gui_result(SCE_NP_MATCHING_GUI_EVENT_GET_ROOM_LIST_LIMIT, std::move(edata)); + ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_GET_ROOM_LIST_LIMIT, 0); + } + else + { + set_gui_result(SCE_NP_MATCHING_GUI_EVENT_GET_ROOM_LIST, std::move(edata)); + ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_GET_ROOM_LIST, 0); + } + + gui_epilog(ctx); + return true; + } + + error_code np_handler::set_room_search_flag_gui(u32 ctx_id, vm::ptr /* lobby_id */, vm::ptr room_id, s32 flag) + { + auto ctx = get_matching_context(ctx_id); + + if (!ctx) + return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; + + const u32 req_id = get_req_id(REQUEST_ID_HIGH::GUI); + add_gui_request(req_id, ctx_id); + + ensure(room_id); + extra_nps::print_SceNpRoomId(*room_id); + get_rpcn()->set_room_search_flag_gui(req_id, *room_id, flag); + + return not_an_error(req_id); + } + + bool np_handler::reply_set_room_search_flag_gui(u32 req_id, std::vector& reply_data) + { + auto ctx = take_pending_gui_request(req_id); + + if (!ctx) + return true; + + s32 error = 0; + + if (rpcn::is_error(static_cast(reply_data[0]))) + { + switch (static_cast(reply_data[0])) + { + case rpcn::ErrorType::NotFound: + error = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM; + break; + case rpcn::ErrorType::Unauthorized: + error = SCE_NP_MATCHING_SERVER_ERROR_NOT_ALLOWED; + break; + default: + fmt::throw_exception("Unexpected error in SetRoomSearchFlagGUI reply: %d", reply_data[0]); + break; + } + } + + ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_SET_ROOM_SEARCH_FLAG_DONE, error); + return true; + } + + error_code np_handler::get_room_search_flag_gui(u32 ctx_id, vm::ptr /* lobby_id */, vm::ptr room_id) + { + auto ctx = get_matching_context(ctx_id); + + if (!ctx) + return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; + + const u32 req_id = get_req_id(REQUEST_ID_HIGH::GUI); + add_gui_request(req_id, ctx_id); + + ensure(room_id); + extra_nps::print_SceNpRoomId(*room_id); + get_rpcn()->get_room_search_flag_gui(req_id, *room_id); + + return not_an_error(req_id); + } + + bool np_handler::reply_get_room_search_flag_gui(u32 req_id, std::vector& reply_data) + { + auto ctx = take_pending_gui_request(req_id); + + if (!ctx) + return true; + + if (rpcn::is_error(static_cast(reply_data[0]))) + { + s32 error = -1; + + switch (static_cast(reply_data[0])) + { + case rpcn::ErrorType::NotFound: + error = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM; + break; + default: + fmt::throw_exception("Unexpected error in GetRoomSearchFlagGUI reply: %d", reply_data[0]); + break; + } + + ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_GET_ROOM_SEARCH_FLAG_DONE, error); + return true; + } + + vec_stream reply(reply_data, 1); + const auto* resp = reply.get_flatbuffer(); + + if (reply.is_error()) + return error_and_disconnect("Malformed reply to GetRoomSearchFlagGUI command"); + + event_data edata(np_memory.allocate(MAX_SceNpMatchingRoom_SIZE), sizeof(SceNpMatchingRoom), MAX_SceNpMatchingRoom_SIZE); + auto* room_info = reinterpret_cast(edata.data()); + MatchingRoom_to_SceNpMatchingRoom(edata, resp, room_info); + np_memory.shrink_allocation(edata.addr(), edata.size()); + + extra_nps::print_SceNpMatchingRoom(room_info); + + gui_notifications.list.emplace(std::make_pair(gui_notifications.current_gui_ctx_id, req_id), gui_notification{.event = SCE_NP_MATCHING_EVENT_GET_ROOM_SEARCH_FLAG_DONE, .edata = std::move(edata)}); + ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_GET_ROOM_SEARCH_FLAG_DONE, 0); + return true; + } + + error_code np_handler::set_room_info_gui(u32 ctx_id, vm::ptr /* lobby_id */, vm::ptr room_id, vm::ptr attr) + { + auto ctx = get_matching_context(ctx_id); + + if (!ctx) + return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; + + for (auto cur_attr = attr; cur_attr; cur_attr = cur_attr->next) + { + extra_nps::print_SceNpMatchingAttr(cur_attr.get_ptr()); + } + + const u32 req_id = get_req_id(REQUEST_ID_HIGH::GUI); + add_gui_request(req_id, ctx_id); + + ensure(room_id && attr); + // extra_nps::print_SceNpRoomId(*room_id); + get_rpcn()->set_room_info_gui(req_id, *room_id, attr); + + return not_an_error(req_id); + } + + bool np_handler::reply_set_room_info_gui(u32 req_id, std::vector& reply_data) + { + auto ctx = take_pending_gui_request(req_id); + + if (!ctx) + return true; + + s32 error = 0; + + if (rpcn::is_error(static_cast(reply_data[0]))) + { + switch (static_cast(reply_data[0])) + { + case rpcn::ErrorType::NotFound: + error = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM; + break; + case rpcn::ErrorType::Unauthorized: + error = SCE_NP_MATCHING_SERVER_ERROR_NOT_ALLOWED; + break; + default: + fmt::throw_exception("Unexpected error in SetRoomInfoGUI reply: %d", reply_data[0]); + break; + } + } + + ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_SET_ROOM_INFO_DONE, error); + return true; + } + + error_code np_handler::get_room_info_gui(u32 ctx_id, vm::ptr /* lobby_id */, vm::ptr room_id, vm::ptr attr) + { + auto ctx = get_matching_context(ctx_id); + + if (!ctx) + return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; + + const u32 req_id = get_req_id(REQUEST_ID_HIGH::GUI); + add_gui_request(req_id, ctx_id); + + ensure(room_id && attr); + // extra_nps::print_SceNpRoomId(*room_id); + get_rpcn()->get_room_info_gui(req_id, *room_id, attr); + + return not_an_error(req_id); + } + + bool np_handler::reply_get_room_info_gui(u32 req_id, std::vector& reply_data) + { + auto ctx = take_pending_gui_request(req_id); + + if (!ctx) + return true; + + if (rpcn::is_error(static_cast(reply_data[0]))) + { + s32 error = -1; + + switch (static_cast(reply_data[0])) + { + case rpcn::ErrorType::NotFound: + error = SCE_NP_MATCHING_SERVER_ERROR_NO_SUCH_ROOM; + break; + default: + fmt::throw_exception("Unexpected error in GetRoomInfoGUI reply: %d", reply_data[0]); + break; + } + + ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_GET_ROOM_INFO_DONE, error); + return true; + } + + vec_stream reply(reply_data, 1); + const auto* resp = reply.get_flatbuffer(); + + if (reply.is_error()) + return error_and_disconnect("Malformed reply to GetRoomInfoGUI command"); + + event_data edata(np_memory.allocate(MAX_SceNpMatchingRoom_SIZE), sizeof(SceNpMatchingRoom), MAX_SceNpMatchingRoom_SIZE); + auto* room_info = reinterpret_cast(edata.data()); + MatchingRoom_to_SceNpMatchingRoom(edata, resp, room_info); + np_memory.shrink_allocation(edata.addr(), edata.size()); + + extra_nps::print_SceNpMatchingRoom(room_info); + + gui_notifications.list.emplace(std::make_pair(gui_notifications.current_gui_ctx_id, req_id), gui_notification{.event = SCE_NP_MATCHING_EVENT_GET_ROOM_INFO_DONE, .edata = std::move(edata)}); + ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_GET_ROOM_INFO_DONE, 0); + return true; + } + + error_code np_handler::quickmatch_gui(u32 ctx_id, vm::cptr communicationId, vm::cptr cond, s32 available_num, s32 timeout, vm::ptr handler, vm::ptr arg) + { + auto [error, ctx] = gui_prelude(ctx_id, handler, arg); + + if (error) + return error; + + ctx->timeout = timeout; + const u32 req_id = get_req_id(REQUEST_ID_HIGH::GUI); + add_gui_request(req_id, ctx_id); + + get_rpcn()->quickmatch_gui(req_id, *communicationId, cond, available_num); + + return CELL_OK; + } + + bool np_handler::reply_quickmatch_gui(u32 req_id, std::vector& reply_data) + { + auto ctx = take_pending_gui_request(req_id); + + if (!ctx) + return true; + + ensure(!rpcn::is_error(static_cast(reply_data[0])), "Unexpected error in QuickMatchGUI reply"); + + vec_stream reply(reply_data, 1); + const auto* resp = reply.get_flatbuffer(); + + if (reply.is_error()) + return error_and_disconnect("Malformed reply to QuickMatchGUI command"); + + SceNpRoomId room_id{}; + ensure(resp->id() && resp->id()->size() == sizeof(SceNpRoomId::opt)); + std::memcpy(room_id.opt, resp->id()->data(), sizeof(SceNpRoomId::opt)); + const auto [_, inserted] = pending_quickmatching.insert_or_assign(room_id, ctx->ctx_id); + ensure(inserted); + + // Now that the reply has been received, we start the wait for the notification + ctx->thread = std::make_unique>>("NP GUI Timeout Worker", [ctx, req_id, this](SceNpRoomId room_id) + { + ctx->wakey.wait(0, static_cast(ctx->timeout * 1'000'000'000)); + + if (thread_ctrl::state() == thread_state::aborting) + return; + + { + std::lock_guard lock(this->mutex_quickmatching); + if (this->pending_quickmatching.erase(room_id) != 1) + return; + } + + if (ctx->wakey == 0) + { + // Verify that the context is still valid + if (!idm::check(ctx->ctx_id)) + return; + + rpcn_log.notice("QuickMatch timeout"); + + const u32 req_id = get_req_id(REQUEST_ID_HIGH::GUI); + this->get_rpcn()->leave_room_gui(req_id, room_id); + + ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_QUICK_MATCH, SCE_NP_MATCHING_ERROR_TIMEOUT); + gui_epilog(ctx); + } + }); + + ctx->wakey = 0; + auto& thread = *ctx->thread; + thread(room_id); + return true; + } + + error_code np_handler::searchjoin_gui(u32 ctx_id, vm::cptr communicationId, vm::cptr cond, vm::cptr attr, vm::ptr handler, vm::ptr arg) + { + auto [error, ctx] = gui_prelude(ctx_id, handler, arg); + + if (error) + return error; + + const u32 req_id = get_req_id(REQUEST_ID_HIGH::GUI); + add_gui_request(req_id, ctx_id); + + get_rpcn()->searchjoin_gui(req_id, *communicationId, cond, attr); + return CELL_OK; + } + + bool np_handler::reply_searchjoin_gui(u32 req_id, std::vector& reply_data) + { + auto ctx = take_pending_gui_request(req_id); + + if (!ctx) + return true; + + if (rpcn::is_error(static_cast(reply_data[0]))) + { + s32 error = -1; + + switch (static_cast(reply_data[0])) + { + case rpcn::ErrorType::NotFound: + error = SCE_NP_MATCHING_ERROR_SEARCH_JOIN_ROOM_NOT_FOUND; + break; + default: + fmt::throw_exception("Unexpected error in SearchJoinRoomGUI reply: %d", reply_data[0]); + break; + } + + ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_SEARCH_JOIN, error); + gui_epilog(ctx); + return true; + } + + vec_stream reply(reply_data, 1); + const auto* resp = reply.get_flatbuffer(); + + if (reply.is_error()) + return error_and_disconnect("Malformed reply to SearchJoinRoomGUI command"); + + event_data edata(np_memory.allocate(MAX_SceNpMatchingSearchJoinRoomInfo_SIZE), sizeof(SceNpMatchingSearchJoinRoomInfo), MAX_SceNpMatchingSearchJoinRoomInfo_SIZE); + auto* room_info = reinterpret_cast(edata.data()); + MatchingSearchJoinRoomInfo_to_SceNpMatchingSearchJoinRoomInfo(edata, resp, room_info); + np_memory.shrink_allocation(edata.addr(), edata.size()); + + extra_nps::print_SceNpMatchingSearchJoinRoomInfo(room_info); + + gui_cache.add_room(room_info->room_status.id); + + for (auto cur_member = room_info->room_status.members; cur_member; cur_member = cur_member->next) + { + gui_cache.add_member(room_info->room_status.id, cur_member.get_ptr(), true); + } + + set_gui_result(SCE_NP_MATCHING_GUI_EVENT_SEARCH_JOIN, std::move(edata)); + ctx->queue_gui_callback(SCE_NP_MATCHING_GUI_EVENT_SEARCH_JOIN, 0); + gui_epilog(ctx); + + return true; + } + + // Local cache requests + + error_code np_handler::get_room_member_list_local_gui(u32 ctx_id, vm::ptr room_id, vm::ptr buflen, vm::ptr buf) + { + auto ctx = get_matching_context(ctx_id); + + if (!ctx) + return SCE_NP_MATCHING_ERROR_CTX_NOT_FOUND; + + if (!room_id) + return SCE_NP_MATCHING_ERROR_ROOM_NOT_FOUND; + + if (!buf) + { + error_code room_size = gui_cache.get_room_member_list(*room_id, 0, {}); + + if (room_size < 0) + return room_size; + + *buflen = room_size; + return CELL_OK; + } + + return gui_cache.get_room_member_list(*room_id, *buflen, buf); + } + +} // namespace np diff --git a/rpcs3/Emu/NP/np_structs_extra.cpp b/rpcs3/Emu/NP/np_structs_extra.cpp index 1a3b8c5a8b..93b8a5ef70 100644 --- a/rpcs3/Emu/NP/np_structs_extra.cpp +++ b/rpcs3/Emu/NP/np_structs_extra.cpp @@ -35,7 +35,7 @@ namespace extra_nps const auto ptr = +bin->ptr; const u32 size = bin->size; - sceNp2.warning("Id: %d, Size: %d, ptr: 0x%x", bin->id, size, ptr); + sceNp2.warning("Id: %d, Size: %d, ptr: *0x%x", bin->id, size, ptr); if (ptr && size) { @@ -438,4 +438,121 @@ namespace extra_nps sceNp.warning("recordDate: %d", data->recordDate.tick); } + void print_SceNpMatchingAttr(const SceNpMatchingAttr* data) + { + sceNp.warning("SceNpMatchingAttr:"); + sceNp.warning("next: 0x%x", data->next); + sceNp.warning("type: %d", data->type); + sceNp.warning("id: %d", data->id); + + if (data->type == SCE_NP_MATCHING_ATTR_TYPE_BASIC_BIN || data->type == SCE_NP_MATCHING_ATTR_TYPE_GAME_BIN) + { + sceNp.warning("ptr: *0x%x", data->value.data.ptr); + sceNp.warning("size: %d", data->value.data.size); + sceNp.warning("data:\n%s", fmt::buf_to_hexstring(static_cast(data->value.data.ptr.get_ptr()), data->value.data.size)); + } + else + { + sceNp.warning("num: %d(0x%x)", data->value.num, data->value.num); + } + } + + void print_SceNpMatchingSearchCondition(const SceNpMatchingSearchCondition* data) + { + sceNp.warning("SceNpMatchingSearchCondition:"); + sceNp.warning("target_attr_type: %d", data->target_attr_type); + sceNp.warning("target_attr_id: %d", data->target_attr_id); + sceNp.warning("comp_type: %d", data->comp_type); + sceNp.warning("comp_op: %d", data->comp_op); + sceNp.warning("next: 0x%x", data->next); + print_SceNpMatchingAttr(&data->compared); + } + + void print_SceNpMatchingRoom(const SceNpMatchingRoom* data) + { + sceNp.warning("SceNpMatchingRoom:"); + sceNp.warning("next: 0x%x", data->next); + print_SceNpRoomId(data->id); + + for (auto it = data->attr; it; it = it->next) + { + print_SceNpMatchingAttr(it.get_ptr()); + } + } + + void print_SceNpMatchingRoomList(const SceNpMatchingRoomList* data) + { + sceNp.warning("SceNpMatchingRoomList:"); + sceNp.warning("lobbyid.opt: %s", fmt::buf_to_hexstring(data->lobbyid.opt, sizeof(data->lobbyid.opt), sizeof(data->lobbyid.opt))); + sceNp.warning("start: %d", data->range.start); + sceNp.warning("results: %d", data->range.results); + sceNp.warning("total: %d", data->range.total); + + for (auto it = data->head; it; it = it->next) + { + print_SceNpMatchingRoom(it.get_ptr()); + } + } + + void print_SceNpUserInfo(const SceNpUserInfo* data) + { + sceNp.warning("userId: %s", data->userId.handle.data); + sceNp.warning("name: %s", data->name.data); + sceNp.warning("icon: %s", data->icon.data); + } + + void print_SceNpRoomId(const SceNpRoomId& room_id) + { + sceNp.warning("room_id: %s", fmt::buf_to_hexstring(room_id.opt, sizeof(room_id.opt), sizeof(room_id.opt))); + } + + void print_SceNpMatchingRoomMember(const SceNpMatchingRoomMember* data) + { + sceNp.warning("SceNpMatchingRoomMember:"); + sceNp.warning("next: 0x%x", data->next); + sceNp.warning("owner: %d", data->owner); + print_SceNpUserInfo(&data->user_info); + } + + void print_SceNpMatchingRoomStatus(const SceNpMatchingRoomStatus* data) + { + sceNp.warning("SceNpMatchingRoomStatus:"); + print_SceNpRoomId(data->id); + sceNp.warning("members: 0x%x", data->members); + sceNp.warning("num: %d", data->num); + + for (auto it = data->members; it; it = it->next) + { + print_SceNpMatchingRoomMember(it.get_ptr()); + } + + sceNp.warning("kick_actor: 0x%x", data->kick_actor); + + if (data->kick_actor) + { + sceNp.warning("kick_actor: %s", data->kick_actor->handle.data); + } + + sceNp.warning("opt: 0x%x", data->kick_actor); + sceNp.warning("opt_len: %d", data->opt_len); + } + + void print_SceNpMatchingJoinedRoomInfo(const SceNpMatchingJoinedRoomInfo* data) + { + sceNp.warning("SceNpMatchingJoinedRoomInfo:"); + sceNp.warning("lobbyid.opt: %s", fmt::buf_to_hexstring(data->lobbyid.opt, sizeof(data->lobbyid.opt), sizeof(data->lobbyid.opt))); + print_SceNpMatchingRoomStatus(&data->room_status); + } + + void print_SceNpMatchingSearchJoinRoomInfo(const SceNpMatchingSearchJoinRoomInfo* data) + { + sceNp.warning("SceNpMatchingSearchJoinRoomInfo:"); + sceNp.warning("lobbyid.opt: %s", fmt::buf_to_hexstring(data->lobbyid.opt, sizeof(data->lobbyid.opt), sizeof(data->lobbyid.opt))); + print_SceNpMatchingRoomStatus(&data->room_status); + for (auto it = data->attr; it; it = it->next) + { + print_SceNpMatchingAttr(it.get_ptr()); + } + } + } // namespace extra_nps diff --git a/rpcs3/Emu/NP/np_structs_extra.h b/rpcs3/Emu/NP/np_structs_extra.h index 418a828719..072a37b1f3 100644 --- a/rpcs3/Emu/NP/np_structs_extra.h +++ b/rpcs3/Emu/NP/np_structs_extra.h @@ -30,4 +30,13 @@ namespace extra_nps void print_SceNpScoreRankData(const SceNpScoreRankData* data); void print_SceNpScoreRankData_deprecated(const SceNpScoreRankData_deprecated* data); + + void print_SceNpRoomId(const SceNpRoomId& room_id); + void print_SceNpMatchingAttr(const SceNpMatchingAttr* data); + void print_SceNpMatchingSearchCondition(const SceNpMatchingSearchCondition* data); + void print_SceNpMatchingRoom(const SceNpMatchingRoom* data); + void print_SceNpMatchingRoomList(const SceNpMatchingRoomList* data); + void print_SceNpMatchingRoomStatus(const SceNpMatchingRoomStatus* data); + void print_SceNpMatchingJoinedRoomInfo(const SceNpMatchingJoinedRoomInfo* data); + void print_SceNpMatchingSearchJoinRoomInfo(const SceNpMatchingSearchJoinRoomInfo* data); } // namespace extra_nps diff --git a/rpcs3/Emu/NP/rpcn_client.cpp b/rpcs3/Emu/NP/rpcn_client.cpp index c2b98e9163..e2608ee2c5 100644 --- a/rpcs3/Emu/NP/rpcn_client.cpp +++ b/rpcs3/Emu/NP/rpcn_client.cpp @@ -84,7 +84,7 @@ namespace rpcn rpcn_log.notice("online: %s, pr_com_id: %s, pr_title: %s, pr_status: %s, pr_comment: %s, pr_data: %s", online ? "true" : "false", pr_com_id.data, pr_title, pr_status, pr_comment, fmt::buf_to_hexstring(pr_data.data(), pr_data.size())); } - constexpr u32 RPCN_PROTOCOL_VERSION = 24; + constexpr u32 RPCN_PROTOCOL_VERSION = 25; constexpr usz RPCN_HEADER_SIZE = 15; bool is_error(ErrorType err) @@ -1305,7 +1305,7 @@ namespace rpcn bool rpcn_client::get_server_list(u32 req_id, const SceNpCommunicationId& communication_id, std::vector& server_list) { std::vector data(COMMUNICATION_ID_SIZE), reply_data; - memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + rpcn_client::write_communication_id(communication_id, data); if (!forge_send_reply(CommandType::GetServerList, req_id, data, reply_data)) { @@ -1368,7 +1368,7 @@ namespace rpcn bool rpcn_client::get_world_list(u32 req_id, const SceNpCommunicationId& communication_id, u16 server_id) { std::vector data(COMMUNICATION_ID_SIZE + sizeof(u16)); - memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + rpcn_client::write_communication_id(communication_id, data); reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = server_id; return forge_send(CommandType::GetWorldList, req_id, data); @@ -1795,7 +1795,7 @@ namespace rpcn { std::vector data(COMMUNICATION_ID_SIZE + sizeof(u64)); - memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + rpcn_client::write_communication_id(communication_id, data); write_to_ptr>(data, COMMUNICATION_ID_SIZE, room_id); return forge_send(CommandType::PingRoomOwner, req_id, data); @@ -1889,7 +1889,7 @@ namespace rpcn bool rpcn_client::get_board_infos(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id) { std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32)); - memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + rpcn_client::write_communication_id(communication_id, data); write_to_ptr>(data, COMMUNICATION_ID_SIZE, board_id); return forge_send(CommandType::GetBoardInfos, req_id, data); @@ -1951,7 +1951,7 @@ namespace rpcn const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize + sizeof(u32) + score_data.size()); - memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE); + rpcn_client::write_communication_id(communication_id, data); reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = static_cast(bufsize); memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize); reinterpret_cast&>(data[COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize]) = static_cast(score_data.size()); @@ -2192,19 +2192,290 @@ namespace rpcn return forge_request_with_com_id(builder, pr_com_id, CommandType::SetPresence, rpcn_request_counter.fetch_add(1)); } + bool rpcn_client::createjoin_room_gui(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatchingAttr* attr_list) + { + flatbuffers::FlatBufferBuilder builder(1024); + + u32 total_slots = 0; + u32 private_slots = 0; + bool privilege_grant = false; + bool stealth = false; + + std::vector> vec_attrs; + + for (const SceNpMatchingAttr* cur_attr = attr_list; cur_attr != nullptr; cur_attr = cur_attr->next ? cur_attr->next.get_ptr() : nullptr) + { + switch (cur_attr->type) + { + case SCE_NP_MATCHING_ATTR_TYPE_BASIC_NUM: + { + switch (cur_attr->id) + { + case SCE_NP_MATCHING_ROOM_ATTR_ID_TOTAL_SLOT: + total_slots = cur_attr->value.num; + break; + case SCE_NP_MATCHING_ROOM_ATTR_ID_PRIVATE_SLOT: + private_slots = cur_attr->value.num; + break; + case SCE_NP_MATCHING_ROOM_ATTR_ID_PRIVILEGE_TYPE: + ensure(cur_attr->value.num == SCE_NP_MATCHING_ROOM_PRIVILEGE_TYPE_NO_AUTO_GRANT || cur_attr->value.num == SCE_NP_MATCHING_ROOM_PRIVILEGE_TYPE_AUTO_GRANT, "Invalid SCE_NP_MATCHING_ROOM_ATTR_ID_PRIVILEGE_TYPE value"); + privilege_grant = (cur_attr->value.num == SCE_NP_MATCHING_ROOM_PRIVILEGE_TYPE_AUTO_GRANT); + break; + case SCE_NP_MATCHING_ROOM_ATTR_ID_ROOM_SEARCH_FLAG: + ensure(cur_attr->value.num == SCE_NP_MATCHING_ROOM_SEARCH_FLAG_OPEN || cur_attr->value.num == SCE_NP_MATCHING_ROOM_SEARCH_FLAG_STEALTH, "Invalid SCE_NP_MATCHING_ROOM_ATTR_ID_ROOM_SEARCH_FLAG value"); + stealth = (cur_attr->value.num == SCE_NP_MATCHING_ROOM_SEARCH_FLAG_STEALTH); + break; + default: + fmt::throw_exception("Invalid basic num attribute id"); + break; + } + + break; + } + case SCE_NP_MATCHING_ATTR_TYPE_GAME_BIN: + { + ensure(cur_attr->id >= 1u && cur_attr->id <= 16u, "Invalid game bin attribute id"); + ensure(cur_attr->value.data.size <= 64u || ((cur_attr->id == 1u || cur_attr->id == 2u) && cur_attr->value.data.size <= 256u), "Invalid game bin size"); + + const std::vector vec_data(static_cast(cur_attr->value.data.ptr.get_ptr()), static_cast(cur_attr->value.data.ptr.get_ptr()) + cur_attr->value.data.size); + auto attr = CreateMatchingAttrDirect(builder, cur_attr->type, cur_attr->id, 0, &vec_data); + vec_attrs.push_back(attr); + break; + } + case SCE_NP_MATCHING_ATTR_TYPE_GAME_NUM: + { + ensure(cur_attr->id >= 1u && cur_attr->id <= 16u, "Invalid game num attribute id"); + + auto attr = CreateMatchingAttrDirect(builder, cur_attr->type, cur_attr->id, cur_attr->value.num, nullptr); + vec_attrs.push_back(attr); + break; + } + default: + fmt::throw_exception("Invalid attribute type"); + } + } + + flatbuffers::Offset>> final_attrs_vec; + + if (!vec_attrs.empty()) + { + final_attrs_vec = builder.CreateVector(vec_attrs); + } + + auto req_finished = CreateCreateRoomGUIRequest(builder, total_slots, private_slots, privilege_grant, stealth, final_attrs_vec); + builder.Finish(req_finished); + + return forge_request_with_com_id(builder, communication_id, CommandType::CreateRoomGUI, req_id); + } + + bool rpcn_client::join_room_gui(u32 req_id, const SceNpRoomId& room_id) + { + flatbuffers::FlatBufferBuilder builder(1024); + const std::vector vec_room_id(room_id.opt, room_id.opt + sizeof(room_id.opt)); + auto req_finished = CreateMatchingGuiRoomIdDirect(builder, &vec_room_id); + builder.Finish(req_finished); + return forge_request_with_data(builder, CommandType::JoinRoomGUI, req_id); + } + + bool rpcn_client::leave_room_gui(u32 req_id, const SceNpRoomId& room_id) + { + flatbuffers::FlatBufferBuilder builder(1024); + const std::vector vec_room_id(room_id.opt, room_id.opt + sizeof(room_id.opt)); + auto req_finished = CreateMatchingGuiRoomIdDirect(builder, &vec_room_id); + builder.Finish(req_finished); + return forge_request_with_data(builder, CommandType::LeaveRoomGUI, req_id); + } + + bool rpcn_client::get_room_list_gui(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatchingReqRange* range, vm::ptr cond, vm::ptr attr) + { + flatbuffers::FlatBufferBuilder builder(1024); + + const s32 range_start = range->start; + const u32 range_max = range->max; + + std::vector> vec_conds; + std::vector> vec_attrs; + + for (auto cur_cond = cond; cur_cond; cur_cond = cur_cond->next) + { + auto fb_cond = CreateMatchingSearchCondition(builder, cur_cond->target_attr_type, cur_cond->target_attr_id, cur_cond->comp_op, cur_cond->compared.value.num); + vec_conds.push_back(fb_cond); + } + + for (auto cur_attr = attr; cur_attr; cur_attr = cur_attr->next) + { + auto fb_attr = CreateMatchingAttr(builder, cur_attr->type, cur_attr->id); + vec_attrs.push_back(fb_attr); + } + + flatbuffers::Offset>> final_conds_vec; + flatbuffers::Offset>> final_attrs_vec; + + if (!vec_conds.empty()) + { + final_conds_vec = builder.CreateVector(vec_conds); + } + + if (!vec_attrs.empty()) + { + final_attrs_vec = builder.CreateVector(vec_attrs); + } + + auto req_finished = CreateGetRoomListGUIRequest(builder, range_start, range_max, final_conds_vec, final_attrs_vec); + builder.Finish(req_finished); + + return forge_request_with_com_id(builder, communication_id, CommandType::GetRoomListGUI, req_id); + } + + bool rpcn_client::set_room_search_flag_gui(u32 req_id, const SceNpRoomId& room_id, bool stealth) + { + flatbuffers::FlatBufferBuilder builder(1024); + const std::vector vec_room_id(room_id.opt, room_id.opt + sizeof(room_id.opt)); + auto req_finished = CreateSetRoomSearchFlagGUIDirect(builder, &vec_room_id, stealth); + builder.Finish(req_finished); + return forge_request_with_data(builder, CommandType::SetRoomSearchFlagGUI, req_id); + } + + bool rpcn_client::get_room_search_flag_gui(u32 req_id, const SceNpRoomId& room_id) + { + flatbuffers::FlatBufferBuilder builder(1024); + const std::vector vec_room_id(room_id.opt, room_id.opt + sizeof(room_id.opt)); + auto req_finished = CreateMatchingGuiRoomIdDirect(builder, &vec_room_id); + builder.Finish(req_finished); + return forge_request_with_data(builder, CommandType::GetRoomSearchFlagGUI, req_id); + } + + bool rpcn_client::set_room_info_gui(u32 req_id, const SceNpRoomId& room_id, vm::ptr attrs) + { + flatbuffers::FlatBufferBuilder builder(1024); + const std::vector vec_room_id(room_id.opt, room_id.opt + sizeof(room_id.opt)); + std::vector> vec_attrs; + + for (auto cur_attr = attrs; cur_attr; cur_attr = cur_attr->next) + { + u32 num = 0; + flatbuffers::Offset> fb_vec_data = 0; + + switch (cur_attr->type) + { + case SCE_NP_MATCHING_ATTR_TYPE_GAME_BIN: + { + const std::vector vec_data(static_cast(cur_attr->value.data.ptr.get_ptr()), static_cast(cur_attr->value.data.ptr.get_ptr()) + cur_attr->value.data.size); + fb_vec_data = builder.CreateVector(vec_data); + break; + } + case SCE_NP_MATCHING_ATTR_TYPE_GAME_NUM: + { + num = cur_attr->value.num; + break; + } + default: + { + fmt::throw_exception("Invalid attr type reached set_room_info_gui"); + break; + } + } + + auto fb_attr = CreateMatchingAttr(builder, cur_attr->type, cur_attr->id, num, fb_vec_data); + vec_attrs.push_back(fb_attr); + } + + auto req_finished = CreateMatchingRoomDirect(builder, &vec_room_id, &vec_attrs); + builder.Finish(req_finished); + return forge_request_with_data(builder, CommandType::SetRoomInfoGUI, req_id); + } + + bool rpcn_client::get_room_info_gui(u32 req_id, const SceNpRoomId& room_id, vm::ptr attrs) + { + flatbuffers::FlatBufferBuilder builder(1024); + const std::vector vec_room_id(room_id.opt, room_id.opt + sizeof(room_id.opt)); + std::vector> vec_attrs; + + for (auto cur_attr = attrs; cur_attr; cur_attr = cur_attr->next) + { + auto fb_attr = CreateMatchingAttr(builder, cur_attr->type, cur_attr->id); + vec_attrs.push_back(fb_attr); + } + + auto req_finished = CreateMatchingRoomDirect(builder, &vec_room_id, &vec_attrs); + builder.Finish(req_finished); + return forge_request_with_data(builder, CommandType::GetRoomInfoGUI, req_id); + } + + bool rpcn_client::quickmatch_gui(u32 req_id, const SceNpCommunicationId& com_id, vm::cptr cond, s32 available_num) + { + flatbuffers::FlatBufferBuilder builder(1024); + std::vector> vec_conds; + + for (auto cur_cond = cond; cur_cond; cur_cond = cur_cond->next) + { + auto fb_cond = CreateMatchingSearchCondition(builder, cur_cond->target_attr_type, cur_cond->target_attr_id, cur_cond->comp_op, cur_cond->compared.value.num); + vec_conds.push_back(fb_cond); + } + + auto req_finished = CreateQuickMatchGUIRequestDirect(builder, &vec_conds, available_num); + builder.Finish(req_finished); + return forge_request_with_com_id(builder, com_id, CommandType::QuickMatchGUI, req_id); + } + + bool rpcn_client::searchjoin_gui(u32 req_id, const SceNpCommunicationId& com_id, vm::cptr cond, vm::cptr attr) + { + flatbuffers::FlatBufferBuilder builder(1024); + + std::vector> vec_conds; + std::vector> vec_attrs; + + for (auto cur_cond = cond; cur_cond; cur_cond = cur_cond->next) + { + auto fb_cond = CreateMatchingSearchCondition(builder, cur_cond->target_attr_type, cur_cond->target_attr_id, cur_cond->comp_op, cur_cond->compared.value.num); + vec_conds.push_back(fb_cond); + } + + for (auto cur_attr = attr; cur_attr; cur_attr = cur_attr->next) + { + auto fb_attr = CreateMatchingAttr(builder, cur_attr->type, cur_attr->id); + vec_attrs.push_back(fb_attr); + } + + auto req_finished = CreateSearchJoinRoomGUIRequestDirect(builder, vec_conds.empty() ? nullptr : &vec_conds, vec_attrs.empty() ? nullptr : &vec_attrs); + builder.Finish(req_finished); + return forge_request_with_com_id(builder, com_id, CommandType::SearchJoinRoomGUI, req_id); + } + + void rpcn_client::write_communication_id(const SceNpCommunicationId& com_id, std::vector& data) + { + ensure(com_id.data[9] == 0 && com_id.num <= 99, "rpcn_client::write_communication_id: Invalid SceNpCommunicationId"); + const std::string com_id_str = np::communication_id_to_string(com_id); + ensure(com_id_str.size() == 12, "rpcn_client::write_communication_id: Error formatting SceNpCommunicationId"); + memcpy(data.data(), com_id_str.data(), COMMUNICATION_ID_SIZE); + } + bool rpcn_client::forge_request_with_com_id(const flatbuffers::FlatBufferBuilder& builder, const SceNpCommunicationId& com_id, CommandType command, u64 packet_id) { const u8* buf = builder.GetBufferPointer(); const usz bufsize = builder.GetSize(); std::vector data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize); - memcpy(data.data(), com_id.data, COMMUNICATION_ID_SIZE); + rpcn_client::write_communication_id(com_id, data); + reinterpret_cast&>(data[COMMUNICATION_ID_SIZE]) = static_cast(bufsize); memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize); return forge_send(command, packet_id, data); } + bool rpcn_client::forge_request_with_data(const flatbuffers::FlatBufferBuilder& builder, CommandType command, u64 packet_id) + { + const u8* buf = builder.GetBufferPointer(); + const usz bufsize = builder.GetSize(); + std::vector data(sizeof(u32) + bufsize); + + reinterpret_cast&>(data[0]) = static_cast(bufsize); + memcpy(data.data() + sizeof(u32), buf, bufsize); + + return forge_send(command, packet_id, data); + } + std::vector rpcn_client::forge_request(u16 command, u64 packet_id, const std::vector& data) const { const usz packet_size = data.size() + RPCN_HEADER_SIZE; diff --git a/rpcs3/Emu/NP/rpcn_client.h b/rpcs3/Emu/NP/rpcn_client.h index c1f9f1e11a..dafe57d991 100644 --- a/rpcs3/Emu/NP/rpcn_client.h +++ b/rpcs3/Emu/NP/rpcn_client.h @@ -39,7 +39,12 @@ #pragma GCC diagnostic pop #endif -constexpr usz COMMUNICATION_ID_SIZE = 9; +// COMID is sent as 9 chars - + '_' + 2 digits +constexpr usz COMMUNICATION_ID_COMID_COMPONENT_SIZE = 9; +constexpr usz COMMUNICATION_ID_SUBID_COMPONENT_SIZE = 2; +constexpr usz COMMUNICATION_ID_SIZE = COMMUNICATION_ID_COMID_COMPONENT_SIZE + COMMUNICATION_ID_SUBID_COMPONENT_SIZE + 1; + + class vec_stream { @@ -110,7 +115,17 @@ public: } SceNpCommunicationId com_id{}; - std::memcpy(&com_id.data[0], &vec[i], COMMUNICATION_ID_SIZE); + std::memcpy(&com_id.data[0], &vec[i], COMMUNICATION_ID_COMID_COMPONENT_SIZE); + const std::string sub_id(reinterpret_cast(&vec[i + COMMUNICATION_ID_COMID_COMPONENT_SIZE + 1]), COMMUNICATION_ID_SUBID_COMPONENT_SIZE); + const unsigned long result_num = std::strtoul(sub_id.c_str(), nullptr, 10); + + if (result_num > 99) + { + error = true; + return {}; + } + + com_id.num = static_cast(result_num); i += COMMUNICATION_ID_SIZE; return com_id; } @@ -223,6 +238,16 @@ namespace rpcn TusDeleteMultiSlotData, ClearPresence, SetPresence, + CreateRoomGUI, + JoinRoomGUI, + LeaveRoomGUI, + GetRoomListGUI, + SetRoomSearchFlagGUI, + GetRoomSearchFlagGUI, + SetRoomInfoGUI, + GetRoomInfoGUI, + QuickMatchGUI, + SearchJoinRoomGUI, }; enum NotificationType : u16 @@ -242,6 +267,12 @@ namespace rpcn MessageReceived, FriendPresenceChanged, SignalingInfo, + MemberJoinedRoomGUI, + MemberLeftRoomGUI, + RoomDisappearedGUI, + RoomOwnerChangedGUI, + UserKickedGUI, + QuickMatchCompleteGUI, }; enum class rpcn_state @@ -485,6 +516,16 @@ namespace rpcn bool tus_get_friends_data_status(u32 req_id, SceNpCommunicationId& communication_id, SceNpTusSlotId slotId, bool includeSelf, s32 sortType, s32 arrayNum); bool tus_delete_multislot_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser); bool send_presence(const SceNpCommunicationId& pr_com_id, const std::string& pr_title, const std::string& pr_status, const std::string& pr_comment, const std::vector& pr_data); + bool createjoin_room_gui(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatchingAttr* attr_list); + bool join_room_gui(u32 req_id, const SceNpRoomId& room_id); + bool leave_room_gui(u32 req_id, const SceNpRoomId& room_id); + bool get_room_list_gui(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatchingReqRange* range, vm::ptr cond, vm::ptr attr); + bool set_room_search_flag_gui(u32 req_id, const SceNpRoomId& room_id, bool stealth); + bool get_room_search_flag_gui(u32 req_id, const SceNpRoomId& room_id); + bool set_room_info_gui(u32 req_id, const SceNpRoomId& room_id, vm::ptr attrs); + bool get_room_info_gui(u32 req_id, const SceNpRoomId& room_id, vm::ptr attrs); + bool quickmatch_gui(u32 req_id, const SceNpCommunicationId& com_id, vm::cptr cond, s32 available_num); + bool searchjoin_gui(u32 req_id, const SceNpCommunicationId& com_id, vm::cptr cond, vm::cptr attr); const std::string& get_online_name() const; const std::string& get_avatar_url() const; @@ -497,9 +538,12 @@ namespace rpcn private: bool get_reply(u64 expected_id, std::vector& data); + static void write_communication_id(const SceNpCommunicationId& com_id, std::vector& data); + std::vector forge_request(u16 command, u64 packet_id, const std::vector& data) const; bool forge_send(u16 command, u64 packet_id, const std::vector& data); bool forge_request_with_com_id(const flatbuffers::FlatBufferBuilder& builder, const SceNpCommunicationId& com_id, CommandType command, u64 packet_id); + bool forge_request_with_data(const flatbuffers::FlatBufferBuilder& builder, CommandType command, u64 packet_id); bool forge_send_reply(u16 command, u64 packet_id, const std::vector& data, std::vector& reply_data); bool error_and_disconnect(const std::string& error_mgs); diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 3ea574f5f8..ddf6c92a7d 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -147,8 +147,10 @@ + + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index d3902de896..1316809abc 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -978,12 +978,18 @@ Emu\NP + + Emu\NP + Emu\NP Emu\NP + + Emu\NP + Emu\NP