From 2e4a187145dfc807a5c92ae7d8a5408f6da07549 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 25 Jan 2026 00:36:24 +0300 Subject: [PATCH 01/40] vk: Persist debug name in the image wrapper to aid in debugging --- rpcs3/Emu/RSX/VK/vkutils/image.cpp | 2 ++ rpcs3/Emu/RSX/VK/vkutils/image.h | 1 + 2 files changed, 3 insertions(+) diff --git a/rpcs3/Emu/RSX/VK/vkutils/image.cpp b/rpcs3/Emu/RSX/VK/vkutils/image.cpp index 02d9bf34bd..e1c1faa8da 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/image.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/image.cpp @@ -304,6 +304,8 @@ namespace vk _vkSetDebugUtilsObjectNameEXT(m_device, &name_info); } + + m_debug_name = name; } image_view::image_view(VkDevice dev, VkImage image, VkImageViewType view_type, VkFormat format, VkComponentMapping mapping, VkImageSubresourceRange range) diff --git a/rpcs3/Emu/RSX/VK/vkutils/image.h b/rpcs3/Emu/RSX/VK/vkutils/image.h index 91ebf5616e..18baf19646 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/image.h +++ b/rpcs3/Emu/RSX/VK/vkutils/image.h @@ -33,6 +33,7 @@ namespace vk VkImageAspectFlags m_storage_aspect = 0; rsx::format_class m_format_class = RSX_FORMAT_CLASS_UNDEFINED; + std::string m_debug_name; void validate(const vk::render_device& dev, const VkImageCreateInfo& info) const; From 11087a973c95988d56478e24dfd7abbcb7c8aed7 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 25 Jan 2026 01:33:03 +0300 Subject: [PATCH 02/40] vk: Set debug names for image views - Crucial for debugging hangs and crashes as well as VVL output --- rpcs3/Emu/RSX/VK/vkutils/image.cpp | 27 +++++++++++++++++++++++++++ rpcs3/Emu/RSX/VK/vkutils/image.h | 2 ++ 2 files changed, 29 insertions(+) diff --git a/rpcs3/Emu/RSX/VK/vkutils/image.cpp b/rpcs3/Emu/RSX/VK/vkutils/image.cpp index e1c1faa8da..5e4c8ce022 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/image.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/image.cpp @@ -207,6 +207,11 @@ namespace vk return m_format_class; } + std::string image::debug_name() const + { + return m_debug_name; + } + void image::push_layout(const command_buffer& cmd, VkImageLayout layout) { ensure(current_queue_family == VK_QUEUE_FAMILY_IGNORED || current_queue_family == cmd.get_queue_family()); @@ -407,6 +412,14 @@ namespace vk // Restore requested mapping info.components = mapping; #endif + + if (m_resource) + { + if (const auto name = m_resource->debug_name(); !name.empty()) + { + set_debug_name(fmt::format("%p (%p) %s", value, m_resource->value, name)); + } + } } viewable_image* viewable_image::clone() @@ -490,4 +503,18 @@ namespace vk views.clear(); } } + + void image_view::set_debug_name(std::string_view name) + { + if (g_render_device->get_debug_utils_support()) + { + VkDebugUtilsObjectNameInfoEXT name_info{}; + name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; + name_info.objectType = VK_OBJECT_TYPE_IMAGE_VIEW; + name_info.objectHandle = reinterpret_cast(value); + name_info.pObjectName = name.data(); + + _vkSetDebugUtilsObjectNameEXT(m_device, &name_info); + } + } } diff --git a/rpcs3/Emu/RSX/VK/vkutils/image.h b/rpcs3/Emu/RSX/VK/vkutils/image.h index 18baf19646..fbe7abb5fd 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/image.h +++ b/rpcs3/Emu/RSX/VK/vkutils/image.h @@ -84,6 +84,7 @@ namespace vk VkSharingMode sharing_mode() const; VkImageAspectFlags aspect() const; rsx::format_class format_class() const; + std::string debug_name() const; // Pipeline management void push_layout(const command_buffer& cmd, VkImageLayout layout); @@ -128,6 +129,7 @@ namespace vk vk::image* m_resource = nullptr; void create_impl(); + void set_debug_name(std::string_view name); }; class viewable_image : public image From 11464f0793056430c0ab4e990952da719510226f Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 25 Jan 2026 01:44:01 +0300 Subject: [PATCH 03/40] vk: Tighten image barriers to account for IMAGE_OP_LOAD operation when starting a renderpass --- rpcs3/Emu/RSX/VK/VKDraw.cpp | 8 +++-- rpcs3/Emu/RSX/VK/VKPresent.cpp | 2 +- rpcs3/Emu/RSX/VK/vkutils/barriers.cpp | 14 ++++++--- rpcs3/Emu/RSX/VK/vkutils/image_helpers.cpp | 36 +++++++++++++++++++--- 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKDraw.cpp b/rpcs3/Emu/RSX/VK/VKDraw.cpp index b73b4a66a8..739253cc03 100644 --- a/rpcs3/Emu/RSX/VK/VKDraw.cpp +++ b/rpcs3/Emu/RSX/VK/VKDraw.cpp @@ -74,16 +74,20 @@ namespace vk // This was used in a cyclic ref before, but is missing a barrier // No need for a full stall, use a custom barrier instead VkPipelineStageFlags src_stage; - VkAccessFlags src_access; + VkAccessFlags src_access, dst_access; if (raw->aspect() == VK_IMAGE_ASPECT_COLOR_BIT) { src_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; src_access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dst_access = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + dst_stage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; } else { src_stage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; src_access = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + dst_access = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + dst_stage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; } vk::insert_image_memory_barrier( @@ -91,7 +95,7 @@ namespace vk raw->value, raw->current_layout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, src_stage, dst_stage, - src_access, VK_ACCESS_SHADER_READ_BIT, + src_access, dst_access, { raw->aspect(), 0, 1, 0, 1 }); raw->current_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index 3eac2821de..d474af2139 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -790,7 +790,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) barrier.oldLayout = target_layout; barrier.image = target_image; barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.subresourceRange = subresource_range; diff --git a/rpcs3/Emu/RSX/VK/vkutils/barriers.cpp b/rpcs3/Emu/RSX/VK/vkutils/barriers.cpp index fb1bb84e34..6a7e518749 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/barriers.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/barriers.cpp @@ -94,19 +94,25 @@ namespace vk vk::end_renderpass(cmd); } - VkAccessFlags src_access; - VkPipelineStageFlags src_stage; + VkAccessFlags src_access, dst_access; + VkPipelineStageFlags src_stage, dst_stage; if (range.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) { src_access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dst_access = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; src_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dst_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; } else { src_access = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + dst_access = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; src_stage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dst_stage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; } + dst_stage |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT; + VkImageMemoryBarrier barrier = {}; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.newLayout = new_layout; @@ -116,9 +122,9 @@ namespace vk barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.subresourceRange = range; barrier.srcAccessMask = src_access; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + barrier.dstAccessMask = dst_access; - vkCmdPipelineBarrier(cmd, src_stage, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier); + vkCmdPipelineBarrier(cmd, src_stage, dst_stage, 0, 0, nullptr, 0, nullptr, 1, &barrier); } void insert_texture_barrier(const vk::command_buffer& cmd, vk::image* image, VkImageLayout new_layout, bool preserve_renderpass) diff --git a/rpcs3/Emu/RSX/VK/vkutils/image_helpers.cpp b/rpcs3/Emu/RSX/VK/vkutils/image_helpers.cpp index e8d8bc9c0d..de0345fdb4 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/image_helpers.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/image_helpers.cpp @@ -58,6 +58,8 @@ namespace vk VkPipelineStageFlags src_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; VkPipelineStageFlags dst_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + const bool is_color_surface = !!(range.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT); + switch (+new_layout) { case VK_IMAGE_LAYOUT_GENERAL: @@ -89,17 +91,30 @@ namespace vk dst_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; break; case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; dst_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break; case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; dst_stage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; break; case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; + dst_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT; + break; case VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT: barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; - dst_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dst_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT; + if (is_color_surface) + { + barrier.dstAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dst_stage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + } + else + { + barrier.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + dst_stage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + } break; case VK_IMAGE_LAYOUT_UNDEFINED: case VK_IMAGE_LAYOUT_PREINITIALIZED: @@ -170,12 +185,25 @@ namespace vk src_stage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break; case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; + src_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT; + break; case VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT: barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; src_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + if (is_color_surface) + { + barrier.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + src_stage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + } + else + { + barrier.srcAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + src_stage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + } break; default: - break; //TODO Investigate what happens here + break; } barrier.srcAccessMask &= src_access_mask_bits; From 318385787a2b463dee1ffba2bfa179c13ae2400f Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 25 Jan 2026 18:54:23 +0300 Subject: [PATCH 04/40] vk: Force strict query scopes quirk if SRM is enabled --- rpcs3/Emu/RSX/VK/VKHelpers.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.cpp b/rpcs3/Emu/RSX/VK/VKHelpers.cpp index f59878ec18..9360215797 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.cpp +++ b/rpcs3/Emu/RSX/VK/VKHelpers.cpp @@ -90,6 +90,7 @@ namespace vk g_drv_no_primitive_restart = false; g_drv_sanitize_fp_values = false; g_drv_disable_fence_reset = false; + g_drv_strict_query_scopes = !!g_cfg.video.strict_rendering_mode; g_drv_emulate_cond_render = (g_cfg.video.relaxed_zcull_sync && !g_render_device->get_conditional_render_support()); g_num_processed_frames = 0; g_num_total_frames = 0; From 9dfaca4cd85d737e6913bd1918e73d770b2b0e23 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 25 Jan 2026 18:54:43 +0300 Subject: [PATCH 05/40] vk: Fix WAW hazard when preparing copy commands for texture uploads using scratch --- rpcs3/Emu/RSX/VK/VKTexture.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKTexture.cpp b/rpcs3/Emu/RSX/VK/VKTexture.cpp index a57378384a..bc6aabf2d4 100644 --- a/rpcs3/Emu/RSX/VK/VKTexture.cpp +++ b/rpcs3/Emu/RSX/VK/VKTexture.cpp @@ -1183,6 +1183,13 @@ namespace vk { ensure(scratch_buf); + // WAW hazard - complete previous work before executing any transfers + insert_buffer_memory_barrier( + cmd2, scratch_buf->value, 0, scratch_offset, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + if (upload_commands.size() > 1) { auto range_ptr = buffer_copies.data(); @@ -1197,8 +1204,11 @@ namespace vk vkCmdCopyBuffer(cmd2, upload_buffer->value, scratch_buf->value, static_cast(buffer_copies.size()), buffer_copies.data()); } - insert_buffer_memory_barrier(cmd2, scratch_buf->value, 0, scratch_offset, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); + insert_buffer_memory_barrier( + cmd2, scratch_buf->value, 0, scratch_offset, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); } // Swap and deswizzle if requested From 29cb4f59bd3f75ca63575d84a278b48220ab6fe5 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 25 Jan 2026 19:26:42 +0300 Subject: [PATCH 06/40] vk: Invalidate renderpass key in post-cyclic-z barrier - Post-Z renderpass split is crucial due to loss of writes. The failure to invalidate the renderpass key was an oversight. --- rpcs3/Emu/RSX/VK/VKDraw.cpp | 21 +++++++++++++++------ rpcs3/Emu/RSX/VK/VKGSRender.h | 1 + 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKDraw.cpp b/rpcs3/Emu/RSX/VK/VKDraw.cpp index 739253cc03..59f9bfb40a 100644 --- a/rpcs3/Emu/RSX/VK/VKDraw.cpp +++ b/rpcs3/Emu/RSX/VK/VKDraw.cpp @@ -143,6 +143,17 @@ VkRenderPass VKGSRender::get_render_pass() return m_cached_renderpass; } +void VKGSRender::invalidate_render_pass() +{ + // Regenerate renderpass key for the next draw call + if (const auto key = vk::get_renderpass_key(m_fbo_images, m_current_renderpass_key); + key != m_current_renderpass_key) + { + m_current_renderpass_key = key; + m_cached_renderpass = VK_NULL_HANDLE; + } +} + void VKGSRender::update_draw_state() { m_profiler.start(); @@ -514,12 +525,7 @@ void VKGSRender::load_texture_env() if (check_for_cyclic_refs) { // Regenerate renderpass key - if (const auto key = vk::get_renderpass_key(m_fbo_images, m_current_renderpass_key); - key != m_current_renderpass_key) - { - m_current_renderpass_key = key; - m_cached_renderpass = VK_NULL_HANDLE; - } + invalidate_render_pass(); } if (backend_config.supports_asynchronous_compute) @@ -1069,6 +1075,9 @@ void VKGSRender::end() // Since we're ending the subpass, might as well restore DCC/HiZ for extra performance ds->change_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); ds->reset_surface_counters(); + + // Regenerate render pass key + invalidate_render_pass(); } } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index b0edaa48f6..aa62df2122 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -227,6 +227,7 @@ private: void begin_render_pass(); void close_render_pass(); VkRenderPass get_render_pass(); + void invalidate_render_pass(); void update_draw_state(); void check_present_status(); From a907cc838bc2f06e09da9b4b4c9a8d0ff01db20b Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 25 Jan 2026 19:27:32 +0300 Subject: [PATCH 07/40] vk: Always specify LATE_FRAGMENT_TESTS and EARLY_FRAGMENT_TESTS together when declaring barriers - The combination of access patterns can go either way, do not assume early testing to always take place. --- rpcs3/Emu/RSX/VK/vkutils/image_helpers.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/RSX/VK/vkutils/image_helpers.cpp b/rpcs3/Emu/RSX/VK/vkutils/image_helpers.cpp index de0345fdb4..2e97e5ad22 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/image_helpers.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/image_helpers.cpp @@ -78,6 +78,7 @@ namespace vk VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT }; break; @@ -96,7 +97,7 @@ namespace vk break; case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; - dst_stage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dst_stage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break; case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; From 33d79ee2cd1c24afa2721c43da82ef6ee20e845b Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 25 Jan 2026 20:39:52 +0300 Subject: [PATCH 08/40] vk: Fix CPU frame misalignment bug - This one has been around for a really long time. - The frame-based structure was due to translating the original vulkan tutorial to working code. - While it is not feasible to throw the arch away, we don't need a rigid 2-frame set for acquire-submit semaphores. --- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 25 +++++++++++----------- rpcs3/Emu/RSX/VK/VKGSRender.h | 5 +++-- rpcs3/Emu/RSX/VK/VKGSRenderTypes.hpp | 15 ++++++++++++- rpcs3/Emu/RSX/VK/VKPresent.cpp | 32 ++++++++++++++++++++++------ 4 files changed, 55 insertions(+), 22 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 4a0e6c19ce..cba661a64b 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -505,9 +505,6 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar) m_occlusion_query_manager->set_control_flags(VK_QUERY_CONTROL_PRECISE_BIT, 0); } - VkSemaphoreCreateInfo semaphore_info = {}; - semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - // VRAM allocation // This first set is bound persistently, so grow notifications are enabled. m_attrib_ring_info.create(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VK_ATTRIB_RING_BUFFER_SIZE_M * 0x100000, vk::heap_pool_default, "attrib buffer", 0x400000, VK_TRUE); @@ -570,10 +567,13 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar) rsx_log.warning("Current driver may crash due to memory limitations (%uk)", m_texbuffer_view_size / 1024); } - for (auto &ctx : frame_context_storage) + m_max_async_frames = m_swapchain->get_swap_image_count(); + m_frame_context_storage.resize(m_max_async_frames); + m_current_frame = &m_frame_context_storage[0]; + + for (auto& ctx : m_frame_context_storage) { - vkCreateSemaphore((*m_device), &semaphore_info, nullptr, &ctx.present_wait_semaphore); - vkCreateSemaphore((*m_device), &semaphore_info, nullptr, &ctx.acquire_signal_semaphore); + ctx.init(*m_device); } const auto& memory_map = m_device->get_memory_mapping(); @@ -612,8 +612,6 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar) } - m_current_frame = &frame_context_storage[0]; - m_texture_cache.initialize((*m_device), m_device->get_graphics_queue(), m_texture_upload_buffer_ring_info); @@ -830,16 +828,17 @@ VKGSRender::~VKGSRender() if (m_current_frame == &m_aux_frame_context) { // Return resources back to the owner - m_current_frame = &frame_context_storage[m_current_queue_index]; + m_current_frame = &m_frame_context_storage[m_current_queue_index]; m_current_frame->grab_resources(m_aux_frame_context); } - // NOTE: aux_context uses descriptor pools borrowed from the main queues and any allocations will be automatically freed when pool is destroyed - for (auto &ctx : frame_context_storage) + // CPU frame contexts + for (auto &ctx : m_frame_context_storage) { - vkDestroySemaphore((*m_device), ctx.present_wait_semaphore, nullptr); - vkDestroySemaphore((*m_device), ctx.acquire_signal_semaphore, nullptr); + ctx.destroy(*m_device); } + m_current_frame = nullptr; + m_frame_context_storage.clear(); // Textures m_rtts.destroy(); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index aa62df2122..faae1bb78f 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -159,8 +159,9 @@ private: u64 m_texture_parameters_dynamic_offset = 0; u64 m_stipple_array_dynamic_offset = 0; - std::array frame_context_storage; - //Temp frame context to use if the real frame queue is overburdened. Only used for storage + std::vector m_frame_context_storage; + u32 m_max_async_frames = 0u; + // Temp frame context to use if the real frame queue is overburdened. Only used for storage vk::frame_context_t m_aux_frame_context; u32 m_current_queue_index = 0; diff --git a/rpcs3/Emu/RSX/VK/VKGSRenderTypes.hpp b/rpcs3/Emu/RSX/VK/VKGSRenderTypes.hpp index 429e428a18..0a400c68d9 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRenderTypes.hpp +++ b/rpcs3/Emu/RSX/VK/VKGSRenderTypes.hpp @@ -23,7 +23,6 @@ #define VK_INDEX_RING_BUFFER_SIZE_M 16 #define VK_MAX_ASYNC_CB_COUNT 512 -#define VK_MAX_ASYNC_FRAMES 2 #define FRAME_PRESENT_TIMEOUT 10000000ull // 10 seconds #define GENERAL_WAIT_TIMEOUT 2000000ull // 2 seconds @@ -186,6 +185,20 @@ namespace vk data_heap_manager::managed_heap_snapshot_t heap_snapshot; u64 last_frame_sync_time = 0; + void init(VkDevice dev) + { + VkSemaphoreCreateInfo semaphore_info = {}; + semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + vkCreateSemaphore(dev, &semaphore_info, nullptr, &present_wait_semaphore); + vkCreateSemaphore(dev, &semaphore_info, nullptr, &acquire_signal_semaphore); + } + + void destroy(VkDevice dev) + { + vkDestroySemaphore(dev, present_wait_semaphore, nullptr); + vkDestroySemaphore(dev, acquire_signal_semaphore, nullptr); + } + // Copy shareable information void grab_resources(frame_context_t& other) { diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index d474af2139..eb30f9f2d6 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -52,7 +52,7 @@ void VKGSRender::reinitialize_swapchain() m_current_command_buffer->reset(); m_current_command_buffer->begin(); - for (auto &ctx : frame_context_storage) + for (auto &ctx : m_frame_context_storage) { if (ctx.present_image == umax) continue; @@ -67,6 +67,16 @@ void VKGSRender::reinitialize_swapchain() // Drain all the queues vkDeviceWaitIdle(*m_device); + // Reset frame context storage + for (auto& ctx : m_frame_context_storage) + { + ctx.destroy(*m_device); + } + m_current_frame = nullptr; + m_max_async_frames = 0; + m_current_queue_index = 0; + m_frame_context_storage.clear(); + // Rebuild swapchain. Old swapchain destruction is handled by the init_swapchain call if (!m_swapchain->init(m_swapchain_dims.width, m_swapchain_dims.height)) { @@ -75,6 +85,16 @@ void VKGSRender::reinitialize_swapchain() return; } + // Re-initialize CPU frame contexts + m_max_async_frames = m_swapchain->get_swap_image_count(); + m_frame_context_storage.resize(m_max_async_frames); + for (auto& ctx : m_frame_context_storage) + { + ctx.init(*m_device); + } + m_current_queue_index = 0; + m_current_frame = &m_frame_context_storage[0]; + // Prepare new swapchain images for use for (u32 i = 0; i < m_swapchain->get_swap_image_count(); ++i) { @@ -158,10 +178,10 @@ void VKGSRender::advance_queued_frames() m_current_frame->tag_frame_end(); m_queued_frames.push_back(m_current_frame); - ensure(m_queued_frames.size() <= VK_MAX_ASYNC_FRAMES); + ensure(m_queued_frames.size() <= m_max_async_frames); - m_current_queue_index = (m_current_queue_index + 1) % VK_MAX_ASYNC_FRAMES; - m_current_frame = &frame_context_storage[m_current_queue_index]; + m_current_queue_index = (m_current_queue_index + 1) % m_max_async_frames; + m_current_frame = &m_frame_context_storage[m_current_queue_index]; m_current_frame->flags |= frame_context_state::dirty; vk::advance_frame_counter(); @@ -398,7 +418,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) if (m_current_frame == &m_aux_frame_context) { - m_current_frame = &frame_context_storage[m_current_queue_index]; + m_current_frame = &m_frame_context_storage[m_current_queue_index]; if (m_current_frame->swap_command_buffer) { // Its possible this flip request is triggered by overlays and the flip queue is in undefined state @@ -520,7 +540,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) ensure(m_current_frame->present_image == umax); ensure(m_current_frame->swap_command_buffer == nullptr); - u64 timeout = m_swapchain->get_swap_image_count() <= VK_MAX_ASYNC_FRAMES? 0ull: 100000000ull; + u64 timeout = m_swapchain->get_swap_image_count() <= 2? 0ull: 100000000ull; while (VkResult status = m_swapchain->acquire_next_swapchain_image(m_current_frame->acquire_signal_semaphore, timeout, &m_current_frame->present_image)) { switch (status) From 9b09fba8117dad097d43ac961a5ad13cb78c7317 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 25 Jan 2026 21:00:48 +0300 Subject: [PATCH 09/40] vk: Prevent WAW hazard when the window size exceeds the output draw box --- rpcs3/Emu/RSX/VK/VKPresent.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index eb30f9f2d6..08006d8dbd 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -612,6 +612,19 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) vk::change_image_layout(*m_current_command_buffer, target_image, present_layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresource_range); vkCmdClearColorImage(*m_current_command_buffer, target_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_black, 1, &subresource_range); + // Prevent WAW on transfer writes + vk::insert_image_memory_barrier( + *m_current_command_buffer, + target_image, + target_layout, + target_layout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + subresource_range + ); + target_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; } From fb420d5989573d564c6871aa04027d9be79d838c Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 25 Jan 2026 21:30:22 +0300 Subject: [PATCH 10/40] vk: Fix flood of VVL synchronization violations appearing when capturing media --- rpcs3/Emu/RSX/VK/VKPresent.cpp | 202 +++++++++++++++++---------------- 1 file changed, 103 insertions(+), 99 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index 08006d8dbd..4f4517d062 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -605,6 +605,109 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) vk::framebuffer_holder* direct_fbo = nullptr; rsx::simple_array calibration_src; + const bool has_overlay = (m_overlay_manager && m_overlay_manager->has_visible()); + const bool user_asked_for_screenshot = g_user_asked_for_screenshot.exchange(false); + const bool user_is_recording = (g_recording_mode != recording_mode::stopped && m_frame->can_consume_frame()); + const bool need_media_capture = user_asked_for_screenshot || user_is_recording; + + const auto render_overlays = [&](vk::framebuffer_holder* fbo, const areau& area) + { + if (!has_overlay) return; + + // Lock to avoid modification during run-update chain + auto ui_renderer = vk::get_overlay_pass(); + std::lock_guard lock(*m_overlay_manager); + + for (const auto& view : m_overlay_manager->get_views()) + { + ui_renderer->run(*m_current_command_buffer, area, fbo, single_target_pass, m_texture_upload_buffer_ring_info, *view.get()); + } + }; + + // WARNING: We have to do this here. We cannot touch the acquired image on the CB and then do a hard sync on it before it is submitted to the presentation engine. + // That introduces a WRITE_AFTER_PRESENT (from the previous present) when we later try to present on a different CB + if (image_to_flip && need_media_capture) + { + const usz sshot_size = buffer_height * buffer_width * 4; + + vk::buffer sshot_vkbuf(*m_device, utils::align(sshot_size, 0x100000), m_device->get_memory_mapping().host_visible_coherent, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0, VMM_ALLOCATION_POOL_UNDEFINED); + + VkBufferImageCopy copy_info{}; + copy_info.bufferOffset = 0; + copy_info.bufferRowLength = 0; + copy_info.bufferImageHeight = 0; + copy_info.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy_info.imageSubresource.baseArrayLayer = 0; + copy_info.imageSubresource.layerCount = 1; + copy_info.imageSubresource.mipLevel = 0; + copy_info.imageOffset.x = 0; + copy_info.imageOffset.y = 0; + copy_info.imageOffset.z = 0; + copy_info.imageExtent.width = buffer_width; + copy_info.imageExtent.height = buffer_height; + copy_info.imageExtent.depth = 1; + + vk::image* image_to_copy = image_to_flip; + + if (g_cfg.video.record_with_overlays && has_overlay) + { + const auto key = vk::get_renderpass_key(m_swapchain->get_surface_format()); + single_target_pass = vk::get_renderpass(*m_device, key); + ensure(single_target_pass != VK_NULL_HANDLE); + + if (!m_overlay_recording_img || + m_overlay_recording_img->type() != image_to_flip->type() || + m_overlay_recording_img->format() != image_to_flip->format() || + m_overlay_recording_img->width() != image_to_flip->width() || + m_overlay_recording_img->height() != image_to_flip->height() || + m_overlay_recording_img->layers() != image_to_flip->layers()) + { + m_overlay_recording_img = std::make_unique(*m_device, m_device->get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + image_to_flip->type(), image_to_flip->format(), image_to_flip->width(), image_to_flip->height(), 1, 1, image_to_flip->layers(), VK_SAMPLE_COUNT_1_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + 0, VMM_ALLOCATION_POOL_UNDEFINED); + } + + m_overlay_recording_img->change_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + image_to_flip->push_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + const areai rect = areai(0, 0, buffer_width, buffer_height); + vk::copy_image(*m_current_command_buffer, image_to_flip, m_overlay_recording_img.get(), rect, rect, 1); + + image_to_flip->pop_layout(*m_current_command_buffer); + m_overlay_recording_img->change_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + vk::framebuffer_holder* sshot_fbo = vk::get_framebuffer(*m_device, buffer_width, buffer_height, VK_FALSE, single_target_pass, { m_overlay_recording_img.get() }); + sshot_fbo->add_ref(); + render_overlays(sshot_fbo, areau(rect)); + sshot_fbo->release(); + + image_to_copy = m_overlay_recording_img.get(); + } + + image_to_copy->push_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + vk::copy_image_to_buffer(*m_current_command_buffer, image_to_copy, &sshot_vkbuf, copy_info); + image_to_copy->pop_layout(*m_current_command_buffer); + + flush_command_queue(true); + const auto src = sshot_vkbuf.map(0, sshot_size); + std::vector sshot_frame(sshot_size); + memcpy(sshot_frame.data(), src, sshot_size); + sshot_vkbuf.unmap(); + + const bool is_bgra = image_to_copy->format() == VK_FORMAT_B8G8R8A8_UNORM; + + if (user_asked_for_screenshot) + { + m_frame->take_screenshot(std::move(sshot_frame), buffer_width, buffer_height, is_bgra); + } + else + { + m_frame->present_frame(std::move(sshot_frame), buffer_width * 4, buffer_width, buffer_height, is_bgra); + } + } + if (!image_to_flip || aspect_ratio.x1 || aspect_ratio.y1) { // Clear the window background to black @@ -648,21 +751,6 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) } } - const bool has_overlay = (m_overlay_manager && m_overlay_manager->has_visible()); - const auto render_overlays = [&](vk::framebuffer_holder* fbo, const areau& area) - { - if (!has_overlay) return; - - // Lock to avoid modification during run-update chain - auto ui_renderer = vk::get_overlay_pass(); - std::lock_guard lock(*m_overlay_manager); - - for (const auto& view : m_overlay_manager->get_views()) - { - ui_renderer->run(*m_current_command_buffer, area, fbo, single_target_pass, m_texture_upload_buffer_ring_info, *view.get()); - } - }; - if (image_to_flip) { const bool use_full_rgb_range_output = g_cfg.video.full_rgb_range_output.get(); @@ -726,90 +814,6 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) m_upscaler->scale_output(*m_current_command_buffer, image_to_flip, target_image, target_layout, rgn, UPSCALE_AND_COMMIT | UPSCALE_DEFAULT_VIEW); } - - const bool user_asked_for_screenshot = g_user_asked_for_screenshot.exchange(false); - - if (user_asked_for_screenshot || (g_recording_mode != recording_mode::stopped && m_frame->can_consume_frame())) - { - const usz sshot_size = buffer_height * buffer_width * 4; - - vk::buffer sshot_vkbuf(*m_device, utils::align(sshot_size, 0x100000), m_device->get_memory_mapping().host_visible_coherent, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0, VMM_ALLOCATION_POOL_UNDEFINED); - - VkBufferImageCopy copy_info {}; - copy_info.bufferOffset = 0; - copy_info.bufferRowLength = 0; - copy_info.bufferImageHeight = 0; - copy_info.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_info.imageSubresource.baseArrayLayer = 0; - copy_info.imageSubresource.layerCount = 1; - copy_info.imageSubresource.mipLevel = 0; - copy_info.imageOffset.x = 0; - copy_info.imageOffset.y = 0; - copy_info.imageOffset.z = 0; - copy_info.imageExtent.width = buffer_width; - copy_info.imageExtent.height = buffer_height; - copy_info.imageExtent.depth = 1; - - vk::image* image_to_copy = image_to_flip; - - if (g_cfg.video.record_with_overlays && has_overlay) - { - const auto key = vk::get_renderpass_key(m_swapchain->get_surface_format()); - single_target_pass = vk::get_renderpass(*m_device, key); - ensure(single_target_pass != VK_NULL_HANDLE); - - if (!m_overlay_recording_img || - m_overlay_recording_img->type() != image_to_flip->type() || - m_overlay_recording_img->format() != image_to_flip->format() || - m_overlay_recording_img->width() != image_to_flip->width() || - m_overlay_recording_img->height() != image_to_flip->height() || - m_overlay_recording_img->layers() != image_to_flip->layers()) - { - m_overlay_recording_img = std::make_unique(*m_device, m_device->get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - image_to_flip->type(), image_to_flip->format(), image_to_flip->width(), image_to_flip->height(), 1, 1, image_to_flip->layers(), VK_SAMPLE_COUNT_1_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - 0, VMM_ALLOCATION_POOL_UNDEFINED); - } - - m_overlay_recording_img->change_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - image_to_flip->push_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - - const areai rect = areai(0, 0, buffer_width, buffer_height); - vk::copy_image(*m_current_command_buffer, image_to_flip, m_overlay_recording_img.get(), rect, rect, 1); - - image_to_flip->pop_layout(*m_current_command_buffer); - m_overlay_recording_img->change_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - - vk::framebuffer_holder* sshot_fbo = vk::get_framebuffer(*m_device, buffer_width, buffer_height, VK_FALSE, single_target_pass, { m_overlay_recording_img.get() }); - sshot_fbo->add_ref(); - render_overlays(sshot_fbo, areau(rect)); - sshot_fbo->release(); - - image_to_copy = m_overlay_recording_img.get(); - } - - image_to_copy->push_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - vk::copy_image_to_buffer(*m_current_command_buffer, image_to_copy, &sshot_vkbuf, copy_info); - image_to_copy->pop_layout(*m_current_command_buffer); - - flush_command_queue(true); - const auto src = sshot_vkbuf.map(0, sshot_size); - std::vector sshot_frame(sshot_size); - memcpy(sshot_frame.data(), src, sshot_size); - sshot_vkbuf.unmap(); - - const bool is_bgra = image_to_copy->format() == VK_FORMAT_B8G8R8A8_UNORM; - - if (user_asked_for_screenshot) - { - m_frame->take_screenshot(std::move(sshot_frame), buffer_width, buffer_height, is_bgra); - } - else - { - m_frame->present_frame(std::move(sshot_frame), buffer_width * 4, buffer_width, buffer_height, is_bgra); - } - } } if (g_cfg.video.debug_overlay || has_overlay) From 0ee3e24b25a119ac8810c30a5065ab846419214b Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 26 Jan 2026 00:23:48 +0300 Subject: [PATCH 11/40] vk: Drain the pending frame queue before resizing the swapchain --- rpcs3/Emu/RSX/VK/VKPresent.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index 4f4517d062..f9fbb114ed 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -61,6 +61,21 @@ void VKGSRender::reinitialize_swapchain() frame_context_cleanup(&ctx); } + // NOTE: frame_context_cleanup alters the queued_frames structure. + while (!m_queued_frames.empty()) + { + auto& frame = m_queued_frames.front(); + if (!frame->swap_command_buffer) + { + // Drop it + m_queued_frames.pop_front(); + continue; + } + + frame_context_cleanup(frame); + } + ensure(m_queued_frames.empty()); + // Discard the current upscaling pipeline if any m_upscaler.reset(); From 818b11fd2fa2607334f781213e26da5fbb8506b5 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 26 Jan 2026 15:55:03 +0300 Subject: [PATCH 12/40] Revert adrenalin crash workaround --- rpcs3/Emu/RSX/VK/vkutils/device.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/RSX/VK/vkutils/device.cpp b/rpcs3/Emu/RSX/VK/vkutils/device.cpp index 14752f160c..f7b7ffb19c 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/device.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/device.cpp @@ -102,7 +102,7 @@ namespace vk multidraw_support.max_batch_size = 65536; optional_features_support.barycentric_coords = !!shader_barycentric_info.fragmentShaderBarycentric; - optional_features_support.framebuffer_loops = !!fbo_loops_info.attachmentFeedbackLoopLayout && get_driver_vendor() != driver_vendor::AMD; + optional_features_support.framebuffer_loops = !!fbo_loops_info.attachmentFeedbackLoopLayout; optional_features_support.extended_device_fault = !!device_fault_info.deviceFault; features = features2.features; From 0e2584fc9f367c2d3cd3e0ce578fb81b0e74b6ce Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Sun, 25 Jan 2026 07:10:50 +0100 Subject: [PATCH 13/40] sceNpBasicLimitedSendMessage --- rpcs3/Emu/Cell/Modules/sceNp.cpp | 65 ++++++++++++++++++++++++++++++-- rpcs3/Emu/Cell/PPUModule.cpp | 1 + rpcs3/Emu/Cell/PPUModule.h | 1 + 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/sceNp.cpp b/rpcs3/Emu/Cell/Modules/sceNp.cpp index 2b49309a9b..ee9c308265 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp.cpp @@ -1118,10 +1118,35 @@ error_code sceNpBasicSetPresenceDetails2(vm::cptr pr return CELL_OK; } -error_code sceNpBasicSendMessage(vm::cptr to, vm::cptr data, u32 size) -{ - sceNp.warning("sceNpBasicSendMessage(to=*0x%x, data=*0x%x, size=%d)", to, data, size); +u64 sys_time_get_system_time(); +error_code acquire_time_slot(u64* time_array, usz array_size, u64 slot_duration) +{ + static shared_mutex mutex; + std::lock_guard lock(mutex); + + const u64 current_time = sys_time_get_system_time(); + + for (usz index = 0; index < array_size; index++) + { + if (time_array[index] == 0) + { + time_array[index] = current_time; + return CELL_OK; + } + + if (current_time > (time_array[index] + slot_duration)) + { + time_array[index] = current_time; + return CELL_OK; + } + } + + return SCE_NP_BASIC_ERROR_BUSY; +} + +error_code _sceNpBasicSendMessage(vm::cptr to, vm::cptr data, u32 size, bool rate_limited) +{ auto& nph = g_fxo->get>(); if (!nph.is_NP_init) @@ -1144,6 +1169,22 @@ error_code sceNpBasicSendMessage(vm::cptr to, vm::cptr data, u32 return SCE_NP_BASIC_ERROR_EXCEEDS_MAX; } + if (rate_limited) + { + struct sceNpBasicSendMessage_time_slots + { + sceNpBasicSendMessage_time_slots(sceNpBasicSendMessage_time_slots&&) = delete; + std::array data{}; + }; + + auto& time_slots = g_fxo->get(); + + if (auto error = acquire_time_slot(time_slots.data.data(), time_slots.data.size(), 60000000); error != CELL_OK) + { + return error; + } + } + if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE) { return not_an_error(SCE_NP_BASIC_ERROR_NOT_CONNECTED); @@ -1164,6 +1205,19 @@ error_code sceNpBasicSendMessage(vm::cptr to, vm::cptr data, u32 return CELL_OK; } +error_code sceNpBasicSendMessage(vm::cptr to, vm::cptr data, u32 size) +{ + sceNp.warning("sceNpBasicSendMessage(to=*0x%x, data=*0x%x, size=%d)", to, data, size); + return _sceNpBasicSendMessage(to, data, size, false); +} + +// This function is sceNpBasicSendMessage + a rate limiter that will return SCE_NP_BASIC_ERROR_BUSY if it too many messages have been sent +error_code sceNpBasicLimited_0xEB42E2E6(vm::cptr to, vm::cptr data, u32 size) +{ + sceNp.warning("sceNpBasicLimited_0xEB42E2E6(to=*0x%x, data=*0x%x, size=%d)", to, data, size); + return _sceNpBasicSendMessage(to, data, size, true); +} + error_code sceNpBasicSendMessageGui(ppu_thread& ppu, vm::cptr msg, sys_memory_container_t containerId) { sceNp.warning("sceNpBasicSendMessageGui(msg=*0x%x, containerId=%d)", msg, containerId); @@ -7289,6 +7343,11 @@ s32 _Z32_sce_np_sysutil_cxml_prepare_docPN16sysutil_cxmlutil11FixedMemoryERN4cxm return CELL_OK; } +DECLARE(ppu_module_manager::sceNpBasicLimited) +("sceNpBasicLimited", []() { + ppu_module_manager::register_static_function<&sceNpBasicLimited_0xEB42E2E6>("sceNpBasicLimited", ppu_select_name("sceNpBasicLimited", "sceNpBasicLimited_0xEB42E2E6"), BIND_FUNC_WITH_BLR(sceNpBasicLimited_0xEB42E2E6, "sceNpBasicLimited"), 0xEB42E2E6); +}); + DECLARE(ppu_module_manager::sceNp) ("sceNp", []() { REG_FUNC(sceNp, sceNpInit); diff --git a/rpcs3/Emu/Cell/PPUModule.cpp b/rpcs3/Emu/Cell/PPUModule.cpp index 65ab0fe18d..b298539519 100644 --- a/rpcs3/Emu/Cell/PPUModule.cpp +++ b/rpcs3/Emu/Cell/PPUModule.cpp @@ -314,6 +314,7 @@ static void ppu_initialize_modules(ppu_linkage_info* link, utils::serial* ar = n &ppu_module_manager::libsnd3, &ppu_module_manager::libsynth2, &ppu_module_manager::sceNp, + &ppu_module_manager::sceNpBasicLimited, &ppu_module_manager::sceNp2, &ppu_module_manager::sceNpClans, &ppu_module_manager::sceNpCommerce2, diff --git a/rpcs3/Emu/Cell/PPUModule.h b/rpcs3/Emu/Cell/PPUModule.h index fdcd736f38..6171a4faa1 100644 --- a/rpcs3/Emu/Cell/PPUModule.h +++ b/rpcs3/Emu/Cell/PPUModule.h @@ -283,6 +283,7 @@ public: static const ppu_static_module libsnd3; static const ppu_static_module libsynth2; static const ppu_static_module sceNp; + static const ppu_static_module sceNpBasicLimited; static const ppu_static_module sceNp2; static const ppu_static_module sceNpClans; static const ppu_static_module sceNpCommerce2; From 8f8032b5a8959397e2d03bef9f3a6e0bf6a3560d Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Mon, 26 Jan 2026 09:36:59 +0100 Subject: [PATCH 14/40] Implement sceNpMatching2GetSignalingOptParamLocal --- rpcs3/Emu/Cell/Modules/sceNp2.cpp | 24 + rpcs3/Emu/NP/generated/np2_structs.pb.cc | 421 ++++++++++++++- rpcs3/Emu/NP/generated/np2_structs.pb.h | 656 ++++++++++++++++++++--- rpcs3/Emu/NP/generated/np2_structs.proto | 95 +--- rpcs3/Emu/NP/np_cache.cpp | 17 + rpcs3/Emu/NP/np_cache.h | 4 + rpcs3/Emu/NP/np_handler.cpp | 5 + rpcs3/Emu/NP/np_handler.h | 1 + rpcs3/Emu/NP/np_requests.cpp | 55 +- rpcs3/Emu/NP/pb_helpers.cpp | 7 + rpcs3/Emu/NP/pb_helpers.h | 1 + rpcs3/Emu/NP/rpcn_client.cpp | 2 +- 12 files changed, 1096 insertions(+), 192 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/sceNp2.cpp b/rpcs3/Emu/Cell/Modules/sceNp2.cpp index 820fbdf1c0..b6ad47b846 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp2.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp2.cpp @@ -1335,6 +1335,30 @@ error_code sceNpMatching2GetSignalingOptParamLocal(SceNpMatching2ContextId ctxId return SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED; } + if (!ctxId) + { + return SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID; + } + + if (!roomId) + { + return SCE_NP_MATCHING2_ERROR_INVALID_ROOM_ID; + } + + if (!check_match2_context(ctxId)) + { + return SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND; + } + + const auto [error, signaling_opt_param] = nph.local_get_signaling_opt_param(roomId); + + if (error) + { + return error; + } + + *signalingOptParam = *signaling_opt_param; + return CELL_OK; } diff --git a/rpcs3/Emu/NP/generated/np2_structs.pb.cc b/rpcs3/Emu/NP/generated/np2_structs.pb.cc index 756b12b0dc..6416723f11 100644 --- a/rpcs3/Emu/NP/generated/np2_structs.pb.cc +++ b/rpcs3/Emu/NP/generated/np2_structs.pb.cc @@ -2555,7 +2555,8 @@ inline constexpr JoinRoomResponse::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept : _cached_size_{0}, signaling_data_{}, - room_data_{nullptr} {} + room_data_{nullptr}, + opt_param_{nullptr} {} template PROTOBUF_CONSTEXPR JoinRoomResponse::JoinRoomResponse(::_pbi::ConstantInitialized) @@ -2576,6 +2577,32 @@ struct JoinRoomResponseDefaultTypeInternal { PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 JoinRoomResponseDefaultTypeInternal _JoinRoomResponse_default_instance_; + +inline constexpr CreateRoomResponse::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + internal_{nullptr}, + opt_param_{nullptr} {} + +template +PROTOBUF_CONSTEXPR CreateRoomResponse::CreateRoomResponse(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::MessageLite(CreateRoomResponse_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::MessageLite(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct CreateRoomResponseDefaultTypeInternal { + PROTOBUF_CONSTEXPR CreateRoomResponseDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~CreateRoomResponseDefaultTypeInternal() {} + union { + CreateRoomResponse _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 CreateRoomResponseDefaultTypeInternal _CreateRoomResponse_default_instance_; } // namespace np2_structs namespace np2_structs { // =================================================================== @@ -11934,6 +11961,324 @@ void CreateJoinRoomRequest::InternalSwap(CreateJoinRoomRequest* PROTOBUF_RESTRIC // =================================================================== +class CreateRoomResponse::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(CreateRoomResponse, _impl_._has_bits_); +}; + +CreateRoomResponse::CreateRoomResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::MessageLite(arena, CreateRoomResponse_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::MessageLite(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:np2_structs.CreateRoomResponse) +} +PROTOBUF_NDEBUG_INLINE CreateRoomResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::np2_structs::CreateRoomResponse& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0} {} + +CreateRoomResponse::CreateRoomResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const CreateRoomResponse& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::MessageLite(arena, CreateRoomResponse_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::MessageLite(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + CreateRoomResponse* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::std::string>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.internal_ = (CheckHasBit(cached_has_bits, 0x00000001U)) + ? ::google::protobuf::MessageLite::CopyConstruct(arena, *from._impl_.internal_) + : nullptr; + _impl_.opt_param_ = (CheckHasBit(cached_has_bits, 0x00000002U)) + ? ::google::protobuf::MessageLite::CopyConstruct(arena, *from._impl_.opt_param_) + : nullptr; + + // @@protoc_insertion_point(copy_constructor:np2_structs.CreateRoomResponse) +} +PROTOBUF_NDEBUG_INLINE CreateRoomResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void CreateRoomResponse::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, internal_), + 0, + offsetof(Impl_, opt_param_) - + offsetof(Impl_, internal_) + + sizeof(Impl_::opt_param_)); +} +CreateRoomResponse::~CreateRoomResponse() { + // @@protoc_insertion_point(destructor:np2_structs.CreateRoomResponse) + SharedDtor(*this); +} +inline void CreateRoomResponse::SharedDtor(MessageLite& self) { + CreateRoomResponse& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::std::string>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.internal_; + delete this_._impl_.opt_param_; + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL CreateRoomResponse::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) CreateRoomResponse(arena); +} +constexpr auto CreateRoomResponse::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(CreateRoomResponse), + alignof(CreateRoomResponse)); +} +constexpr auto CreateRoomResponse::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataLite<31>{ + { + &_CreateRoomResponse_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &CreateRoomResponse::MergeImpl, + ::google::protobuf::MessageLite::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &CreateRoomResponse::SharedDtor, + ::google::protobuf::MessageLite::GetClearImpl(), &CreateRoomResponse::ByteSizeLong, + &CreateRoomResponse::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(CreateRoomResponse, _impl_._cached_size_), + true, + }, + "np2_structs.CreateRoomResponse", + }; +} + +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::google::protobuf::internal::ClassDataLite<31> CreateRoomResponse_class_data_ = + CreateRoomResponse::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +CreateRoomResponse::GetClassData() const { + return CreateRoomResponse_class_data_.base(); +} +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 2, 0, 2> +CreateRoomResponse::_table_ = { + { + PROTOBUF_FIELD_OFFSET(CreateRoomResponse, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 2, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + CreateRoomResponse_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallbackLite, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::np2_structs::CreateRoomResponse>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // .np2_structs.OptParam opt_param = 2; + {::_pbi::TcParser::FastMtS1, + {18, 1, 1, + PROTOBUF_FIELD_OFFSET(CreateRoomResponse, _impl_.opt_param_)}}, + // .np2_structs.RoomDataInternal internal = 1; + {::_pbi::TcParser::FastMtS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(CreateRoomResponse, _impl_.internal_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .np2_structs.RoomDataInternal internal = 1; + {PROTOBUF_FIELD_OFFSET(CreateRoomResponse, _impl_.internal_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .np2_structs.OptParam opt_param = 2; + {PROTOBUF_FIELD_OFFSET(CreateRoomResponse, _impl_.opt_param_), _Internal::kHasBitsOffset + 1, 1, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::np2_structs::RoomDataInternal>()}, + {::_pbi::TcParser::GetTable<::np2_structs::OptParam>()}, + }}, + {{ + }}, +}; +PROTOBUF_NOINLINE void CreateRoomResponse::Clear() { +// @@protoc_insertion_point(message_clear_start:np2_structs.CreateRoomResponse) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(_impl_.internal_ != nullptr); + _impl_.internal_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + ABSL_DCHECK(_impl_.opt_param_ != nullptr); + _impl_.opt_param_->Clear(); + } + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::std::string>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL CreateRoomResponse::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const CreateRoomResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL CreateRoomResponse::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const CreateRoomResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:np2_structs.CreateRoomResponse) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // .np2_structs.RoomDataInternal internal = 1; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, *this_._impl_.internal_, this_._impl_.internal_->GetCachedSize(), target, + stream); + } + + // .np2_structs.OptParam opt_param = 2; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, *this_._impl_.opt_param_, this_._impl_.opt_param_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = stream->WriteRaw( + this_._internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString).data(), + static_cast(this_._internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString).size()), target); + } + // @@protoc_insertion_point(serialize_to_array_end:np2_structs.CreateRoomResponse) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t CreateRoomResponse::ByteSizeLong(const MessageLite& base) { + const CreateRoomResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t CreateRoomResponse::ByteSizeLong() const { + const CreateRoomResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:np2_structs.CreateRoomResponse) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + // .np2_structs.RoomDataInternal internal = 1; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.internal_); + } + // .np2_structs.OptParam opt_param = 2; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.opt_param_); + } + } + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + total_size += this_._internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString).size(); + } + this_._impl_._cached_size_.Set(::_pbi::ToCachedSize(total_size)); + return total_size; +} + +void CreateRoomResponse::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = + static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:np2_structs.CreateRoomResponse) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(from._impl_.internal_ != nullptr); + if (_this->_impl_.internal_ == nullptr) { + _this->_impl_.internal_ = ::google::protobuf::MessageLite::CopyConstruct(arena, *from._impl_.internal_); + } else { + _this->_impl_.internal_->MergeFrom(*from._impl_.internal_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + ABSL_DCHECK(from._impl_.opt_param_ != nullptr); + if (_this->_impl_.opt_param_ == nullptr) { + _this->_impl_.opt_param_ = ::google::protobuf::MessageLite::CopyConstruct(arena, *from._impl_.opt_param_); + } else { + _this->_impl_.opt_param_->MergeFrom(*from._impl_.opt_param_); + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::std::string>( + from._internal_metadata_); +} + +void CreateRoomResponse::CopyFrom(const CreateRoomResponse& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:np2_structs.CreateRoomResponse) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void CreateRoomResponse::InternalSwap(CreateRoomResponse* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(CreateRoomResponse, _impl_.opt_param_) + + sizeof(CreateRoomResponse::_impl_.opt_param_) + - PROTOBUF_FIELD_OFFSET(CreateRoomResponse, _impl_.internal_)>( + reinterpret_cast(&_impl_.internal_), + reinterpret_cast(&other->_impl_.internal_)); +} + +// =================================================================== + class JoinRoomRequest::_Internal { public: using HasBits = @@ -12451,6 +12796,9 @@ JoinRoomResponse::JoinRoomResponse( _impl_.room_data_ = (CheckHasBit(cached_has_bits, 0x00000002U)) ? ::google::protobuf::MessageLite::CopyConstruct(arena, *from._impl_.room_data_) : nullptr; + _impl_.opt_param_ = (CheckHasBit(cached_has_bits, 0x00000004U)) + ? ::google::protobuf::MessageLite::CopyConstruct(arena, *from._impl_.opt_param_) + : nullptr; // @@protoc_insertion_point(copy_constructor:np2_structs.JoinRoomResponse) } @@ -12462,7 +12810,12 @@ PROTOBUF_NDEBUG_INLINE JoinRoomResponse::Impl_::Impl_( inline void JoinRoomResponse::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { new (&_impl_) Impl_(internal_visibility(), arena); - _impl_.room_data_ = {}; + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, room_data_), + 0, + offsetof(Impl_, opt_param_) - + offsetof(Impl_, room_data_) + + sizeof(Impl_::opt_param_)); } JoinRoomResponse::~JoinRoomResponse() { // @@protoc_insertion_point(destructor:np2_structs.JoinRoomResponse) @@ -12476,6 +12829,7 @@ inline void JoinRoomResponse::SharedDtor(MessageLite& self) { this_._internal_metadata_.Delete<::std::string>(); ABSL_DCHECK(this_.GetArena() == nullptr); delete this_._impl_.room_data_; + delete this_._impl_.opt_param_; this_._impl_.~Impl_(); } @@ -12531,17 +12885,17 @@ JoinRoomResponse::GetClassData() const { return JoinRoomResponse_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 -const ::_pbi::TcParseTable<1, 2, 2, 0, 2> +const ::_pbi::TcParseTable<2, 3, 3, 0, 2> JoinRoomResponse::_table_ = { { PROTOBUF_FIELD_OFFSET(JoinRoomResponse, _impl_._has_bits_), 0, // no _extensions_ - 2, 8, // max_field_number, fast_idx_mask + 3, 24, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), - 4294967292, // skipmap + 4294967288, // skipmap offsetof(decltype(_table_), field_entries), - 2, // num_field_entries - 2, // num_aux_entries + 3, // num_field_entries + 3, // num_aux_entries offsetof(decltype(_table_), aux_entries), JoinRoomResponse_class_data_.base(), nullptr, // post_loop_handler @@ -12550,14 +12904,19 @@ JoinRoomResponse::_table_ = { ::_pbi::TcParser::GetTable<::np2_structs::JoinRoomResponse>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE }, {{ - // repeated .np2_structs.Matching2SignalingInfo signaling_data = 2; - {::_pbi::TcParser::FastMtR1, - {18, 0, 1, - PROTOBUF_FIELD_OFFSET(JoinRoomResponse, _impl_.signaling_data_)}}, + {::_pbi::TcParser::MiniParse, {}}, // .np2_structs.RoomDataInternal room_data = 1; {::_pbi::TcParser::FastMtS1, {10, 1, 0, PROTOBUF_FIELD_OFFSET(JoinRoomResponse, _impl_.room_data_)}}, + // repeated .np2_structs.Matching2SignalingInfo signaling_data = 2; + {::_pbi::TcParser::FastMtR1, + {18, 0, 1, + PROTOBUF_FIELD_OFFSET(JoinRoomResponse, _impl_.signaling_data_)}}, + // .np2_structs.OptParam opt_param = 3; + {::_pbi::TcParser::FastMtS1, + {26, 2, 2, + PROTOBUF_FIELD_OFFSET(JoinRoomResponse, _impl_.opt_param_)}}, }}, {{ 65535, 65535 }}, {{ @@ -12565,10 +12924,13 @@ JoinRoomResponse::_table_ = { {PROTOBUF_FIELD_OFFSET(JoinRoomResponse, _impl_.room_data_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, // repeated .np2_structs.Matching2SignalingInfo signaling_data = 2; {PROTOBUF_FIELD_OFFSET(JoinRoomResponse, _impl_.signaling_data_), _Internal::kHasBitsOffset + 0, 1, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // .np2_structs.OptParam opt_param = 3; + {PROTOBUF_FIELD_OFFSET(JoinRoomResponse, _impl_.opt_param_), _Internal::kHasBitsOffset + 2, 2, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, }}, {{ {::_pbi::TcParser::GetTable<::np2_structs::RoomDataInternal>()}, {::_pbi::TcParser::GetTable<::np2_structs::Matching2SignalingInfo>()}, + {::_pbi::TcParser::GetTable<::np2_structs::OptParam>()}, }}, {{ }}, @@ -12581,7 +12943,7 @@ PROTOBUF_NOINLINE void JoinRoomResponse::Clear() { (void) cached_has_bits; cached_has_bits = _impl_._has_bits_[0]; - if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + if (BatchCheckHasBit(cached_has_bits, 0x00000007U)) { if (CheckHasBitForRepeated(cached_has_bits, 0x00000001U)) { _impl_.signaling_data_.Clear(); } @@ -12589,6 +12951,10 @@ PROTOBUF_NOINLINE void JoinRoomResponse::Clear() { ABSL_DCHECK(_impl_.room_data_ != nullptr); _impl_.room_data_->Clear(); } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(_impl_.opt_param_ != nullptr); + _impl_.opt_param_->Clear(); + } } _impl_._has_bits_.Clear(); _internal_metadata_.Clear<::std::string>(); @@ -12633,6 +12999,13 @@ PROTOBUF_NOINLINE void JoinRoomResponse::Clear() { } } + // .np2_structs.OptParam opt_param = 3; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.opt_param_, this_._impl_.opt_param_->GetCachedSize(), target, + stream); + } + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { target = stream->WriteRaw( this_._internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString).data(), @@ -12658,7 +13031,7 @@ PROTOBUF_NOINLINE void JoinRoomResponse::Clear() { ::_pbi::Prefetch5LinesFrom7Lines(&this_); cached_has_bits = this_._impl_._has_bits_[0]; - if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + if (BatchCheckHasBit(cached_has_bits, 0x00000007U)) { // repeated .np2_structs.Matching2SignalingInfo signaling_data = 2; if (CheckHasBitForRepeated(cached_has_bits, 0x00000001U)) { total_size += 1UL * this_._internal_signaling_data_size(); @@ -12671,6 +13044,11 @@ PROTOBUF_NOINLINE void JoinRoomResponse::Clear() { total_size += 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.room_data_); } + // .np2_structs.OptParam opt_param = 3; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.opt_param_); + } } if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { total_size += this_._internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString).size(); @@ -12694,7 +13072,7 @@ void JoinRoomResponse::MergeImpl(::google::protobuf::MessageLite& to_msg, (void)cached_has_bits; cached_has_bits = from._impl_._has_bits_[0]; - if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + if (BatchCheckHasBit(cached_has_bits, 0x00000007U)) { if (CheckHasBitForRepeated(cached_has_bits, 0x00000001U)) { _this->_internal_mutable_signaling_data()->InternalMergeFromWithArena( ::google::protobuf::MessageLite::internal_visibility(), arena, @@ -12708,6 +13086,14 @@ void JoinRoomResponse::MergeImpl(::google::protobuf::MessageLite& to_msg, _this->_impl_.room_data_->MergeFrom(*from._impl_.room_data_); } } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(from._impl_.opt_param_ != nullptr); + if (_this->_impl_.opt_param_ == nullptr) { + _this->_impl_.opt_param_ = ::google::protobuf::MessageLite::CopyConstruct(arena, *from._impl_.opt_param_); + } else { + _this->_impl_.opt_param_->MergeFrom(*from._impl_.opt_param_); + } + } } _this->_impl_._has_bits_[0] |= cached_has_bits; _this->_internal_metadata_.MergeFrom<::std::string>( @@ -12727,7 +13113,12 @@ void JoinRoomResponse::InternalSwap(JoinRoomResponse* PROTOBUF_RESTRICT PROTOBUF _internal_metadata_.InternalSwap(&other->_internal_metadata_); swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); _impl_.signaling_data_.InternalSwap(&other->_impl_.signaling_data_); - swap(_impl_.room_data_, other->_impl_.room_data_); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(JoinRoomResponse, _impl_.opt_param_) + + sizeof(JoinRoomResponse::_impl_.opt_param_) + - PROTOBUF_FIELD_OFFSET(JoinRoomResponse, _impl_.room_data_)>( + reinterpret_cast(&_impl_.room_data_), + reinterpret_cast(&other->_impl_.room_data_)); } // =================================================================== diff --git a/rpcs3/Emu/NP/generated/np2_structs.pb.h b/rpcs3/Emu/NP/generated/np2_structs.pb.h index f662c0a1a0..0e035973fd 100644 --- a/rpcs3/Emu/NP/generated/np2_structs.pb.h +++ b/rpcs3/Emu/NP/generated/np2_structs.pb.h @@ -71,6 +71,10 @@ class CreateRoomGUIRequest; struct CreateRoomGUIRequestDefaultTypeInternal; extern CreateRoomGUIRequestDefaultTypeInternal _CreateRoomGUIRequest_default_instance_; extern const ::google::protobuf::internal::ClassDataLite<33> CreateRoomGUIRequest_class_data_; +class CreateRoomResponse; +struct CreateRoomResponseDefaultTypeInternal; +extern CreateRoomResponseDefaultTypeInternal _CreateRoomResponse_default_instance_; +extern const ::google::protobuf::internal::ClassDataLite<31> CreateRoomResponse_class_data_; class GUIUserInfo; struct GUIUserInfoDefaultTypeInternal; extern GUIUserInfoDefaultTypeInternal _GUIUserInfo_default_instance_; @@ -1031,7 +1035,7 @@ class TusVariable final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_TusVariable_default_instance_); } - static constexpr int kIndexInFileMessages = 56; + static constexpr int kIndexInFileMessages = 57; friend void swap(TusVariable& a, TusVariable& b) { a.Swap(&b); } inline void Swap(TusVariable* PROTOBUF_NONNULL other) { if (other == this) return; @@ -1279,7 +1283,7 @@ class TusUser final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_TusUser_default_instance_); } - static constexpr int kIndexInFileMessages = 55; + static constexpr int kIndexInFileMessages = 56; friend void swap(TusUser& a, TusUser& b) { a.Swap(&b); } inline void Swap(TusUser* PROTOBUF_NONNULL other) { if (other == this) return; @@ -1474,7 +1478,7 @@ class TusGetFriendsVariableRequest final : public ::google::protobuf::MessageLit return *reinterpret_cast( &_TusGetFriendsVariableRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 61; + static constexpr int kIndexInFileMessages = 62; friend void swap(TusGetFriendsVariableRequest& a, TusGetFriendsVariableRequest& b) { a.Swap(&b); } inline void Swap(TusGetFriendsVariableRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -1688,7 +1692,7 @@ class TusGetFriendsDataStatusRequest final : public ::google::protobuf::MessageL return *reinterpret_cast( &_TusGetFriendsDataStatusRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 72; + static constexpr int kIndexInFileMessages = 73; friend void swap(TusGetFriendsDataStatusRequest& a, TusGetFriendsDataStatusRequest& b) { a.Swap(&b); } inline void Swap(TusGetFriendsDataStatusRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -1902,7 +1906,7 @@ class TusDataStatus final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_TusDataStatus_default_instance_); } - static constexpr int kIndexInFileMessages = 66; + static constexpr int kIndexInFileMessages = 67; friend void swap(TusDataStatus& a, TusDataStatus& b) { a.Swap(&b); } inline void Swap(TusDataStatus* PROTOBUF_NONNULL other) { if (other == this) return; @@ -2143,7 +2147,7 @@ class SetRoomSearchFlagGUI final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_SetRoomSearchFlagGUI_default_instance_); } - static constexpr int kIndexInFileMessages = 84; + static constexpr int kIndexInFileMessages = 85; friend void swap(SetRoomSearchFlagGUI& a, SetRoomSearchFlagGUI& b) { a.Swap(&b); } inline void Swap(SetRoomSearchFlagGUI* PROTOBUF_NONNULL other) { if (other == this) return; @@ -2338,7 +2342,7 @@ class SetPresenceRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_SetPresenceRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 74; + static constexpr int kIndexInFileMessages = 75; friend void swap(SetPresenceRequest& a, SetPresenceRequest& b) { a.Swap(&b); } inline void Swap(SetPresenceRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -2572,7 +2576,7 @@ class SendMessageRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_SendMessageRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 43; + static constexpr int kIndexInFileMessages = 44; friend void swap(SendMessageRequest& a, SendMessageRequest& b) { a.Swap(&b); } inline void Swap(SendMessageRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -2779,7 +2783,7 @@ class ScoreRankData final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_ScoreRankData_default_instance_); } - static constexpr int kIndexInFileMessages = 50; + static constexpr int kIndexInFileMessages = 51; friend void swap(ScoreRankData& a, ScoreRankData& b) { a.Swap(&b); } inline void Swap(ScoreRankData* PROTOBUF_NONNULL other) { if (other == this) return; @@ -3039,7 +3043,7 @@ class ScoreNpIdPcId final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_ScoreNpIdPcId_default_instance_); } - static constexpr int kIndexInFileMessages = 47; + static constexpr int kIndexInFileMessages = 48; friend void swap(ScoreNpIdPcId& a, ScoreNpIdPcId& b) { a.Swap(&b); } inline void Swap(ScoreNpIdPcId* PROTOBUF_NONNULL other) { if (other == this) return; @@ -3234,7 +3238,7 @@ class ScoreInfo final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_ScoreInfo_default_instance_); } - static constexpr int kIndexInFileMessages = 51; + static constexpr int kIndexInFileMessages = 52; friend void swap(ScoreInfo& a, ScoreInfo& b) { a.Swap(&b); } inline void Swap(ScoreInfo* PROTOBUF_NONNULL other) { if (other == this) return; @@ -3417,7 +3421,7 @@ class RecordScoreRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_RecordScoreRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 45; + static constexpr int kIndexInFileMessages = 46; friend void swap(RecordScoreRequest& a, RecordScoreRequest& b) { a.Swap(&b); } inline void Swap(RecordScoreRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -3653,7 +3657,7 @@ class RecordScoreGameDataRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_RecordScoreGameDataRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 53; + static constexpr int kIndexInFileMessages = 54; friend void swap(RecordScoreGameDataRequest& a, RecordScoreGameDataRequest& b) { a.Swap(&b); } inline void Swap(RecordScoreGameDataRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -4050,7 +4054,7 @@ class MatchingSearchCondition final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_MatchingSearchCondition_default_instance_); } - static constexpr int kIndexInFileMessages = 75; + static constexpr int kIndexInFileMessages = 76; friend void swap(MatchingSearchCondition& a, MatchingSearchCondition& b) { a.Swap(&b); } inline void Swap(MatchingSearchCondition* PROTOBUF_NONNULL other) { if (other == this) return; @@ -4264,7 +4268,7 @@ class MatchingGuiRoomId final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_MatchingGuiRoomId_default_instance_); } - static constexpr int kIndexInFileMessages = 83; + static constexpr int kIndexInFileMessages = 84; friend void swap(MatchingGuiRoomId& a, MatchingGuiRoomId& b) { a.Swap(&b); } inline void Swap(MatchingGuiRoomId* PROTOBUF_NONNULL other) { if (other == this) return; @@ -4447,7 +4451,7 @@ class MatchingAttr final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_MatchingAttr_default_instance_); } - static constexpr int kIndexInFileMessages = 76; + static constexpr int kIndexInFileMessages = 77; friend void swap(MatchingAttr& a, MatchingAttr& b) { a.Swap(&b); } inline void Swap(MatchingAttr* PROTOBUF_NONNULL other) { if (other == this) return; @@ -4873,7 +4877,7 @@ class GetScoreRangeRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_GetScoreRangeRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 46; + static constexpr int kIndexInFileMessages = 47; friend void swap(GetScoreRangeRequest& a, GetScoreRangeRequest& b) { a.Swap(&b); } inline void Swap(GetScoreRangeRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -5099,7 +5103,7 @@ class GetScoreGameDataRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_GetScoreGameDataRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 54; + static constexpr int kIndexInFileMessages = 55; friend void swap(GetScoreGameDataRequest& a, GetScoreGameDataRequest& b) { a.Swap(&b); } inline void Swap(GetScoreGameDataRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -5306,7 +5310,7 @@ class GetScoreFriendsRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_GetScoreFriendsRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 49; + static constexpr int kIndexInFileMessages = 50; friend void swap(GetScoreFriendsRequest& a, GetScoreFriendsRequest& b) { a.Swap(&b); } inline void Swap(GetScoreFriendsRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -5532,7 +5536,7 @@ class BoardInfo final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_BoardInfo_default_instance_); } - static constexpr int kIndexInFileMessages = 44; + static constexpr int kIndexInFileMessages = 45; friend void swap(BoardInfo& a, BoardInfo& b) { a.Swap(&b); } inline void Swap(BoardInfo* PROTOBUF_NONNULL other) { if (other == this) return; @@ -5758,7 +5762,7 @@ class TusVarResponse final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_TusVarResponse_default_instance_); } - static constexpr int kIndexInFileMessages = 57; + static constexpr int kIndexInFileMessages = 58; friend void swap(TusVarResponse& a, TusVarResponse& b) { a.Swap(&b); } inline void Swap(TusVarResponse* PROTOBUF_NONNULL other) { if (other == this) return; @@ -5943,7 +5947,7 @@ class TusTryAndSetVariableRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_TusTryAndSetVariableRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 63; + static constexpr int kIndexInFileMessages = 64; friend void swap(TusTryAndSetVariableRequest& a, TusTryAndSetVariableRequest& b) { a.Swap(&b); } inline void Swap(TusTryAndSetVariableRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -6221,7 +6225,7 @@ class TusSetMultiSlotVariableRequest final : public ::google::protobuf::MessageL return *reinterpret_cast( &_TusSetMultiSlotVariableRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 58; + static constexpr int kIndexInFileMessages = 59; friend void swap(TusSetMultiSlotVariableRequest& a, TusSetMultiSlotVariableRequest& b) { a.Swap(&b); } inline void Swap(TusSetMultiSlotVariableRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -6446,7 +6450,7 @@ class TusSetDataRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_TusSetDataRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 65; + static constexpr int kIndexInFileMessages = 66; friend void swap(TusSetDataRequest& a, TusSetDataRequest& b) { a.Swap(&b); } inline void Swap(TusSetDataRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -6713,7 +6717,7 @@ class TusGetMultiUserVariableRequest final : public ::google::protobuf::MessageL return *reinterpret_cast( &_TusGetMultiUserVariableRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 60; + static constexpr int kIndexInFileMessages = 61; friend void swap(TusGetMultiUserVariableRequest& a, TusGetMultiUserVariableRequest& b) { a.Swap(&b); } inline void Swap(TusGetMultiUserVariableRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -6910,7 +6914,7 @@ class TusGetMultiUserDataStatusRequest final : public ::google::protobuf::Messag return *reinterpret_cast( &_TusGetMultiUserDataStatusRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 71; + static constexpr int kIndexInFileMessages = 72; friend void swap(TusGetMultiUserDataStatusRequest& a, TusGetMultiUserDataStatusRequest& b) { a.Swap(&b); } inline void Swap(TusGetMultiUserDataStatusRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -7107,7 +7111,7 @@ class TusGetMultiSlotVariableRequest final : public ::google::protobuf::MessageL return *reinterpret_cast( &_TusGetMultiSlotVariableRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 59; + static constexpr int kIndexInFileMessages = 60; friend void swap(TusGetMultiSlotVariableRequest& a, TusGetMultiSlotVariableRequest& b) { a.Swap(&b); } inline void Swap(TusGetMultiSlotVariableRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -7311,7 +7315,7 @@ class TusGetMultiSlotDataStatusRequest final : public ::google::protobuf::Messag return *reinterpret_cast( &_TusGetMultiSlotDataStatusRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 70; + static constexpr int kIndexInFileMessages = 71; friend void swap(TusGetMultiSlotDataStatusRequest& a, TusGetMultiSlotDataStatusRequest& b) { a.Swap(&b); } inline void Swap(TusGetMultiSlotDataStatusRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -7515,7 +7519,7 @@ class TusGetDataRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_TusGetDataRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 69; + static constexpr int kIndexInFileMessages = 70; friend void swap(TusGetDataRequest& a, TusGetDataRequest& b) { a.Swap(&b); } inline void Swap(TusGetDataRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -7710,7 +7714,7 @@ class TusDeleteMultiSlotVariableRequest final : public ::google::protobuf::Messa return *reinterpret_cast( &_TusDeleteMultiSlotVariableRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 64; + static constexpr int kIndexInFileMessages = 65; friend void swap(TusDeleteMultiSlotVariableRequest& a, TusDeleteMultiSlotVariableRequest& b) { a.Swap(&b); } inline void Swap(TusDeleteMultiSlotVariableRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -7914,7 +7918,7 @@ class TusDeleteMultiSlotDataRequest final : public ::google::protobuf::MessageLi return *reinterpret_cast( &_TusDeleteMultiSlotDataRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 73; + static constexpr int kIndexInFileMessages = 74; friend void swap(TusDeleteMultiSlotDataRequest& a, TusDeleteMultiSlotDataRequest& b) { a.Swap(&b); } inline void Swap(TusDeleteMultiSlotDataRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -8118,7 +8122,7 @@ class TusDataStatusResponse final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_TusDataStatusResponse_default_instance_); } - static constexpr int kIndexInFileMessages = 68; + static constexpr int kIndexInFileMessages = 69; friend void swap(TusDataStatusResponse& a, TusDataStatusResponse& b) { a.Swap(&b); } inline void Swap(TusDataStatusResponse* PROTOBUF_NONNULL other) { if (other == this) return; @@ -8303,7 +8307,7 @@ class TusData final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_TusData_default_instance_); } - static constexpr int kIndexInFileMessages = 67; + static constexpr int kIndexInFileMessages = 68; friend void swap(TusData& a, TusData& b) { a.Swap(&b); } inline void Swap(TusData* PROTOBUF_NONNULL other) { if (other == this) return; @@ -8503,7 +8507,7 @@ class TusAddAndGetVariableRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_TusAddAndGetVariableRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 62; + static constexpr int kIndexInFileMessages = 63; friend void swap(TusAddAndGetVariableRequest& a, TusAddAndGetVariableRequest& b) { a.Swap(&b); } inline void Swap(TusAddAndGetVariableRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -8948,7 +8952,7 @@ class SendRoomMessageRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_SendRoomMessageRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 40; + static constexpr int kIndexInFileMessages = 41; friend void swap(SendRoomMessageRequest& a, SendRoomMessageRequest& b) { a.Swap(&b); } inline void Swap(SendRoomMessageRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -9196,7 +9200,7 @@ class SearchJoinRoomGUIRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_SearchJoinRoomGUIRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 86; + static constexpr int kIndexInFileMessages = 87; friend void swap(SearchJoinRoomGUIRequest& a, SearchJoinRoomGUIRequest& b) { a.Swap(&b); } inline void Swap(SearchJoinRoomGUIRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -9400,7 +9404,7 @@ class RoomUpdateInfo final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_RoomUpdateInfo_default_instance_); } - static constexpr int kIndexInFileMessages = 36; + static constexpr int kIndexInFileMessages = 37; friend void swap(RoomUpdateInfo& a, RoomUpdateInfo& b) { a.Swap(&b); } inline void Swap(RoomUpdateInfo* PROTOBUF_NONNULL other) { if (other == this) return; @@ -9612,7 +9616,7 @@ class RoomMessageInfo final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_RoomMessageInfo_default_instance_); } - static constexpr int kIndexInFileMessages = 41; + static constexpr int kIndexInFileMessages = 42; friend void swap(RoomMessageInfo& a, RoomMessageInfo& b) { a.Swap(&b); } inline void Swap(RoomMessageInfo* PROTOBUF_NONNULL other) { if (other == this) return; @@ -10291,7 +10295,7 @@ class QuickMatchGUIRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_QuickMatchGUIRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 85; + static constexpr int kIndexInFileMessages = 86; friend void swap(QuickMatchGUIRequest& a, QuickMatchGUIRequest& b) { a.Swap(&b); } inline void Swap(QuickMatchGUIRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -10705,7 +10709,7 @@ class MessageDetails final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_MessageDetails_default_instance_); } - static constexpr int kIndexInFileMessages = 42; + static constexpr int kIndexInFileMessages = 43; friend void swap(MessageDetails& a, MessageDetails& b) { a.Swap(&b); } inline void Swap(MessageDetails* PROTOBUF_NONNULL other) { if (other == this) return; @@ -10997,7 +11001,7 @@ class MatchingRoom final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_MatchingRoom_default_instance_); } - static constexpr int kIndexInFileMessages = 81; + static constexpr int kIndexInFileMessages = 82; friend void swap(MatchingRoom& a, MatchingRoom& b) { a.Swap(&b); } inline void Swap(MatchingRoom* PROTOBUF_NONNULL other) { if (other == this) return; @@ -11199,7 +11203,7 @@ class LeaveRoomRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_LeaveRoomRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 25; + static constexpr int kIndexInFileMessages = 26; friend void swap(LeaveRoomRequest& a, LeaveRoomRequest& b) { a.Swap(&b); } inline void Swap(LeaveRoomRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -11589,7 +11593,7 @@ class GetScoreResponse final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_GetScoreResponse_default_instance_); } - static constexpr int kIndexInFileMessages = 52; + static constexpr int kIndexInFileMessages = 53; friend void swap(GetScoreResponse& a, GetScoreResponse& b) { a.Swap(&b); } inline void Swap(GetScoreResponse* PROTOBUF_NONNULL other) { if (other == this) return; @@ -11841,7 +11845,7 @@ class GetScoreNpIdRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_GetScoreNpIdRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 48; + static constexpr int kIndexInFileMessages = 49; friend void swap(GetScoreNpIdRequest& a, GetScoreNpIdRequest& b) { a.Swap(&b); } inline void Swap(GetScoreNpIdRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -12062,7 +12066,7 @@ class GetRoomMemberDataInternalRequest final : public ::google::protobuf::Messag return *reinterpret_cast( &_GetRoomMemberDataInternalRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 30; + static constexpr int kIndexInFileMessages = 31; friend void swap(GetRoomMemberDataInternalRequest& a, GetRoomMemberDataInternalRequest& b) { a.Swap(&b); } inline void Swap(GetRoomMemberDataInternalRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -12276,7 +12280,7 @@ class GetRoomListGUIRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_GetRoomListGUIRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 80; + static constexpr int kIndexInFileMessages = 81; friend void swap(GetRoomListGUIRequest& a, GetRoomListGUIRequest& b) { a.Swap(&b); } inline void Swap(GetRoomListGUIRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -12504,7 +12508,7 @@ class GetRoomDataInternalRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_GetRoomDataInternalRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 33; + static constexpr int kIndexInFileMessages = 34; friend void swap(GetRoomDataInternalRequest& a, GetRoomDataInternalRequest& b) { a.Swap(&b); } inline void Swap(GetRoomDataInternalRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -12701,7 +12705,7 @@ class GetRoomDataExternalListRequest final : public ::google::protobuf::MessageL return *reinterpret_cast( &_GetRoomDataExternalListRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 26; + static constexpr int kIndexInFileMessages = 27; friend void swap(GetRoomDataExternalListRequest& a, GetRoomDataExternalListRequest& b) { a.Swap(&b); } inline void Swap(GetRoomDataExternalListRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -12907,7 +12911,7 @@ class GetPingInfoResponse final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_GetPingInfoResponse_default_instance_); } - static constexpr int kIndexInFileMessages = 39; + static constexpr int kIndexInFileMessages = 40; friend void swap(GetPingInfoResponse& a, GetPingInfoResponse& b) { a.Swap(&b); } inline void Swap(GetPingInfoResponse* PROTOBUF_NONNULL other) { if (other == this) return; @@ -13126,7 +13130,7 @@ class GUIUserInfo final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_GUIUserInfo_default_instance_); } - static constexpr int kIndexInFileMessages = 78; + static constexpr int kIndexInFileMessages = 79; friend void swap(GUIUserInfo& a, GUIUserInfo& b) { a.Swap(&b); } inline void Swap(GUIUserInfo* PROTOBUF_NONNULL other) { if (other == this) return; @@ -13321,7 +13325,7 @@ class CreateRoomGUIRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_CreateRoomGUIRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 77; + static constexpr int kIndexInFileMessages = 78; friend void swap(CreateRoomGUIRequest& a, CreateRoomGUIRequest& b) { a.Swap(&b); } inline void Swap(CreateRoomGUIRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -13754,7 +13758,7 @@ class SetUserInfo final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_SetUserInfo_default_instance_); } - static constexpr int kIndexInFileMessages = 32; + static constexpr int kIndexInFileMessages = 33; friend void swap(SetUserInfo& a, SetUserInfo& b) { a.Swap(&b); } inline void Swap(SetUserInfo* PROTOBUF_NONNULL other) { if (other == this) return; @@ -13956,7 +13960,7 @@ class SetRoomMemberDataInternalRequest final : public ::google::protobuf::Messag return *reinterpret_cast( &_SetRoomMemberDataInternalRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 31; + static constexpr int kIndexInFileMessages = 32; friend void swap(SetRoomMemberDataInternalRequest& a, SetRoomMemberDataInternalRequest& b) { a.Swap(&b); } inline void Swap(SetRoomMemberDataInternalRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -14187,7 +14191,7 @@ class SetRoomDataInternalRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_SetRoomDataInternalRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 29; + static constexpr int kIndexInFileMessages = 30; friend void swap(SetRoomDataInternalRequest& a, SetRoomDataInternalRequest& b) { a.Swap(&b); } inline void Swap(SetRoomDataInternalRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -14467,7 +14471,7 @@ class SetRoomDataExternalRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_SetRoomDataExternalRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 28; + static constexpr int kIndexInFileMessages = 29; friend void swap(SetRoomDataExternalRequest& a, SetRoomDataExternalRequest& b) { a.Swap(&b); } inline void Swap(SetRoomDataExternalRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -15535,7 +15539,7 @@ class MatchingRoomStatus final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_MatchingRoomStatus_default_instance_); } - static constexpr int kIndexInFileMessages = 79; + static constexpr int kIndexInFileMessages = 80; friend void swap(MatchingRoomStatus& a, MatchingRoomStatus& b) { a.Swap(&b); } inline void Swap(MatchingRoomStatus* PROTOBUF_NONNULL other) { if (other == this) return; @@ -15771,7 +15775,7 @@ class MatchingRoomList final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_MatchingRoomList_default_instance_); } - static constexpr int kIndexInFileMessages = 82; + static constexpr int kIndexInFileMessages = 83; friend void swap(MatchingRoomList& a, MatchingRoomList& b) { a.Swap(&b); } inline void Swap(MatchingRoomList* PROTOBUF_NONNULL other) { if (other == this) return; @@ -16180,7 +16184,7 @@ class JoinRoomRequest final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_JoinRoomRequest_default_instance_); } - static constexpr int kIndexInFileMessages = 23; + static constexpr int kIndexInFileMessages = 24; friend void swap(JoinRoomRequest& a, JoinRoomRequest& b) { a.Swap(&b); } inline void Swap(JoinRoomRequest* PROTOBUF_NONNULL other) { if (other == this) return; @@ -18318,7 +18322,7 @@ class MatchingSearchJoinRoomInfo final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_MatchingSearchJoinRoomInfo_default_instance_); } - static constexpr int kIndexInFileMessages = 87; + static constexpr int kIndexInFileMessages = 88; friend void swap(MatchingSearchJoinRoomInfo& a, MatchingSearchJoinRoomInfo& b) { a.Swap(&b); } inline void Swap(MatchingSearchJoinRoomInfo* PROTOBUF_NONNULL other) { if (other == this) return; @@ -18520,7 +18524,7 @@ class GetRoomDataExternalListResponse final : public ::google::protobuf::Message return *reinterpret_cast( &_GetRoomDataExternalListResponse_default_instance_); } - static constexpr int kIndexInFileMessages = 27; + static constexpr int kIndexInFileMessages = 28; friend void swap(GetRoomDataExternalListResponse& a, GetRoomDataExternalListResponse& b) { a.Swap(&b); } inline void Swap(GetRoomDataExternalListResponse* PROTOBUF_NONNULL other) { if (other == this) return; @@ -18705,7 +18709,7 @@ class RoomMemberUpdateInfo final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_RoomMemberUpdateInfo_default_instance_); } - static constexpr int kIndexInFileMessages = 34; + static constexpr int kIndexInFileMessages = 35; friend void swap(RoomMemberUpdateInfo& a, RoomMemberUpdateInfo& b) { a.Swap(&b); } inline void Swap(RoomMemberUpdateInfo* PROTOBUF_NONNULL other) { if (other == this) return; @@ -18922,7 +18926,7 @@ class RoomMemberDataInternalUpdateInfo final : public ::google::protobuf::Messag return *reinterpret_cast( &_RoomMemberDataInternalUpdateInfo_default_instance_); } - static constexpr int kIndexInFileMessages = 38; + static constexpr int kIndexInFileMessages = 39; friend void swap(RoomMemberDataInternalUpdateInfo& a, RoomMemberDataInternalUpdateInfo& b) { a.Swap(&b); } inline void Swap(RoomMemberDataInternalUpdateInfo* PROTOBUF_NONNULL other) { if (other == this) return; @@ -19482,7 +19486,7 @@ class RoomDataInternalUpdateInfo final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_RoomDataInternalUpdateInfo_default_instance_); } - static constexpr int kIndexInFileMessages = 37; + static constexpr int kIndexInFileMessages = 38; friend void swap(RoomDataInternalUpdateInfo& a, RoomDataInternalUpdateInfo& b) { a.Swap(&b); } inline void Swap(RoomDataInternalUpdateInfo* PROTOBUF_NONNULL other) { if (other == this) return; @@ -19725,7 +19729,7 @@ class NotificationUserJoinedRoom final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_NotificationUserJoinedRoom_default_instance_); } - static constexpr int kIndexInFileMessages = 35; + static constexpr int kIndexInFileMessages = 36; friend void swap(NotificationUserJoinedRoom& a, NotificationUserJoinedRoom& b) { a.Swap(&b); } inline void Swap(NotificationUserJoinedRoom* PROTOBUF_NONNULL other) { if (other == this) return; @@ -19937,7 +19941,7 @@ class JoinRoomResponse final : public ::google::protobuf::MessageLite return *reinterpret_cast( &_JoinRoomResponse_default_instance_); } - static constexpr int kIndexInFileMessages = 24; + static constexpr int kIndexInFileMessages = 25; friend void swap(JoinRoomResponse& a, JoinRoomResponse& b) { a.Swap(&b); } inline void Swap(JoinRoomResponse* PROTOBUF_NONNULL other) { if (other == this) return; @@ -20023,6 +20027,7 @@ class JoinRoomResponse final : public ::google::protobuf::MessageLite enum : int { kSignalingDataFieldNumber = 2, kRoomDataFieldNumber = 1, + kOptParamFieldNumber = 3, }; // repeated .np2_structs.Matching2SignalingInfo signaling_data = 2; int signaling_data_size() const; @@ -20055,13 +20060,28 @@ class JoinRoomResponse final : public ::google::protobuf::MessageLite const ::np2_structs::RoomDataInternal& _internal_room_data() const; ::np2_structs::RoomDataInternal* PROTOBUF_NONNULL _internal_mutable_room_data(); + public: + // .np2_structs.OptParam opt_param = 3; + bool has_opt_param() const; + void clear_opt_param() ; + const ::np2_structs::OptParam& opt_param() const; + [[nodiscard]] ::np2_structs::OptParam* PROTOBUF_NULLABLE release_opt_param(); + ::np2_structs::OptParam* PROTOBUF_NONNULL mutable_opt_param(); + void set_allocated_opt_param(::np2_structs::OptParam* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_opt_param(::np2_structs::OptParam* PROTOBUF_NULLABLE value); + ::np2_structs::OptParam* PROTOBUF_NULLABLE unsafe_arena_release_opt_param(); + + private: + const ::np2_structs::OptParam& _internal_opt_param() const; + ::np2_structs::OptParam* PROTOBUF_NONNULL _internal_mutable_opt_param(); + public: // @@protoc_insertion_point(class_scope:np2_structs.JoinRoomResponse) private: class _Internal; friend class ::google::protobuf::internal::TcParser; - static const ::google::protobuf::internal::TcParseTable<1, 2, - 2, 0, + static const ::google::protobuf::internal::TcParseTable<2, 3, + 3, 0, 2> _table_; @@ -20084,6 +20104,7 @@ class JoinRoomResponse final : public ::google::protobuf::MessageLite ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::np2_structs::Matching2SignalingInfo > signaling_data_; ::np2_structs::RoomDataInternal* PROTOBUF_NULLABLE room_data_; + ::np2_structs::OptParam* PROTOBUF_NULLABLE opt_param_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; @@ -20091,6 +20112,206 @@ class JoinRoomResponse final : public ::google::protobuf::MessageLite }; extern const ::google::protobuf::internal::ClassDataLite<29> JoinRoomResponse_class_data_; +// ------------------------------------------------------------------- + +class CreateRoomResponse final : public ::google::protobuf::MessageLite +/* @@protoc_insertion_point(class_definition:np2_structs.CreateRoomResponse) */ { + public: + inline CreateRoomResponse() : CreateRoomResponse(nullptr) {} + ~CreateRoomResponse() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(CreateRoomResponse* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(CreateRoomResponse)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR CreateRoomResponse(::google::protobuf::internal::ConstantInitialized); + + inline CreateRoomResponse(const CreateRoomResponse& from) : CreateRoomResponse(nullptr, from) {} + inline CreateRoomResponse(CreateRoomResponse&& from) noexcept + : CreateRoomResponse(nullptr, ::std::move(from)) {} + inline CreateRoomResponse& operator=(const CreateRoomResponse& from) { + CopyFrom(from); + return *this; + } + inline CreateRoomResponse& operator=(CreateRoomResponse&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::std::string& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString); + } + inline ::std::string* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::std::string>(); + } + + static const CreateRoomResponse& default_instance() { + return *reinterpret_cast( + &_CreateRoomResponse_default_instance_); + } + static constexpr int kIndexInFileMessages = 23; + friend void swap(CreateRoomResponse& a, CreateRoomResponse& b) { a.Swap(&b); } + inline void Swap(CreateRoomResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(CreateRoomResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + CreateRoomResponse* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::MessageLite::DefaultConstruct(arena); + } + void CopyFrom(const CreateRoomResponse& from); + void MergeFrom(const CreateRoomResponse& from) { CreateRoomResponse::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(CreateRoomResponse* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "np2_structs.CreateRoomResponse"; } + + explicit CreateRoomResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + CreateRoomResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const CreateRoomResponse& from); + CreateRoomResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, CreateRoomResponse&& from) noexcept + : CreateRoomResponse(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kInternalFieldNumber = 1, + kOptParamFieldNumber = 2, + }; + // .np2_structs.RoomDataInternal internal = 1; + bool has_internal() const; + void clear_internal() ; + const ::np2_structs::RoomDataInternal& internal() const; + [[nodiscard]] ::np2_structs::RoomDataInternal* PROTOBUF_NULLABLE release_internal(); + ::np2_structs::RoomDataInternal* PROTOBUF_NONNULL mutable_internal(); + void set_allocated_internal(::np2_structs::RoomDataInternal* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_internal(::np2_structs::RoomDataInternal* PROTOBUF_NULLABLE value); + ::np2_structs::RoomDataInternal* PROTOBUF_NULLABLE unsafe_arena_release_internal(); + + private: + const ::np2_structs::RoomDataInternal& _internal_internal() const; + ::np2_structs::RoomDataInternal* PROTOBUF_NONNULL _internal_mutable_internal(); + + public: + // .np2_structs.OptParam opt_param = 2; + bool has_opt_param() const; + void clear_opt_param() ; + const ::np2_structs::OptParam& opt_param() const; + [[nodiscard]] ::np2_structs::OptParam* PROTOBUF_NULLABLE release_opt_param(); + ::np2_structs::OptParam* PROTOBUF_NONNULL mutable_opt_param(); + void set_allocated_opt_param(::np2_structs::OptParam* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_opt_param(::np2_structs::OptParam* PROTOBUF_NULLABLE value); + ::np2_structs::OptParam* PROTOBUF_NULLABLE unsafe_arena_release_opt_param(); + + private: + const ::np2_structs::OptParam& _internal_opt_param() const; + ::np2_structs::OptParam* PROTOBUF_NONNULL _internal_mutable_opt_param(); + + public: + // @@protoc_insertion_point(class_scope:np2_structs.CreateRoomResponse) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 2, + 2, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const CreateRoomResponse& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::np2_structs::RoomDataInternal* PROTOBUF_NULLABLE internal_; + ::np2_structs::OptParam* PROTOBUF_NULLABLE opt_param_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_np2_5fstructs_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataLite<31> CreateRoomResponse_class_data_; // =================================================================== @@ -26431,6 +26652,208 @@ inline void CreateJoinRoomRequest::set_allocated_sigoptparam(::np2_structs::OptP // ------------------------------------------------------------------- +// CreateRoomResponse + +// .np2_structs.RoomDataInternal internal = 1; +inline bool CreateRoomResponse::has_internal() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000001U); + PROTOBUF_ASSUME(!value || _impl_.internal_ != nullptr); + return value; +} +inline void CreateRoomResponse::clear_internal() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.internal_ != nullptr) _impl_.internal_->Clear(); + ClearHasBit(_impl_._has_bits_[0], + 0x00000001U); +} +inline const ::np2_structs::RoomDataInternal& CreateRoomResponse::_internal_internal() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::np2_structs::RoomDataInternal* p = _impl_.internal_; + return p != nullptr ? *p : reinterpret_cast(::np2_structs::_RoomDataInternal_default_instance_); +} +inline const ::np2_structs::RoomDataInternal& CreateRoomResponse::internal() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:np2_structs.CreateRoomResponse.internal) + return _internal_internal(); +} +inline void CreateRoomResponse::unsafe_arena_set_allocated_internal( + ::np2_structs::RoomDataInternal* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.internal_); + } + _impl_.internal_ = reinterpret_cast<::np2_structs::RoomDataInternal*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:np2_structs.CreateRoomResponse.internal) +} +inline ::np2_structs::RoomDataInternal* PROTOBUF_NULLABLE CreateRoomResponse::release_internal() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::np2_structs::RoomDataInternal* released = _impl_.internal_; + _impl_.internal_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::np2_structs::RoomDataInternal* PROTOBUF_NULLABLE CreateRoomResponse::unsafe_arena_release_internal() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:np2_structs.CreateRoomResponse.internal) + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::np2_structs::RoomDataInternal* temp = _impl_.internal_; + _impl_.internal_ = nullptr; + return temp; +} +inline ::np2_structs::RoomDataInternal* PROTOBUF_NONNULL CreateRoomResponse::_internal_mutable_internal() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.internal_ == nullptr) { + auto* p = ::google::protobuf::MessageLite::DefaultConstruct<::np2_structs::RoomDataInternal>(GetArena()); + _impl_.internal_ = reinterpret_cast<::np2_structs::RoomDataInternal*>(p); + } + return _impl_.internal_; +} +inline ::np2_structs::RoomDataInternal* PROTOBUF_NONNULL CreateRoomResponse::mutable_internal() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::np2_structs::RoomDataInternal* _msg = _internal_mutable_internal(); + // @@protoc_insertion_point(field_mutable:np2_structs.CreateRoomResponse.internal) + return _msg; +} +inline void CreateRoomResponse::set_allocated_internal(::np2_structs::RoomDataInternal* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.internal_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + + _impl_.internal_ = reinterpret_cast<::np2_structs::RoomDataInternal*>(value); + // @@protoc_insertion_point(field_set_allocated:np2_structs.CreateRoomResponse.internal) +} + +// .np2_structs.OptParam opt_param = 2; +inline bool CreateRoomResponse::has_opt_param() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000002U); + PROTOBUF_ASSUME(!value || _impl_.opt_param_ != nullptr); + return value; +} +inline void CreateRoomResponse::clear_opt_param() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.opt_param_ != nullptr) _impl_.opt_param_->Clear(); + ClearHasBit(_impl_._has_bits_[0], + 0x00000002U); +} +inline const ::np2_structs::OptParam& CreateRoomResponse::_internal_opt_param() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::np2_structs::OptParam* p = _impl_.opt_param_; + return p != nullptr ? *p : reinterpret_cast(::np2_structs::_OptParam_default_instance_); +} +inline const ::np2_structs::OptParam& CreateRoomResponse::opt_param() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:np2_structs.CreateRoomResponse.opt_param) + return _internal_opt_param(); +} +inline void CreateRoomResponse::unsafe_arena_set_allocated_opt_param( + ::np2_structs::OptParam* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.opt_param_); + } + _impl_.opt_param_ = reinterpret_cast<::np2_structs::OptParam*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:np2_structs.CreateRoomResponse.opt_param) +} +inline ::np2_structs::OptParam* PROTOBUF_NULLABLE CreateRoomResponse::release_opt_param() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + ::np2_structs::OptParam* released = _impl_.opt_param_; + _impl_.opt_param_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::np2_structs::OptParam* PROTOBUF_NULLABLE CreateRoomResponse::unsafe_arena_release_opt_param() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:np2_structs.CreateRoomResponse.opt_param) + + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + ::np2_structs::OptParam* temp = _impl_.opt_param_; + _impl_.opt_param_ = nullptr; + return temp; +} +inline ::np2_structs::OptParam* PROTOBUF_NONNULL CreateRoomResponse::_internal_mutable_opt_param() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.opt_param_ == nullptr) { + auto* p = ::google::protobuf::MessageLite::DefaultConstruct<::np2_structs::OptParam>(GetArena()); + _impl_.opt_param_ = reinterpret_cast<::np2_structs::OptParam*>(p); + } + return _impl_.opt_param_; +} +inline ::np2_structs::OptParam* PROTOBUF_NONNULL CreateRoomResponse::mutable_opt_param() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::np2_structs::OptParam* _msg = _internal_mutable_opt_param(); + // @@protoc_insertion_point(field_mutable:np2_structs.CreateRoomResponse.opt_param) + return _msg; +} +inline void CreateRoomResponse::set_allocated_opt_param(::np2_structs::OptParam* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.opt_param_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + + _impl_.opt_param_ = reinterpret_cast<::np2_structs::OptParam*>(value); + // @@protoc_insertion_point(field_set_allocated:np2_structs.CreateRoomResponse.opt_param) +} + +// ------------------------------------------------------------------- + // JoinRoomRequest // uint64 roomId = 1; @@ -27001,6 +27424,105 @@ JoinRoomResponse::_internal_mutable_signaling_data() { return &_impl_.signaling_data_; } +// .np2_structs.OptParam opt_param = 3; +inline bool JoinRoomResponse::has_opt_param() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000004U); + PROTOBUF_ASSUME(!value || _impl_.opt_param_ != nullptr); + return value; +} +inline void JoinRoomResponse::clear_opt_param() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.opt_param_ != nullptr) _impl_.opt_param_->Clear(); + ClearHasBit(_impl_._has_bits_[0], + 0x00000004U); +} +inline const ::np2_structs::OptParam& JoinRoomResponse::_internal_opt_param() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::np2_structs::OptParam* p = _impl_.opt_param_; + return p != nullptr ? *p : reinterpret_cast(::np2_structs::_OptParam_default_instance_); +} +inline const ::np2_structs::OptParam& JoinRoomResponse::opt_param() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:np2_structs.JoinRoomResponse.opt_param) + return _internal_opt_param(); +} +inline void JoinRoomResponse::unsafe_arena_set_allocated_opt_param( + ::np2_structs::OptParam* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.opt_param_); + } + _impl_.opt_param_ = reinterpret_cast<::np2_structs::OptParam*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:np2_structs.JoinRoomResponse.opt_param) +} +inline ::np2_structs::OptParam* PROTOBUF_NULLABLE JoinRoomResponse::release_opt_param() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::np2_structs::OptParam* released = _impl_.opt_param_; + _impl_.opt_param_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::np2_structs::OptParam* PROTOBUF_NULLABLE JoinRoomResponse::unsafe_arena_release_opt_param() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:np2_structs.JoinRoomResponse.opt_param) + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::np2_structs::OptParam* temp = _impl_.opt_param_; + _impl_.opt_param_ = nullptr; + return temp; +} +inline ::np2_structs::OptParam* PROTOBUF_NONNULL JoinRoomResponse::_internal_mutable_opt_param() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.opt_param_ == nullptr) { + auto* p = ::google::protobuf::MessageLite::DefaultConstruct<::np2_structs::OptParam>(GetArena()); + _impl_.opt_param_ = reinterpret_cast<::np2_structs::OptParam*>(p); + } + return _impl_.opt_param_; +} +inline ::np2_structs::OptParam* PROTOBUF_NONNULL JoinRoomResponse::mutable_opt_param() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::np2_structs::OptParam* _msg = _internal_mutable_opt_param(); + // @@protoc_insertion_point(field_mutable:np2_structs.JoinRoomResponse.opt_param) + return _msg; +} +inline void JoinRoomResponse::set_allocated_opt_param(::np2_structs::OptParam* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.opt_param_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + + _impl_.opt_param_ = reinterpret_cast<::np2_structs::OptParam*>(value); + // @@protoc_insertion_point(field_set_allocated:np2_structs.JoinRoomResponse.opt_param) +} + // ------------------------------------------------------------------- // LeaveRoomRequest diff --git a/rpcs3/Emu/NP/generated/np2_structs.proto b/rpcs3/Emu/NP/generated/np2_structs.proto index 34413476e6..46628781fb 100644 --- a/rpcs3/Emu/NP/generated/np2_structs.proto +++ b/rpcs3/Emu/NP/generated/np2_structs.proto @@ -1,4 +1,3 @@ - // Protocol Buffers definition for np2_structs syntax = "proto3"; @@ -16,71 +15,61 @@ message uint16 { uint32 value = 1; } -// SignalingAddr + message SignalingAddr { bytes ip = 1; uint16 port = 2; } -// MatchingSignalingInfo message MatchingSignalingInfo { string npid = 1; SignalingAddr addr = 2; } -// Matching2SignalingInfo message Matching2SignalingInfo { uint16 member_id = 1; SignalingAddr addr = 2; } -// BinAttr message BinAttr { uint16 id = 1; bytes data = 2; } -// IntAttr message IntAttr { uint16 id = 1; uint32 num = 2; } -// RoomMemberBinAttrInternal message RoomMemberBinAttrInternal { uint64 updateDate = 1; BinAttr data = 2; } -// BinAttrInternal message BinAttrInternal { uint64 updateDate = 1; uint16 updateMemberId = 2; BinAttr data = 3; } -// OptParam message OptParam { uint8 type = 1; uint8 flag = 2; uint16 hubMemberId = 3; } -// GroupConfig message GroupConfig { uint32 slotNum = 1; bytes label = 2; bool withPassword = 3; } -// UserInfo message UserInfo { string npId = 1; string onlineName = 2; string avatarUrl = 3; } -// RoomMemberDataInternal message RoomMemberDataInternal { UserInfo userInfo = 1; uint64 joinDate = 2; @@ -92,7 +81,6 @@ message RoomMemberDataInternal { repeated RoomMemberBinAttrInternal roomMemberBinAttrInternal = 8; } -// RoomGroup message RoomGroup { uint8 groupId = 1; bool withPassword = 2; @@ -101,7 +89,6 @@ message RoomGroup { uint32 curGroupMemberNum = 5; } -// RoomDataInternal message RoomDataInternal { uint16 serverId = 1; uint32 worldId = 2; @@ -116,7 +103,6 @@ message RoomDataInternal { repeated BinAttrInternal roomBinAttrInternal = 11; } -// RoomDataExternal message RoomDataExternal { uint16 serverId = 1; uint32 worldId = 2; @@ -137,31 +123,26 @@ message RoomDataExternal { repeated BinAttr roomBinAttrExternal = 17; } -// IntSearchFilter message IntSearchFilter { uint8 searchOperator = 1; IntAttr attr = 2; } -// BinSearchFilter message BinSearchFilter { uint8 searchOperator = 1; BinAttr attr = 2; } -// PresenceOptionData message PresenceOptionData { bytes data = 1; uint32 len = 2; } -// RoomGroupPasswordConfig message RoomGroupPasswordConfig { uint8 groupId = 1; bool withPassword = 2; } -// SearchRoomRequest message SearchRoomRequest { int32 option = 1; uint32 worldId = 2; @@ -175,14 +156,12 @@ message SearchRoomRequest { repeated uint16 attrId = 10; } -// SearchRoomResponse message SearchRoomResponse { uint32 startIndex = 1; uint32 total = 2; repeated RoomDataExternal rooms = 3; } -// CreateJoinRoomRequest message CreateJoinRoomRequest { uint32 worldId = 1; uint64 lobbyId = 2; @@ -203,7 +182,12 @@ message CreateJoinRoomRequest { OptParam sigOptParam = 17; } -// JoinRoomRequest +// Reply on creating a room +message CreateRoomResponse { + RoomDataInternal internal = 1; + OptParam opt_param = 2; +} + message JoinRoomRequest { uint64 roomId = 1; bytes roomPassword = 2; @@ -213,30 +197,26 @@ message JoinRoomRequest { uint8 teamId = 6; } -// JoinRoomResponse message JoinRoomResponse { RoomDataInternal room_data = 1; repeated Matching2SignalingInfo signaling_data = 2; + OptParam opt_param = 3; } -// LeaveRoomRequest message LeaveRoomRequest { uint64 roomId = 1; PresenceOptionData optData = 2; } -// GetRoomDataExternalListRequest message GetRoomDataExternalListRequest { repeated uint64 roomIds = 1; repeated uint16 attrIds = 2; } -// GetRoomDataExternalListResponse message GetRoomDataExternalListResponse { repeated RoomDataExternal rooms = 1; } -// SetRoomDataExternalRequest message SetRoomDataExternalRequest { uint64 roomId = 1; repeated IntAttr roomSearchableIntAttrExternal = 2; @@ -244,7 +224,6 @@ message SetRoomDataExternalRequest { repeated BinAttr roomBinAttrExternal = 4; } -// SetRoomDataInternalRequest message SetRoomDataInternalRequest { uint64 roomId = 1; uint32 flagFilter = 2; @@ -255,14 +234,12 @@ message SetRoomDataInternalRequest { repeated uint16 ownerPrivilegeRank = 7; } -// GetRoomMemberDataInternalRequest message GetRoomMemberDataInternalRequest { uint64 roomId = 1; uint16 memberId = 2; repeated uint16 attrId = 3; } -// SetRoomMemberDataInternalRequest message SetRoomMemberDataInternalRequest { uint64 roomId = 1; uint16 memberId = 2; @@ -270,40 +247,34 @@ message SetRoomMemberDataInternalRequest { repeated BinAttr roomMemberBinAttrInternal = 4; } -// SetUserInfo message SetUserInfo { uint16 serverId = 1; repeated BinAttr userBinAttr = 2; } -// GetRoomDataInternalRequest message GetRoomDataInternalRequest { uint64 roomId = 1; repeated uint16 attrId = 2; } -// RoomMemberUpdateInfo message RoomMemberUpdateInfo { RoomMemberDataInternal roomMemberDataInternal = 1; uint8 eventCause = 2; PresenceOptionData optData = 3; } -// NotificationUserJoinedRoom message NotificationUserJoinedRoom { uint64 room_id = 1; RoomMemberUpdateInfo update_info = 2; SignalingAddr signaling = 3; } -// RoomUpdateInfo message RoomUpdateInfo { uint8 eventCause = 1; int32 errorCode = 2; PresenceOptionData optData = 3; } -// RoomDataInternalUpdateInfo message RoomDataInternalUpdateInfo { RoomDataInternal newRoomDataInternal = 1; uint32 prevFlagAttr = 2; @@ -312,7 +283,6 @@ message RoomDataInternalUpdateInfo { repeated uint16 newRoomBinAttrInternal = 5; } -// RoomMemberDataInternalUpdateInfo message RoomMemberDataInternalUpdateInfo { RoomMemberDataInternal newRoomMemberDataInternal = 1; uint32 prevFlagAttr = 2; @@ -320,7 +290,6 @@ message RoomMemberDataInternalUpdateInfo { repeated uint16 newRoomMemberBinAttrInternal = 4; } -// GetPingInfoResponse message GetPingInfoResponse { uint16 serverId = 1; uint32 worldId = 2; @@ -328,7 +297,6 @@ message GetPingInfoResponse { uint32 rtt = 4; } -// SendRoomMessageRequest message SendRoomMessageRequest { uint64 roomId = 1; uint8 castType = 2; @@ -337,7 +305,6 @@ message SendRoomMessageRequest { uint8 option = 5; } -// RoomMessageInfo message RoomMessageInfo { bool filtered = 1; uint8 castType = 2; @@ -346,7 +313,6 @@ message RoomMessageInfo { bytes msg = 5; } -// MessageDetails message MessageDetails { string communicationId = 1; uint64 msgId = 2; @@ -358,13 +324,11 @@ message MessageDetails { bytes data = 8; } -// SendMessageRequest message SendMessageRequest { bytes message = 1; repeated string npids = 2; } -// BoardInfo message BoardInfo { uint32 rankLimit = 1; uint32 updateMode = 2; @@ -373,7 +337,6 @@ message BoardInfo { uint32 uploadSizeLimit = 5; } -// RecordScoreRequest message RecordScoreRequest { uint32 boardId = 1; int32 pcId = 2; @@ -382,7 +345,6 @@ message RecordScoreRequest { bytes data = 5; } -// GetScoreRangeRequest message GetScoreRangeRequest { uint32 boardId = 1; uint32 startRank = 2; @@ -391,13 +353,11 @@ message GetScoreRangeRequest { bool withGameInfo = 5; } -// ScoreNpIdPcId message ScoreNpIdPcId { string npid = 1; int32 pcId = 2; } -// GetScoreNpIdRequest message GetScoreNpIdRequest { uint32 boardId = 1; repeated ScoreNpIdPcId npids = 2; @@ -405,7 +365,6 @@ message GetScoreNpIdRequest { bool withGameInfo = 4; } -// GetScoreFriendsRequest message GetScoreFriendsRequest { uint32 boardId = 1; bool include_self = 2; @@ -414,7 +373,6 @@ message GetScoreFriendsRequest { bool withGameInfo = 5; } -// ScoreRankData message ScoreRankData { string npId = 1; string onlineName = 2; @@ -425,12 +383,10 @@ message ScoreRankData { uint64 recordDate = 7; } -// ScoreInfo message ScoreInfo { bytes data = 1; } -// GetScoreResponse message GetScoreResponse { repeated ScoreRankData rankArray = 1; repeated string commentArray = 2; @@ -439,27 +395,23 @@ message GetScoreResponse { uint32 totalRecord = 5; } -// RecordScoreGameDataRequest message RecordScoreGameDataRequest { uint32 boardId = 1; int32 pcId = 2; int64 score = 3; } -// GetScoreGameDataRequest message GetScoreGameDataRequest { uint32 boardId = 1; string npId = 2; int32 pcId = 3; } -// TusUser message TusUser { bool vuser = 1; string npid = 2; } -// TusVariable message TusVariable { string ownerId = 1; bool hasData = 2; @@ -469,31 +421,26 @@ message TusVariable { int64 oldVariable = 6; } -// TusVarResponse message TusVarResponse { repeated TusVariable vars = 1; } -// TusSetMultiSlotVariableRequest message TusSetMultiSlotVariableRequest { TusUser user = 1; repeated int32 slotIdArray = 2; repeated int64 variableArray = 3; } -// TusGetMultiSlotVariableRequest message TusGetMultiSlotVariableRequest { TusUser user = 1; repeated int32 slotIdArray = 2; } -// TusGetMultiUserVariableRequest message TusGetMultiUserVariableRequest { repeated TusUser users = 1; int32 slotId = 2; } -// TusGetFriendsVariableRequest message TusGetFriendsVariableRequest { int32 slotId = 1; bool includeSelf = 2; @@ -501,7 +448,6 @@ message TusGetFriendsVariableRequest { uint32 arrayNum = 4; } -// TusAddAndGetVariableRequest message TusAddAndGetVariableRequest { TusUser user = 1; int32 slotId = 2; @@ -510,7 +456,6 @@ message TusAddAndGetVariableRequest { string isLastChangedAuthorId = 5; } -// TusTryAndSetVariableRequest message TusTryAndSetVariableRequest { TusUser user = 1; int32 slotId = 2; @@ -521,13 +466,11 @@ message TusTryAndSetVariableRequest { repeated int64 compareValue = 7; } -// TusDeleteMultiSlotVariableRequest message TusDeleteMultiSlotVariableRequest { TusUser user = 1; repeated int32 slotIdArray = 2; } -// TusSetDataRequest message TusSetDataRequest { TusUser user = 1; int32 slotId = 2; @@ -537,7 +480,6 @@ message TusSetDataRequest { string isLastChangedAuthorId = 6; } -// TusDataStatus message TusDataStatus { string ownerId = 1; bool hasData = 2; @@ -546,36 +488,30 @@ message TusDataStatus { bytes info = 5; } -// TusData message TusData { TusDataStatus status = 1; bytes data = 2; } -// TusDataStatusResponse message TusDataStatusResponse { repeated TusDataStatus status = 1; } -// TusGetDataRequest message TusGetDataRequest { TusUser user = 1; int32 slotId = 2; } -// TusGetMultiSlotDataStatusRequest message TusGetMultiSlotDataStatusRequest { TusUser user = 1; repeated int32 slotIdArray = 2; } -// TusGetMultiUserDataStatusRequest message TusGetMultiUserDataStatusRequest { repeated TusUser users = 1; int32 slotId = 2; } -// TusGetFriendsDataStatusRequest message TusGetFriendsDataStatusRequest { int32 slotId = 1; bool includeSelf = 2; @@ -583,13 +519,11 @@ message TusGetFriendsDataStatusRequest { uint32 arrayNum = 4; } -// TusDeleteMultiSlotDataRequest message TusDeleteMultiSlotDataRequest { TusUser user = 1; repeated int32 slotIdArray = 2; } -// SetPresenceRequest message SetPresenceRequest { string title = 1; string status = 2; @@ -597,7 +531,6 @@ message SetPresenceRequest { bytes data = 4; } -// MatchingSearchCondition message MatchingSearchCondition { uint32 attr_type = 1; uint32 attr_id = 2; @@ -605,7 +538,6 @@ message MatchingSearchCondition { uint32 comp_value = 4; } -// MatchingAttr message MatchingAttr { uint32 attr_type = 1; uint32 attr_id = 2; @@ -613,7 +545,6 @@ message MatchingAttr { bytes data = 4; } -// CreateRoomGUIRequest message CreateRoomGUIRequest { uint32 total_slots = 1; uint32 private_slots = 2; @@ -622,13 +553,11 @@ message CreateRoomGUIRequest { repeated MatchingAttr game_attrs = 5; } -// GUIUserInfo message GUIUserInfo { UserInfo info = 1; bool owner = 2; } -// MatchingRoomStatus message MatchingRoomStatus { bytes id = 1; repeated GUIUserInfo members = 2; @@ -636,7 +565,6 @@ message MatchingRoomStatus { bytes opt = 4; } -// GetRoomListGUIRequest message GetRoomListGUIRequest { uint32 range_start = 1; uint32 range_max = 2; @@ -644,43 +572,36 @@ message GetRoomListGUIRequest { repeated MatchingAttr attrs = 4; } -// MatchingRoom message MatchingRoom { bytes id = 1; repeated MatchingAttr attr = 2; } -// MatchingRoomList message MatchingRoomList { uint32 start = 1; uint32 total = 2; repeated MatchingRoom rooms = 3; } -// MatchingGuiRoomId message MatchingGuiRoomId { bytes id = 1; } -// SetRoomSearchFlagGUI message SetRoomSearchFlagGUI { bytes roomid = 1; bool stealth = 2; } -// QuickMatchGUIRequest message QuickMatchGUIRequest { repeated MatchingSearchCondition conds = 1; uint32 available_num = 2; } -// SearchJoinRoomGUIRequest message SearchJoinRoomGUIRequest { repeated MatchingSearchCondition conds = 1; repeated MatchingAttr attrs = 2; } -// MatchingSearchJoinRoomInfo message MatchingSearchJoinRoomInfo { MatchingRoomStatus room = 1; repeated MatchingAttr attr = 2; diff --git a/rpcs3/Emu/NP/np_cache.cpp b/rpcs3/Emu/NP/np_cache.cpp index fc90a641a5..04223da545 100644 --- a/rpcs3/Emu/NP/np_cache.cpp +++ b/rpcs3/Emu/NP/np_cache.cpp @@ -120,6 +120,11 @@ namespace np rooms[room_id].password = password; } + void cache_manager::update_opt_param(SceNpMatching2RoomId room_id, const SceNpMatching2SignalingOptParam* sce_opt_param) + { + rooms[room_id].opt_param = *sce_opt_param; + } + std::pair> cache_manager::get_slots(SceNpMatching2RoomId room_id) { std::lock_guard lock(mutex); @@ -223,6 +228,18 @@ namespace np return {CELL_OK, rooms[room_id].password}; } + std::pair> cache_manager::get_opt_param(SceNpMatching2RoomId room_id) + { + std::lock_guard lock(mutex); + + if (!rooms.contains(room_id)) + { + return {SCE_NP_MATCHING2_ERROR_ROOM_NOT_FOUND, {}}; + } + + return {CELL_OK, rooms[room_id].opt_param}; + } + error_code cache_manager::get_member_and_attrs(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id, const std::vector& binattrs_list, SceNpMatching2RoomMemberDataInternal* ptr_member, u32 addr_data, u32 size_data, bool include_onlinename, bool include_avatarurl) { std::lock_guard lock(mutex); diff --git a/rpcs3/Emu/NP/np_cache.h b/rpcs3/Emu/NP/np_cache.h index 9e1b496ea5..8870f169a8 100644 --- a/rpcs3/Emu/NP/np_cache.h +++ b/rpcs3/Emu/NP/np_cache.h @@ -58,6 +58,8 @@ namespace np std::map groups; std::map members; + SceNpMatching2SignalingOptParam opt_param{}; + bool owner = false; }; @@ -70,10 +72,12 @@ namespace np bool add_member(SceNpMatching2RoomId room_id, const SceNpMatching2RoomMemberDataInternal* sce_roommemberdata); bool del_member(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id); void update_password(SceNpMatching2RoomId room_id, const std::optional& password); + void update_opt_param(SceNpMatching2RoomId room_id, const SceNpMatching2SignalingOptParam* sce_opt_param); std::pair> get_slots(SceNpMatching2RoomId room_id); std::pair> get_memberids(u64 room_id, s32 sort_method); std::pair> get_password(SceNpMatching2RoomId room_id); + std::pair> get_opt_param(SceNpMatching2RoomId room_id); error_code get_member_and_attrs(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id, const std::vector& binattrs_list, SceNpMatching2RoomMemberDataInternal* ptr_member, u32 addr_data, u32 size_data, bool include_onlinename, bool include_avatarurl); std::pair> get_npid(u64 room_id, u16 member_id); std::optional get_memberid(u64 room_id, const SceNpId& npid); diff --git a/rpcs3/Emu/NP/np_handler.cpp b/rpcs3/Emu/NP/np_handler.cpp index f76788287b..c55c16afec 100644 --- a/rpcs3/Emu/NP/np_handler.cpp +++ b/rpcs3/Emu/NP/np_handler.cpp @@ -1672,6 +1672,11 @@ namespace np return np_cache.get_memberids(room_id, sort_method); } + std::pair> np_handler::local_get_signaling_opt_param(SceNpMatching2RoomId room_id) + { + return np_cache.get_opt_param(room_id); + } + error_code np_handler::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) { auto [include_onlinename, include_avatarurl] = get_match2_context_options(ctx_id); diff --git a/rpcs3/Emu/NP/np_handler.h b/rpcs3/Emu/NP/np_handler.h index d3c1213cc6..a5f8014538 100644 --- a/rpcs3/Emu/NP/np_handler.h +++ b/rpcs3/Emu/NP/np_handler.h @@ -235,6 +235,7 @@ namespace np std::pair> local_get_room_slots(SceNpMatching2RoomId room_id); std::pair> local_get_room_password(SceNpMatching2RoomId room_id); std::pair> local_get_room_memberids(SceNpMatching2RoomId room_id, s32 sort_method); + std::pair> local_get_signaling_opt_param(SceNpMatching2RoomId room_id); 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 diff --git a/rpcs3/Emu/NP/np_requests.cpp b/rpcs3/Emu/NP/np_requests.cpp index bcc97a2b25..0ee7d1d0fc 100644 --- a/rpcs3/Emu/NP/np_requests.cpp +++ b/rpcs3/Emu/NP/np_requests.cpp @@ -200,8 +200,11 @@ namespace np return; } - const auto resp = reply.get_protobuf(); + const auto resp = reply.get_protobuf(); ensure(!reply.is_error(), "Malformed reply to CreateRoom command"); + ensure(resp->has_internal()); + + const auto& resp_internal = resp->internal(); const u32 event_key = get_event_key(); auto [include_onlinename, include_avatarurl] = get_match2_context_options(cb_info_opt->ctx_id); @@ -209,13 +212,19 @@ namespace np auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_CreateJoinRoom, sizeof(SceNpMatching2CreateJoinRoomResponse)); auto* room_resp = reinterpret_cast(edata.data()); auto* room_info = edata.allocate(sizeof(SceNpMatching2RoomDataInternal), room_resp->roomDataInternal); - RoomDataInternal_to_SceNpMatching2RoomDataInternal(edata, *resp, room_info, npid, include_onlinename, include_avatarurl); + RoomDataInternal_to_SceNpMatching2RoomDataInternal(edata, resp_internal, room_info, npid, include_onlinename, include_avatarurl); np_memory.shrink_allocation(edata.addr(), edata.size()); + const auto resp_opt_param = resp->opt_param(); + SceNpMatching2SignalingOptParam opt_param{}; + OptParam_to_SceNpMatching2SignalingOptParam(resp_opt_param, &opt_param); + np_cache.insert_room(room_info); - np_cache.update_password(room_resp->roomDataInternal->roomId, cached_cj_password); + np_cache.update_password(room_info->roomId, cached_cj_password); + np_cache.update_opt_param(room_info->roomId, &opt_param); extra_nps::print_SceNpMatching2CreateJoinRoomResponse(room_resp); + extra_nps::print_SceNpMatching2SignalingOptParam(&opt_param); cb_info_opt->queue_callback(req_id, event_key, 0, edata.size()); } @@ -275,36 +284,38 @@ namespace np RoomDataInternal_to_SceNpMatching2RoomDataInternal(edata, resp->room_data(), room_info, npid, include_onlinename, include_avatarurl); np_memory.shrink_allocation(edata.addr(), edata.size()); + const u64 room_id = resp->room_data().roomid(); + + const auto resp_opt_param = resp->opt_param(); + SceNpMatching2SignalingOptParam opt_param{}; + OptParam_to_SceNpMatching2SignalingOptParam(resp_opt_param, &opt_param); np_cache.insert_room(room_info); + np_cache.update_opt_param(room_id, &opt_param); extra_nps::print_SceNpMatching2RoomDataInternal(room_info); + extra_nps::print_SceNpMatching2SignalingOptParam(&opt_param); // We initiate signaling if necessary - if (resp->signaling_data_size() > 0) + for (int i = 0; i < resp->signaling_data_size(); i++) { - const u64 room_id = resp->room_data().roomid(); + const auto& signaling_info = resp->signaling_data(i); + ensure(signaling_info.has_addr()); - for (int i = 0; i < resp->signaling_data_size(); i++) - { - const auto& signaling_info = resp->signaling_data(i); - ensure(signaling_info.has_addr()); + const u32 addr_p2p = register_ip(signaling_info.addr().ip()); + const u16 port_p2p = signaling_info.addr().port().value(); - const u32 addr_p2p = register_ip(signaling_info.addr().ip()); - const u16 port_p2p = signaling_info.addr().port().value(); + const u16 member_id = signaling_info.member_id().value(); + const auto [npid_res, npid_p2p] = np_cache.get_npid(room_id, member_id); - const u16 member_id = signaling_info.member_id().value(); - const auto [npid_res, npid_p2p] = np_cache.get_npid(room_id, member_id); + if (npid_res != CELL_OK) + continue; - if (npid_res != CELL_OK) - continue; + rpcn_log.notice("JoinRoomResult told to connect to member(%d=%s) of room(%d): %s:%d", member_id, reinterpret_cast(npid_p2p->handle.data), room_id, ip_to_string(addr_p2p), port_p2p); - rpcn_log.notice("JoinRoomResult told to connect to member(%d=%s) of room(%d): %s:%d", member_id, reinterpret_cast(npid_p2p->handle.data), room_id, ip_to_string(addr_p2p), port_p2p); - - // Attempt Signaling - auto& sigh = g_fxo->get>(); - const u32 conn_id = sigh.init_sig2(*npid_p2p, room_id, member_id); - sigh.start_sig(conn_id, addr_p2p, port_p2p); - } + // Attempt Signaling + auto& sigh = g_fxo->get>(); + const u32 conn_id = sigh.init_sig2(*npid_p2p, room_id, member_id); + sigh.start_sig(conn_id, addr_p2p, port_p2p); } cb_info_opt->queue_callback(req_id, event_key, 0, edata.size()); diff --git a/rpcs3/Emu/NP/pb_helpers.cpp b/rpcs3/Emu/NP/pb_helpers.cpp index c00eed8496..e82fc2ec0a 100644 --- a/rpcs3/Emu/NP/pb_helpers.cpp +++ b/rpcs3/Emu/NP/pb_helpers.cpp @@ -632,4 +632,11 @@ namespace np MatchingAttr_to_SceNpMatchingAttr(edata, resp.attr(), room_info->attr); } + void OptParam_to_SceNpMatching2SignalingOptParam(const np2_structs::OptParam& resp, SceNpMatching2SignalingOptParam* opt_param) + { + opt_param->type = resp.type().value(); + opt_param->flag = resp.flag().value(); + opt_param->hubMemberId = resp.hubmemberid().value(); + } + } // namespace np diff --git a/rpcs3/Emu/NP/pb_helpers.h b/rpcs3/Emu/NP/pb_helpers.h index a11c092f9c..c7482d7bc4 100644 --- a/rpcs3/Emu/NP/pb_helpers.h +++ b/rpcs3/Emu/NP/pb_helpers.h @@ -32,4 +32,5 @@ namespace np void MatchingRoomList_to_SceNpMatchingRoomList(event_data& edata, const np2_structs::MatchingRoomList& resp, SceNpMatchingRoomList* room_list); void MatchingSearchJoinRoomInfo_to_SceNpMatchingSearchJoinRoomInfo(event_data& edata, const np2_structs::MatchingSearchJoinRoomInfo& resp, SceNpMatchingSearchJoinRoomInfo* room_info); void MatchingAttr_to_SceNpMatchingAttr(event_data& edata, const google::protobuf::RepeatedPtrField& attr_list, vm::bptr& first_attr); + void OptParam_to_SceNpMatching2SignalingOptParam(const np2_structs::OptParam& resp, SceNpMatching2SignalingOptParam* opt_param); } // namespace np diff --git a/rpcs3/Emu/NP/rpcn_client.cpp b/rpcs3/Emu/NP/rpcn_client.cpp index 2b58310f1c..a87fff8244 100644 --- a/rpcs3/Emu/NP/rpcn_client.cpp +++ b/rpcs3/Emu/NP/rpcn_client.cpp @@ -256,7 +256,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 = 29; + constexpr u32 RPCN_PROTOCOL_VERSION = 30; constexpr usz RPCN_HEADER_SIZE = 15; const char* error_to_explanation(rpcn::ErrorType error) From cafc2aa9d01e2b89927bfb71f7d144da1167b500 Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Mon, 26 Jan 2026 10:37:59 +0100 Subject: [PATCH 15/40] Implement sceNpMatching2GetMemoryInfo --- rpcs3/Emu/Cell/Modules/sceNp2.cpp | 12 ++++++++++-- rpcs3/Emu/NP/np_allocator.h | 12 ++++++++++++ rpcs3/Emu/NP/np_handler.cpp | 12 ++++++++++++ rpcs3/Emu/NP/np_handler.h | 1 + 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/sceNp2.cpp b/rpcs3/Emu/Cell/Modules/sceNp2.cpp index b6ad47b846..0c8f97fc2f 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp2.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp2.cpp @@ -616,9 +616,9 @@ error_code sceNpMatching2CreateServerContext( return CELL_OK; } -error_code sceNpMatching2GetMemoryInfo(vm::ptr memInfo) // TODO +error_code sceNpMatching2GetMemoryInfo(vm::ptr memInfo) { - sceNp2.todo("sceNpMatching2GetMemoryInfo(memInfo=*0x%x)", memInfo); + sceNp2.warning("sceNpMatching2GetMemoryInfo(memInfo=*0x%x)", memInfo); auto& nph = g_fxo->get>(); @@ -627,6 +627,14 @@ error_code sceNpMatching2GetMemoryInfo(vm::ptr memInfo return SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED; } + if (!memInfo) + { + return SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT; + } + + SceNpMatching2MemoryInfo mem_info = nph.get_memory_info(); + *memInfo = mem_info; + return CELL_OK; } diff --git a/rpcs3/Emu/NP/np_allocator.h b/rpcs3/Emu/NP/np_allocator.h index ee8017cb72..76445a4274 100644 --- a/rpcs3/Emu/NP/np_allocator.h +++ b/rpcs3/Emu/NP/np_allocator.h @@ -39,6 +39,11 @@ namespace np m_allocs.clear(); } + std::tuple get_stats() const + { + return {m_size, m_size - m_avail, m_max_usage}; + } + u32 allocate(u32 size) { std::lock_guard lock(m_mutex); @@ -82,6 +87,12 @@ namespace np m_allocs.emplace(last_free, alloc_size); m_avail -= alloc_size; + const u32 usage = m_size - m_avail; + if (usage > m_max_usage) + { + m_max_usage = usage; + } + memset((static_cast(m_pool.get_ptr())) + last_free, 0, alloc_size); np_mem_allocator.trace("Allocation off:%d size:%d psize:%d, pavail:%d", last_free, alloc_size, m_size, m_avail); @@ -121,6 +132,7 @@ namespace np vm::ptr m_pool{}; u32 m_size = 0; u32 m_avail = 0; + u32 m_max_usage = 0; std::map m_allocs{}; // offset/size }; } // namespace np diff --git a/rpcs3/Emu/NP/np_handler.cpp b/rpcs3/Emu/NP/np_handler.cpp index c55c16afec..777301abbb 100644 --- a/rpcs3/Emu/NP/np_handler.cpp +++ b/rpcs3/Emu/NP/np_handler.cpp @@ -1764,4 +1764,16 @@ namespace np } } + SceNpMatching2MemoryInfo np_handler::get_memory_info() const + { + auto [m_size, m_usage, m_max_usage] = np_memory.get_stats(); + + SceNpMatching2MemoryInfo mem_info{}; + mem_info.totalMemSize = m_size; + mem_info.curMemUsage = m_usage; + mem_info.maxMemUsage = m_max_usage; + + return mem_info; + } + } // namespace np diff --git a/rpcs3/Emu/NP/np_handler.h b/rpcs3/Emu/NP/np_handler.h index a5f8014538..51d510b854 100644 --- a/rpcs3/Emu/NP/np_handler.h +++ b/rpcs3/Emu/NP/np_handler.h @@ -262,6 +262,7 @@ namespace np u32 add_players_to_history(const SceNpId* npids, const char* description, u32 count); u32 get_players_history_count(u32 options); bool get_player_history_entry(u32 options, u32 index, SceNpId* npid); + SceNpMatching2MemoryInfo get_memory_info() const; error_code abort_request(u32 req_id); // For signaling From b0b0ed7634fa544978a5f2f111905b3a90e68bae Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Mon, 26 Jan 2026 10:44:59 +0100 Subject: [PATCH 16/40] Implement sceNpMatching2GetCbQueueInfo --- rpcs3/Emu/Cell/Modules/sceNp2.cpp | 13 ++++++++++++- rpcs3/Emu/Cell/Modules/sceNpUtil.cpp | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/sceNp2.cpp b/rpcs3/Emu/Cell/Modules/sceNp2.cpp index 0c8f97fc2f..98f2bf3883 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp2.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp2.cpp @@ -1064,7 +1064,7 @@ error_code sceNpMatching2GetRoomMemberDataInternalLocal(SceNpMatching2ContextId error_code sceNpMatching2GetCbQueueInfo(SceNpMatching2ContextId ctxId, vm::ptr queueInfo) { - sceNp2.todo("sceNpMatching2GetCbQueueInfo(ctxId=%d, queueInfo=*0x%x)", ctxId, queueInfo); + sceNp2.warning("sceNpMatching2GetCbQueueInfo(ctxId=%d, queueInfo=*0x%x)", ctxId, queueInfo); auto& nph = g_fxo->get>(); @@ -1073,6 +1073,17 @@ error_code sceNpMatching2GetCbQueueInfo(SceNpMatching2ContextId ctxId, vm::ptrrequestCbQueueLen = 255; + queueInfo->sessionEventCbQueueLen = 255; + queueInfo->sessionMsgCbQueueLen = 255; + return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp b/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp index b8f1341d85..e2f0df9620 100644 --- a/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp @@ -65,7 +65,7 @@ struct sce_np_util_manager error_code sceNpUtilBandwidthTestInitStart([[maybe_unused]] ppu_thread& ppu, u32 prio, u32 stack) { - sceNpUtil.todo("sceNpUtilBandwidthTestInitStart(prio=%d, stack=%d)", prio, stack); + sceNpUtil.warning("sceNpUtilBandwidthTestInitStart(prio=%d, stack=%d)", prio, stack); auto& util_manager = g_fxo->get(); std::lock_guard lock(util_manager.mtx); From b7311bd6dbea76af058b05849c69406f2a7d744e Mon Sep 17 00:00:00 2001 From: Ani Date: Thu, 29 Jan 2026 04:27:30 +0100 Subject: [PATCH 17/40] hle: Register missing functions --- rpcs3/Emu/Cell/Modules/cellFont.cpp | 7 ++++++ rpcs3/Emu/Cell/Modules/cellFs.cpp | 14 ++++++++++++ rpcs3/Emu/Cell/Modules/cellSaveData.cpp | 14 +++++++++++- rpcs3/Emu/Cell/Modules/cellSpurs.cpp | 8 +++++++ rpcs3/Emu/Cell/Modules/cellSysmodule.cpp | 28 ++++++++++++++++++++++++ rpcs3/Emu/Cell/Modules/sceNpTrophy.cpp | 6 +++++ 6 files changed, 76 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/Cell/Modules/cellFont.cpp b/rpcs3/Emu/Cell/Modules/cellFont.cpp index c960375c0c..348a2869fc 100644 --- a/rpcs3/Emu/Cell/Modules/cellFont.cpp +++ b/rpcs3/Emu/Cell/Modules/cellFont.cpp @@ -2228,6 +2228,12 @@ error_code cellFontStatic() return CELL_OK; } +error_code cellFontsetUSleep() +{ + cellFont.todo("cellFontsetUSleep()"); + return CELL_OK; +} + DECLARE(ppu_module_manager::cellFont)("cellFont", []() { @@ -2315,4 +2321,5 @@ DECLARE(ppu_module_manager::cellFont)("cellFont", []() REG_FUNC(cellFont, cellFontGraphicsGetLineRGBA); REG_FUNC(cellFont, cellFontControl); REG_FUNC(cellFont, cellFontStatic); + REG_FUNC(cellFont, cellFontsetUSleep); }); diff --git a/rpcs3/Emu/Cell/Modules/cellFs.cpp b/rpcs3/Emu/Cell/Modules/cellFs.cpp index bff73f530b..1aa83390ae 100644 --- a/rpcs3/Emu/Cell/Modules/cellFs.cpp +++ b/rpcs3/Emu/Cell/Modules/cellFs.cpp @@ -1034,6 +1034,18 @@ s32 cellFsUnregisterL10nCallbacks() return CELL_OK; } +s32 cellFsGetDirent() +{ + cellFs.todo("cellFsGetDirent()"); + return CELL_OK; +} + +s32 cellFsGetDirentCount() +{ + cellFs.todo("cellFsGetDirentCount()"); + return CELL_OK; +} + DECLARE(ppu_module_manager::cellFs)("sys_fs", []() { REG_FUNC(sys_fs, cellFsAccess); @@ -1065,6 +1077,8 @@ DECLARE(ppu_module_manager::cellFs)("sys_fs", []() REG_FUNC(sys_fs, cellFsGetBlockSize); REG_FUNC(sys_fs, cellFsGetBlockSize2); REG_FUNC(sys_fs, cellFsGetDirectoryEntries); + REG_FUNC(sys_fs, cellFsGetDirent); + REG_FUNC(sys_fs, cellFsGetDirentCount); REG_FUNC(sys_fs, cellFsGetFreeSize); REG_FUNC(sys_fs, cellFsGetPath); REG_FUNC(sys_fs, cellFsLink); diff --git a/rpcs3/Emu/Cell/Modules/cellSaveData.cpp b/rpcs3/Emu/Cell/Modules/cellSaveData.cpp index bb99a1f6d6..a4d160fdcb 100644 --- a/rpcs3/Emu/Cell/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSaveData.cpp @@ -2514,6 +2514,18 @@ error_code cellSaveDataUserFixedDelete(ppu_thread& ppu, u32 userId, PSetList set return savedata_op(ppu, SAVEDATA_OP_FIXED_DELETE, 0, vm::null, 1, setList, setBuf, vm::null, funcFixed, vm::null, vm::null, container, 6, userdata, userId, funcDone); } +error_code cellSaveDataGetEnableOverlay() +{ + cellSaveData.todo("cellSaveDataGetEnableOverlay()"); + + // auto& manager = g_fxo->get(); + // manager.enable_overlay; + + // TODO + + return CELL_OK; +} + void cellSaveDataEnableOverlay(s32 enable) { cellSaveData.notice("cellSaveDataEnableOverlay(enable=%d)", enable); @@ -2521,7 +2533,6 @@ void cellSaveDataEnableOverlay(s32 enable) manager.enable_overlay = enable != 0; } - // Functions (Extensions) error_code cellSaveDataListDelete(ppu_thread& ppu, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncDone funcDone, u32 container, vm::ptr userdata) { @@ -2678,6 +2689,7 @@ void cellSysutil_SaveData_init() REG_VAR(cellSysutil, g_savedata_context).flag(MFF_HIDDEN); // libsysutil functions: + REG_FUNC(cellSysutil, cellSaveDataGetEnableOverlay); REG_FUNC(cellSysutil, cellSaveDataEnableOverlay); REG_FUNC(cellSysutil, cellSaveDataDelete2); diff --git a/rpcs3/Emu/Cell/Modules/cellSpurs.cpp b/rpcs3/Emu/Cell/Modules/cellSpurs.cpp index c5defbd048..7caee24849 100644 --- a/rpcs3/Emu/Cell/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSpurs.cpp @@ -1438,6 +1438,13 @@ s32 cellSpursInitializeWithAttribute2(ppu_thread& ppu, vm::ptr spurs, attr->swlIsPreem); } +// Initialise SPURS +s32 cellSpursInitializeForSpuSharing() +{ + cellSpurs.todo("cellSpursInitializeForSpuSharing()"); + return CELL_OK; +} + /// Initialise SPURS attribute s32 _cellSpursAttributeInitialize(vm::ptr attr, u32 revision, u32 sdkVersion, u32 nSpus, s32 spuPriority, s32 ppuPriority, b8 exitIfNoWork) { @@ -5390,6 +5397,7 @@ DECLARE(ppu_module_manager::cellSpurs)("cellSpurs", [](ppu_static_module* _this) REG_FUNC(cellSpurs, cellSpursInitialize); REG_FUNC(cellSpurs, cellSpursInitializeWithAttribute); REG_FUNC(cellSpurs, cellSpursInitializeWithAttribute2); + REG_FUNC(cellSpurs, cellSpursInitializeForSpuSharing); REG_FUNC(cellSpurs, cellSpursFinalize); REG_FUNC(cellSpurs, _cellSpursAttributeInitialize); REG_FUNC(cellSpurs, cellSpursAttributeSetMemoryContainerForSpuThread); diff --git a/rpcs3/Emu/Cell/Modules/cellSysmodule.cpp b/rpcs3/Emu/Cell/Modules/cellSysmodule.cpp index 5548a1bbb4..41eae6bb82 100644 --- a/rpcs3/Emu/Cell/Modules/cellSysmodule.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSysmodule.cpp @@ -406,6 +406,30 @@ error_code cellSysmoduleIsLoadedEx() return CELL_OK; } +error_code cellSysmoduleLoadModuleFile() +{ + UNIMPLEMENTED_FUNC(cellSysmodule); + return CELL_OK; +} + +error_code cellSysmoduleUnloadModuleFile() +{ + UNIMPLEMENTED_FUNC(cellSysmodule); + return CELL_OK; +} + +error_code cellSysmoduleSetDebugmode() +{ + UNIMPLEMENTED_FUNC(cellSysmodule); + return CELL_OK; +} + +error_code cellSysmoduleSetInternalmode() +{ + UNIMPLEMENTED_FUNC(cellSysmodule); + return CELL_OK; +} + DECLARE(ppu_module_manager::cellSysmodule)("cellSysmodule", []() { REG_FUNC(cellSysmodule, cellSysmoduleInitialize); @@ -421,4 +445,8 @@ DECLARE(ppu_module_manager::cellSysmodule)("cellSysmodule", []() REG_FUNC(cellSysmodule, cellSysmoduleUnloadModuleEx); REG_FUNC(cellSysmodule, cellSysmoduleLoadModuleEx); REG_FUNC(cellSysmodule, cellSysmoduleIsLoadedEx); + REG_FUNC(cellSysmodule, cellSysmoduleLoadModuleFile); + REG_FUNC(cellSysmodule, cellSysmoduleUnloadModuleFile); + REG_FUNC(cellSysmodule, cellSysmoduleSetDebugmode); + REG_FUNC(cellSysmodule, cellSysmoduleSetInternalmode); }); diff --git a/rpcs3/Emu/Cell/Modules/sceNpTrophy.cpp b/rpcs3/Emu/Cell/Modules/sceNpTrophy.cpp index 3407778d64..803d174549 100644 --- a/rpcs3/Emu/Cell/Modules/sceNpTrophy.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNpTrophy.cpp @@ -1529,6 +1529,11 @@ error_code sceNpTrophyGetTrophyIcon(u32 context, u32 handle, s32 trophyId, vm::p return CELL_OK; } +error_code sceNpTrophyNetworkSync() +{ + UNIMPLEMENTED_FUNC(sceNpTrophy); + return CELL_OK; +} DECLARE(ppu_module_manager::sceNpTrophy)("sceNpTrophy", []() { @@ -1553,4 +1558,5 @@ DECLARE(ppu_module_manager::sceNpTrophy)("sceNpTrophy", []() REG_FUNC(sceNpTrophy, sceNpTrophyGetTrophyDetails); REG_FUNC(sceNpTrophy, sceNpTrophyGetTrophyInfo); REG_FUNC(sceNpTrophy, sceNpTrophyGetGameIcon); + REG_FUNC(sceNpTrophy, sceNpTrophyNetworkSync); }); From 086ab3cb37dc8e993ad72480047bd0739cd832d5 Mon Sep 17 00:00:00 2001 From: Tuna Celik <24642056+freakmaxi@users.noreply.github.com> Date: Thu, 29 Jan 2026 22:25:56 +0100 Subject: [PATCH 18/40] Fix for an emulation shutdown hang --- rpcs3/Emu/System.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 0fa9300cc2..b204cc38b9 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -3393,7 +3393,7 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s bool is_being_held_longer = false; - for (int i = 0; !*join_ended && thread_ctrl::state() != thread_state::aborting;) + for (int i = 0; !*join_ended && thread_ctrl::state() != thread_state::aborting; i++) { if (g_watchdog_hold_ctr) { From 97feb4eed48787b0e985483164fcff69d08b3179 Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Thu, 29 Jan 2026 00:37:04 +0100 Subject: [PATCH 19/40] Add Message logging --- Utilities/StrUtil.h | 2 +- rpcs3/Emu/NP/np_handler.cpp | 5 +++++ rpcs3/Emu/NP/rpcn_client.cpp | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Utilities/StrUtil.h b/Utilities/StrUtil.h index b5df886164..d274cc074d 100644 --- a/Utilities/StrUtil.h +++ b/Utilities/StrUtil.h @@ -188,7 +188,7 @@ namespace fmt result.append(separator); } - return result.append(source.back()); + return result.append(*end); } template diff --git a/rpcs3/Emu/NP/np_handler.cpp b/rpcs3/Emu/NP/np_handler.cpp index 777301abbb..9dc02f983c 100644 --- a/rpcs3/Emu/NP/np_handler.cpp +++ b/rpcs3/Emu/NP/np_handler.cpp @@ -1085,6 +1085,11 @@ namespace np void np_handler::send_message(const message_data& msg_data, const std::set& npids) { + const std::string npids_string = fmt::format("\"%s\"", fmt::merge(npids, "\",\"")); + + rpcn_log.notice("Sending message to %s:", npids_string); + msg_data.print(); + get_rpcn()->send_message(msg_data, npids); } diff --git a/rpcs3/Emu/NP/rpcn_client.cpp b/rpcs3/Emu/NP/rpcn_client.cpp index a87fff8244..61ad839555 100644 --- a/rpcs3/Emu/NP/rpcn_client.cpp +++ b/rpcs3/Emu/NP/rpcn_client.cpp @@ -3122,6 +3122,7 @@ namespace rpcn if (sdata.is_error()) { + rpcn_log.error("Error parsing MessageReceived notification"); return; } @@ -3143,6 +3144,9 @@ namespace rpcn strcpy_trunc(mdata.commId.data, pb_mdata->communicationid()); mdata.data.assign(pb_mdata->data().begin(), pb_mdata->data().end()); + rpcn_log.notice("Received message from %s:", sender); + mdata.print(); + // Save the message and call callbacks { std::lock_guard lock(mutex_messages); From 4df51025e5a268aed439f7dea1fe0d3b4debf8a4 Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Thu, 29 Jan 2026 05:05:06 +0100 Subject: [PATCH 20/40] Improve Message ComId handling --- rpcs3/Emu/Cell/Modules/sceNp2.cpp | 2 +- rpcs3/Emu/NP/np_helpers.cpp | 26 ++++++++++++++++++++------ rpcs3/Emu/NP/np_helpers.h | 2 +- rpcs3/Emu/NP/rpcn_client.cpp | 9 +++++---- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/sceNp2.cpp b/rpcs3/Emu/Cell/Modules/sceNp2.cpp index 98f2bf3883..fddc514bcc 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp2.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp2.cpp @@ -1345,7 +1345,7 @@ error_code sceNpMatching2CreateContext( error_code sceNpMatching2GetSignalingOptParamLocal(SceNpMatching2ContextId ctxId, SceNpMatching2RoomId roomId, vm::ptr signalingOptParam) { - sceNp2.todo("sceNpMatching2GetSignalingOptParamLocal(ctxId=%d, roomId=%d, signalingOptParam=*0x%x)", ctxId, roomId, signalingOptParam); + sceNp2.warning("sceNpMatching2GetSignalingOptParamLocal(ctxId=%d, roomId=%d, signalingOptParam=*0x%x)", ctxId, roomId, signalingOptParam); auto& nph = g_fxo->get>(); diff --git a/rpcs3/Emu/NP/np_helpers.cpp b/rpcs3/Emu/NP/np_helpers.cpp index b6e49b97b2..839b33b614 100644 --- a/rpcs3/Emu/NP/np_helpers.cpp +++ b/rpcs3/Emu/NP/np_helpers.cpp @@ -8,6 +8,8 @@ #include #endif +LOG_CHANNEL(rpcn_log, "rpcn"); + namespace np { std::string ip_to_string(u32 ip_addr) @@ -34,6 +36,24 @@ namespace np return fmt::format("%s_%02d", com_id_data, communicationId.num); } + std::optional string_to_communication_id(std::string_view str) + { + SceNpCommunicationId id{}; + + const auto split_id = fmt::split_sv(str, {"_"}); + + if (split_id.size() != 2 || split_id[0].length() != 9 || split_id[1].length() != 2 || !std::isdigit(split_id[1][0]) || !std::isdigit(split_id[1][1])) + { + rpcn_log.error("Tried to parse an invalid communication_id!"); + return std::nullopt; + } + + strcpy_trunc(id.data, split_id); + id.num = std::stoi(std::string(split_id[1])); + + return id; + } + void strings_to_userinfo(std::string_view npid, std::string_view online_name, std::string_view avatar_url, SceNpUserInfo& user_info) { memset(&user_info, 0, sizeof(user_info)); @@ -81,12 +101,6 @@ namespace np strcpy_trunc(avatar_url.data, str); } - void string_to_communication_id(std::string_view str, SceNpCommunicationId& comm_id) - { - memset(&comm_id, 0, sizeof(comm_id)); - strcpy_trunc(comm_id.data, str); - } - bool is_valid_npid(const SceNpId& npid) { if (!std::all_of(npid.handle.data, npid.handle.data + 16, [](char c) { return std::isalnum(c) || c == '-' || c == '_' || c == 0; } ) diff --git a/rpcs3/Emu/NP/np_helpers.h b/rpcs3/Emu/NP/np_helpers.h index 054e45388d..c33b4ca001 100644 --- a/rpcs3/Emu/NP/np_helpers.h +++ b/rpcs3/Emu/NP/np_helpers.h @@ -10,11 +10,11 @@ namespace np std::string ether_to_string(std::array& ether); bool validate_communication_id(const SceNpCommunicationId& com_id); std::string communication_id_to_string(const SceNpCommunicationId& communicationId); + std::optional string_to_communication_id(std::string_view str); void string_to_npid(std::string_view str, SceNpId& npid); void string_to_online_name(std::string_view str, SceNpOnlineName& online_name); void string_to_avatar_url(std::string_view str, SceNpAvatarUrl& avatar_url); - void string_to_communication_id(std::string_view str, SceNpCommunicationId& comm_id); void strings_to_userinfo(std::string_view npid, std::string_view online_name, std::string_view avatar_url, SceNpUserInfo& user_info); template diff --git a/rpcs3/Emu/NP/rpcn_client.cpp b/rpcs3/Emu/NP/rpcn_client.cpp index 61ad839555..cce4fa397b 100644 --- a/rpcs3/Emu/NP/rpcn_client.cpp +++ b/rpcs3/Emu/NP/rpcn_client.cpp @@ -2171,7 +2171,7 @@ namespace rpcn bool rpcn_client::send_message(const message_data& msg_data, const std::set& npids) { np2_structs::MessageDetails pb_message; - pb_message.set_communicationid(static_cast(msg_data.commId.data)); + pb_message.set_communicationid(np::communication_id_to_string(msg_data.commId)); pb_message.set_msgid(msg_data.msgId); pb_message.mutable_maintype()->set_value(msg_data.mainType); pb_message.mutable_subtype()->set_value(msg_data.subType); @@ -3126,8 +3126,9 @@ namespace rpcn return; } - if (pb_mdata->communicationid().empty() || pb_mdata->communicationid().size() > 9 || - pb_mdata->subject().empty() || pb_mdata->body().empty()) + const auto communication_id = np::string_to_communication_id(pb_mdata->communicationid()); + + if (!communication_id) { rpcn_log.warning("Discarded invalid message!"); return; @@ -3141,7 +3142,7 @@ namespace rpcn .subject = pb_mdata->subject(), .body = pb_mdata->body()}; - strcpy_trunc(mdata.commId.data, pb_mdata->communicationid()); + mdata.commId = *communication_id; mdata.data.assign(pb_mdata->data().begin(), pb_mdata->data().end()); rpcn_log.notice("Received message from %s:", sender); From 3e0cfc651d9e2363248dcc013fc15ed71328ec9a Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Thu, 29 Jan 2026 05:37:51 +0100 Subject: [PATCH 21/40] Fix sceNpBasicLimited_0xEB42E2E6 --- rpcs3/Emu/Cell/Modules/sceNp.cpp | 1 + rpcs3/Emu/NP/np_handler.cpp | 4 +--- rpcs3/Emu/NP/np_helpers.cpp | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/sceNp.cpp b/rpcs3/Emu/Cell/Modules/sceNp.cpp index ee9c308265..2a2075f0ca 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp.cpp @@ -1173,6 +1173,7 @@ error_code _sceNpBasicSendMessage(vm::cptr to, vm::cptr data, u32 { struct sceNpBasicSendMessage_time_slots { + sceNpBasicSendMessage_time_slots() = default; sceNpBasicSendMessage_time_slots(sceNpBasicSendMessage_time_slots&&) = delete; std::array data{}; }; diff --git a/rpcs3/Emu/NP/np_handler.cpp b/rpcs3/Emu/NP/np_handler.cpp index 9dc02f983c..bc65f545b3 100644 --- a/rpcs3/Emu/NP/np_handler.cpp +++ b/rpcs3/Emu/NP/np_handler.cpp @@ -1085,9 +1085,7 @@ namespace np void np_handler::send_message(const message_data& msg_data, const std::set& npids) { - const std::string npids_string = fmt::format("\"%s\"", fmt::merge(npids, "\",\"")); - - rpcn_log.notice("Sending message to %s:", npids_string); + rpcn_log.notice("Sending message to \"%s\":", fmt::merge(npids, "\",\"")); msg_data.print(); get_rpcn()->send_message(msg_data, npids); diff --git a/rpcs3/Emu/NP/np_helpers.cpp b/rpcs3/Emu/NP/np_helpers.cpp index 839b33b614..79f61ca627 100644 --- a/rpcs3/Emu/NP/np_helpers.cpp +++ b/rpcs3/Emu/NP/np_helpers.cpp @@ -48,7 +48,7 @@ namespace np return std::nullopt; } - strcpy_trunc(id.data, split_id); + strcpy_trunc(id.data, split_id[0]); id.num = std::stoi(std::string(split_id[1])); return id; From db3d9cd2179ac0c1080b997f277d9c114e82bc76 Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Fri, 30 Jan 2026 10:28:49 +0100 Subject: [PATCH 22/40] Implement sceNpMatching2GetRoomMemberDataExternalList --- rpcs3/Emu/Cell/Modules/sceNp2.cpp | 9 +- rpcs3/Emu/NP/generated/np2_structs.pb.cc | 681 ++++++++++++++++++++++ rpcs3/Emu/NP/generated/np2_structs.pb.h | 692 +++++++++++++++++++++++ rpcs3/Emu/NP/generated/np2_structs.proto | 11 + rpcs3/Emu/NP/np_handler.cpp | 1 + rpcs3/Emu/NP/np_handler.h | 2 + rpcs3/Emu/NP/np_requests.cpp | 44 ++ rpcs3/Emu/NP/np_structs_extra.cpp | 24 + rpcs3/Emu/NP/np_structs_extra.h | 2 + rpcs3/Emu/NP/pb_helpers.cpp | 31 +- rpcs3/Emu/NP/pb_helpers.h | 2 + rpcs3/Emu/NP/rpcn_client.cpp | 11 + rpcs3/Emu/NP/rpcn_client.h | 1 + rpcs3/Emu/NP/rpcn_types.h | 1 + 14 files changed, 1506 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/sceNp2.cpp b/rpcs3/Emu/Cell/Modules/sceNp2.cpp index fddc514bcc..c9816b60f5 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp2.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp2.cpp @@ -798,7 +798,7 @@ error_code sceNpMatching2JoinLobby( error_code sceNpMatching2GetRoomMemberDataExternalList(SceNpMatching2ContextId ctxId, vm::cptr reqParam, vm::cptr optParam, vm::ptr assignedReqId) { - sceNp2.todo("sceNpMatching2GetRoomMemberDataExternalList(ctxId=%d, reqParam=*0x%x, optParam=*0x%x, assignedReqId=*0x%x)", ctxId, reqParam, optParam, assignedReqId); + sceNp2.warning("sceNpMatching2GetRoomMemberDataExternalList(ctxId=%d, reqParam=*0x%x, optParam=*0x%x, assignedReqId=*0x%x)", ctxId, reqParam, optParam, assignedReqId); auto& nph = g_fxo->get>(); if (auto res = generic_match2_error_check(nph, ctxId, reqParam); res != CELL_OK) @@ -806,6 +806,13 @@ error_code sceNpMatching2GetRoomMemberDataExternalList(SceNpMatching2ContextId c return res; } + const u32 request_id = nph.get_room_member_data_external_list(ctxId, optParam, reqParam.get_ptr()); + + if (assignedReqId) + { + *assignedReqId = request_id; + } + return CELL_OK; } diff --git a/rpcs3/Emu/NP/generated/np2_structs.pb.cc b/rpcs3/Emu/NP/generated/np2_structs.pb.cc index 6416723f11..2a4c4f6241 100644 --- a/rpcs3/Emu/NP/generated/np2_structs.pb.cc +++ b/rpcs3/Emu/NP/generated/np2_structs.pb.cc @@ -1299,6 +1299,33 @@ struct RoomMessageInfoDefaultTypeInternal { PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 RoomMessageInfoDefaultTypeInternal _RoomMessageInfo_default_instance_; +inline constexpr RoomMemberDataExternal::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + userinfo_{nullptr}, + role_{nullptr}, + joindate_{::uint64_t{0u}} {} + +template +PROTOBUF_CONSTEXPR RoomMemberDataExternal::RoomMemberDataExternal(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::MessageLite(RoomMemberDataExternal_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::MessageLite(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct RoomMemberDataExternalDefaultTypeInternal { + PROTOBUF_CONSTEXPR RoomMemberDataExternalDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~RoomMemberDataExternalDefaultTypeInternal() {} + union { + RoomMemberDataExternal _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 RoomMemberDataExternalDefaultTypeInternal _RoomMemberDataExternal_default_instance_; + inline constexpr RoomGroupPasswordConfig::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept : _cached_size_{0}, @@ -2161,6 +2188,31 @@ struct IntSearchFilterDefaultTypeInternal { PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 IntSearchFilterDefaultTypeInternal _IntSearchFilter_default_instance_; +inline constexpr GetRoomMemberDataExternalListResponse::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + members_{} {} + +template +PROTOBUF_CONSTEXPR GetRoomMemberDataExternalListResponse::GetRoomMemberDataExternalListResponse(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::MessageLite(GetRoomMemberDataExternalListResponse_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::MessageLite(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct GetRoomMemberDataExternalListResponseDefaultTypeInternal { + PROTOBUF_CONSTEXPR GetRoomMemberDataExternalListResponseDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~GetRoomMemberDataExternalListResponseDefaultTypeInternal() {} + union { + GetRoomMemberDataExternalListResponse _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 GetRoomMemberDataExternalListResponseDefaultTypeInternal _GetRoomMemberDataExternalListResponse_default_instance_; + inline constexpr CreateJoinRoomRequest::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept : _cached_size_{0}, @@ -36071,6 +36123,635 @@ void MatchingSearchJoinRoomInfo::InternalSwap(MatchingSearchJoinRoomInfo* PROTOB swap(_impl_.room_, other->_impl_.room_); } +// =================================================================== + +class RoomMemberDataExternal::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(RoomMemberDataExternal, _impl_._has_bits_); +}; + +RoomMemberDataExternal::RoomMemberDataExternal(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::MessageLite(arena, RoomMemberDataExternal_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::MessageLite(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:np2_structs.RoomMemberDataExternal) +} +PROTOBUF_NDEBUG_INLINE RoomMemberDataExternal::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::np2_structs::RoomMemberDataExternal& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0} {} + +RoomMemberDataExternal::RoomMemberDataExternal( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const RoomMemberDataExternal& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::MessageLite(arena, RoomMemberDataExternal_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::MessageLite(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + RoomMemberDataExternal* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::std::string>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.userinfo_ = (CheckHasBit(cached_has_bits, 0x00000001U)) + ? ::google::protobuf::MessageLite::CopyConstruct(arena, *from._impl_.userinfo_) + : nullptr; + _impl_.role_ = (CheckHasBit(cached_has_bits, 0x00000002U)) + ? ::google::protobuf::MessageLite::CopyConstruct(arena, *from._impl_.role_) + : nullptr; + _impl_.joindate_ = from._impl_.joindate_; + + // @@protoc_insertion_point(copy_constructor:np2_structs.RoomMemberDataExternal) +} +PROTOBUF_NDEBUG_INLINE RoomMemberDataExternal::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void RoomMemberDataExternal::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, userinfo_), + 0, + offsetof(Impl_, joindate_) - + offsetof(Impl_, userinfo_) + + sizeof(Impl_::joindate_)); +} +RoomMemberDataExternal::~RoomMemberDataExternal() { + // @@protoc_insertion_point(destructor:np2_structs.RoomMemberDataExternal) + SharedDtor(*this); +} +inline void RoomMemberDataExternal::SharedDtor(MessageLite& self) { + RoomMemberDataExternal& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::std::string>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.userinfo_; + delete this_._impl_.role_; + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL RoomMemberDataExternal::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) RoomMemberDataExternal(arena); +} +constexpr auto RoomMemberDataExternal::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(RoomMemberDataExternal), + alignof(RoomMemberDataExternal)); +} +constexpr auto RoomMemberDataExternal::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataLite<35>{ + { + &_RoomMemberDataExternal_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &RoomMemberDataExternal::MergeImpl, + ::google::protobuf::MessageLite::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &RoomMemberDataExternal::SharedDtor, + ::google::protobuf::MessageLite::GetClearImpl(), &RoomMemberDataExternal::ByteSizeLong, + &RoomMemberDataExternal::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(RoomMemberDataExternal, _impl_._cached_size_), + true, + }, + "np2_structs.RoomMemberDataExternal", + }; +} + +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::google::protobuf::internal::ClassDataLite<35> RoomMemberDataExternal_class_data_ = + RoomMemberDataExternal::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +RoomMemberDataExternal::GetClassData() const { + return RoomMemberDataExternal_class_data_.base(); +} +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<2, 3, 2, 0, 2> +RoomMemberDataExternal::_table_ = { + { + PROTOBUF_FIELD_OFFSET(RoomMemberDataExternal, _impl_._has_bits_), + 0, // no _extensions_ + 3, 24, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967288, // skipmap + offsetof(decltype(_table_), field_entries), + 3, // num_field_entries + 2, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + RoomMemberDataExternal_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallbackLite, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::np2_structs::RoomMemberDataExternal>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // .np2_structs.UserInfo userInfo = 1; + {::_pbi::TcParser::FastMtS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(RoomMemberDataExternal, _impl_.userinfo_)}}, + // uint64 joinDate = 2; + {::_pbi::TcParser::FastV64S1, + {16, 2, 0, + PROTOBUF_FIELD_OFFSET(RoomMemberDataExternal, _impl_.joindate_)}}, + // .np2_structs.uint8 role = 3; + {::_pbi::TcParser::FastMtS1, + {26, 1, 1, + PROTOBUF_FIELD_OFFSET(RoomMemberDataExternal, _impl_.role_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .np2_structs.UserInfo userInfo = 1; + {PROTOBUF_FIELD_OFFSET(RoomMemberDataExternal, _impl_.userinfo_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // uint64 joinDate = 2; + {PROTOBUF_FIELD_OFFSET(RoomMemberDataExternal, _impl_.joindate_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + // .np2_structs.uint8 role = 3; + {PROTOBUF_FIELD_OFFSET(RoomMemberDataExternal, _impl_.role_), _Internal::kHasBitsOffset + 1, 1, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::np2_structs::UserInfo>()}, + {::_pbi::TcParser::GetTable<::np2_structs::uint8>()}, + }}, + {{ + }}, +}; +PROTOBUF_NOINLINE void RoomMemberDataExternal::Clear() { +// @@protoc_insertion_point(message_clear_start:np2_structs.RoomMemberDataExternal) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(_impl_.userinfo_ != nullptr); + _impl_.userinfo_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + ABSL_DCHECK(_impl_.role_ != nullptr); + _impl_.role_->Clear(); + } + } + _impl_.joindate_ = ::uint64_t{0u}; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::std::string>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL RoomMemberDataExternal::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const RoomMemberDataExternal& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL RoomMemberDataExternal::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const RoomMemberDataExternal& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:np2_structs.RoomMemberDataExternal) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // .np2_structs.UserInfo userInfo = 1; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, *this_._impl_.userinfo_, this_._impl_.userinfo_->GetCachedSize(), target, + stream); + } + + // uint64 joinDate = 2; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (this_._internal_joindate() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 2, this_._internal_joindate(), target); + } + } + + // .np2_structs.uint8 role = 3; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.role_, this_._impl_.role_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = stream->WriteRaw( + this_._internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString).data(), + static_cast(this_._internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString).size()), target); + } + // @@protoc_insertion_point(serialize_to_array_end:np2_structs.RoomMemberDataExternal) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t RoomMemberDataExternal::ByteSizeLong(const MessageLite& base) { + const RoomMemberDataExternal& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t RoomMemberDataExternal::ByteSizeLong() const { + const RoomMemberDataExternal& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:np2_structs.RoomMemberDataExternal) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000007U)) { + // .np2_structs.UserInfo userInfo = 1; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.userinfo_); + } + // .np2_structs.uint8 role = 3; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.role_); + } + // uint64 joinDate = 2; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (this_._internal_joindate() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_joindate()); + } + } + } + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + total_size += this_._internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString).size(); + } + this_._impl_._cached_size_.Set(::_pbi::ToCachedSize(total_size)); + return total_size; +} + +void RoomMemberDataExternal::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = + static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:np2_structs.RoomMemberDataExternal) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000007U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(from._impl_.userinfo_ != nullptr); + if (_this->_impl_.userinfo_ == nullptr) { + _this->_impl_.userinfo_ = ::google::protobuf::MessageLite::CopyConstruct(arena, *from._impl_.userinfo_); + } else { + _this->_impl_.userinfo_->MergeFrom(*from._impl_.userinfo_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + ABSL_DCHECK(from._impl_.role_ != nullptr); + if (_this->_impl_.role_ == nullptr) { + _this->_impl_.role_ = ::google::protobuf::MessageLite::CopyConstruct(arena, *from._impl_.role_); + } else { + _this->_impl_.role_->MergeFrom(*from._impl_.role_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (from._internal_joindate() != 0) { + _this->_impl_.joindate_ = from._impl_.joindate_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::std::string>( + from._internal_metadata_); +} + +void RoomMemberDataExternal::CopyFrom(const RoomMemberDataExternal& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:np2_structs.RoomMemberDataExternal) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void RoomMemberDataExternal::InternalSwap(RoomMemberDataExternal* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(RoomMemberDataExternal, _impl_.joindate_) + + sizeof(RoomMemberDataExternal::_impl_.joindate_) + - PROTOBUF_FIELD_OFFSET(RoomMemberDataExternal, _impl_.userinfo_)>( + reinterpret_cast(&_impl_.userinfo_), + reinterpret_cast(&other->_impl_.userinfo_)); +} + +// =================================================================== + +class GetRoomMemberDataExternalListResponse::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(GetRoomMemberDataExternalListResponse, _impl_._has_bits_); +}; + +GetRoomMemberDataExternalListResponse::GetRoomMemberDataExternalListResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::MessageLite(arena, GetRoomMemberDataExternalListResponse_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::MessageLite(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:np2_structs.GetRoomMemberDataExternalListResponse) +} +PROTOBUF_NDEBUG_INLINE GetRoomMemberDataExternalListResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::np2_structs::GetRoomMemberDataExternalListResponse& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + members_{visibility, arena, from.members_} {} + +GetRoomMemberDataExternalListResponse::GetRoomMemberDataExternalListResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const GetRoomMemberDataExternalListResponse& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::MessageLite(arena, GetRoomMemberDataExternalListResponse_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::MessageLite(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + GetRoomMemberDataExternalListResponse* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::std::string>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + + // @@protoc_insertion_point(copy_constructor:np2_structs.GetRoomMemberDataExternalListResponse) +} +PROTOBUF_NDEBUG_INLINE GetRoomMemberDataExternalListResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0}, + members_{visibility, arena} {} + +inline void GetRoomMemberDataExternalListResponse::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +GetRoomMemberDataExternalListResponse::~GetRoomMemberDataExternalListResponse() { + // @@protoc_insertion_point(destructor:np2_structs.GetRoomMemberDataExternalListResponse) + SharedDtor(*this); +} +inline void GetRoomMemberDataExternalListResponse::SharedDtor(MessageLite& self) { + GetRoomMemberDataExternalListResponse& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::std::string>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL GetRoomMemberDataExternalListResponse::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) GetRoomMemberDataExternalListResponse(arena); +} +constexpr auto GetRoomMemberDataExternalListResponse::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(GetRoomMemberDataExternalListResponse, _impl_.members_) + + decltype(GetRoomMemberDataExternalListResponse::_impl_.members_):: + InternalGetArenaOffset( + ::google::protobuf::MessageLite::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(GetRoomMemberDataExternalListResponse), alignof(GetRoomMemberDataExternalListResponse), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&GetRoomMemberDataExternalListResponse::PlacementNew_, + sizeof(GetRoomMemberDataExternalListResponse), + alignof(GetRoomMemberDataExternalListResponse)); + } +} +constexpr auto GetRoomMemberDataExternalListResponse::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataLite<50>{ + { + &_GetRoomMemberDataExternalListResponse_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &GetRoomMemberDataExternalListResponse::MergeImpl, + ::google::protobuf::MessageLite::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &GetRoomMemberDataExternalListResponse::SharedDtor, + ::google::protobuf::MessageLite::GetClearImpl(), &GetRoomMemberDataExternalListResponse::ByteSizeLong, + &GetRoomMemberDataExternalListResponse::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(GetRoomMemberDataExternalListResponse, _impl_._cached_size_), + true, + }, + "np2_structs.GetRoomMemberDataExternalListResponse", + }; +} + +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::google::protobuf::internal::ClassDataLite<50> GetRoomMemberDataExternalListResponse_class_data_ = + GetRoomMemberDataExternalListResponse::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +GetRoomMemberDataExternalListResponse::GetClassData() const { + return GetRoomMemberDataExternalListResponse_class_data_.base(); +} +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 1, 0, 2> +GetRoomMemberDataExternalListResponse::_table_ = { + { + PROTOBUF_FIELD_OFFSET(GetRoomMemberDataExternalListResponse, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 1, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + GetRoomMemberDataExternalListResponse_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallbackLite, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::np2_structs::GetRoomMemberDataExternalListResponse>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // repeated .np2_structs.RoomMemberDataExternal members = 1; + {::_pbi::TcParser::FastMtR1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(GetRoomMemberDataExternalListResponse, _impl_.members_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // repeated .np2_structs.RoomMemberDataExternal members = 1; + {PROTOBUF_FIELD_OFFSET(GetRoomMemberDataExternalListResponse, _impl_.members_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::np2_structs::RoomMemberDataExternal>()}, + }}, + {{ + }}, +}; +PROTOBUF_NOINLINE void GetRoomMemberDataExternalListResponse::Clear() { +// @@protoc_insertion_point(message_clear_start:np2_structs.GetRoomMemberDataExternalListResponse) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (CheckHasBitForRepeated(cached_has_bits, 0x00000001U)) { + _impl_.members_.Clear(); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::std::string>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL GetRoomMemberDataExternalListResponse::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const GetRoomMemberDataExternalListResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL GetRoomMemberDataExternalListResponse::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const GetRoomMemberDataExternalListResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:np2_structs.GetRoomMemberDataExternalListResponse) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // repeated .np2_structs.RoomMemberDataExternal members = 1; + if (CheckHasBitForRepeated(cached_has_bits, 0x00000001U)) { + for (unsigned i = 0, n = static_cast( + this_._internal_members_size()); + i < n; i++) { + const auto& repfield = this_._internal_members().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, repfield, repfield.GetCachedSize(), + target, stream); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = stream->WriteRaw( + this_._internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString).data(), + static_cast(this_._internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString).size()), target); + } + // @@protoc_insertion_point(serialize_to_array_end:np2_structs.GetRoomMemberDataExternalListResponse) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t GetRoomMemberDataExternalListResponse::ByteSizeLong(const MessageLite& base) { + const GetRoomMemberDataExternalListResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t GetRoomMemberDataExternalListResponse::ByteSizeLong() const { + const GetRoomMemberDataExternalListResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:np2_structs.GetRoomMemberDataExternalListResponse) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .np2_structs.RoomMemberDataExternal members = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBitForRepeated(cached_has_bits, 0x00000001U)) { + total_size += 1UL * this_._internal_members_size(); + for (const auto& msg : this_._internal_members()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + total_size += this_._internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString).size(); + } + this_._impl_._cached_size_.Set(::_pbi::ToCachedSize(total_size)); + return total_size; +} + +void GetRoomMemberDataExternalListResponse::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = + static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:np2_structs.GetRoomMemberDataExternalListResponse) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (CheckHasBitForRepeated(cached_has_bits, 0x00000001U)) { + _this->_internal_mutable_members()->InternalMergeFromWithArena( + ::google::protobuf::MessageLite::internal_visibility(), arena, + from._internal_members()); + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::std::string>( + from._internal_metadata_); +} + +void GetRoomMemberDataExternalListResponse::CopyFrom(const GetRoomMemberDataExternalListResponse& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:np2_structs.GetRoomMemberDataExternalListResponse) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void GetRoomMemberDataExternalListResponse::InternalSwap(GetRoomMemberDataExternalListResponse* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.members_.InternalSwap(&other->_impl_.members_); +} + // @@protoc_insertion_point(namespace_scope) } // namespace np2_structs namespace google { diff --git a/rpcs3/Emu/NP/generated/np2_structs.pb.h b/rpcs3/Emu/NP/generated/np2_structs.pb.h index 0e035973fd..4e435b3b07 100644 --- a/rpcs3/Emu/NP/generated/np2_structs.pb.h +++ b/rpcs3/Emu/NP/generated/np2_structs.pb.h @@ -99,6 +99,10 @@ class GetRoomListGUIRequest; struct GetRoomListGUIRequestDefaultTypeInternal; extern GetRoomListGUIRequestDefaultTypeInternal _GetRoomListGUIRequest_default_instance_; extern const ::google::protobuf::internal::ClassDataLite<34> GetRoomListGUIRequest_class_data_; +class GetRoomMemberDataExternalListResponse; +struct GetRoomMemberDataExternalListResponseDefaultTypeInternal; +extern GetRoomMemberDataExternalListResponseDefaultTypeInternal _GetRoomMemberDataExternalListResponse_default_instance_; +extern const ::google::protobuf::internal::ClassDataLite<50> GetRoomMemberDataExternalListResponse_class_data_; class GetRoomMemberDataInternalRequest; struct GetRoomMemberDataInternalRequestDefaultTypeInternal; extern GetRoomMemberDataInternalRequestDefaultTypeInternal _GetRoomMemberDataInternalRequest_default_instance_; @@ -235,6 +239,10 @@ class RoomMemberBinAttrInternal; struct RoomMemberBinAttrInternalDefaultTypeInternal; extern RoomMemberBinAttrInternalDefaultTypeInternal _RoomMemberBinAttrInternal_default_instance_; extern const ::google::protobuf::internal::ClassDataLite<38> RoomMemberBinAttrInternal_class_data_; +class RoomMemberDataExternal; +struct RoomMemberDataExternalDefaultTypeInternal; +extern RoomMemberDataExternalDefaultTypeInternal _RoomMemberDataExternal_default_instance_; +extern const ::google::protobuf::internal::ClassDataLite<35> RoomMemberDataExternal_class_data_; class RoomMemberDataInternal; struct RoomMemberDataInternalDefaultTypeInternal; extern RoomMemberDataInternalDefaultTypeInternal _RoomMemberDataInternal_default_instance_; @@ -9818,6 +9826,218 @@ class RoomMessageInfo final : public ::google::protobuf::MessageLite extern const ::google::protobuf::internal::ClassDataLite<28> RoomMessageInfo_class_data_; // ------------------------------------------------------------------- +class RoomMemberDataExternal final : public ::google::protobuf::MessageLite +/* @@protoc_insertion_point(class_definition:np2_structs.RoomMemberDataExternal) */ { + public: + inline RoomMemberDataExternal() : RoomMemberDataExternal(nullptr) {} + ~RoomMemberDataExternal() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(RoomMemberDataExternal* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(RoomMemberDataExternal)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR RoomMemberDataExternal(::google::protobuf::internal::ConstantInitialized); + + inline RoomMemberDataExternal(const RoomMemberDataExternal& from) : RoomMemberDataExternal(nullptr, from) {} + inline RoomMemberDataExternal(RoomMemberDataExternal&& from) noexcept + : RoomMemberDataExternal(nullptr, ::std::move(from)) {} + inline RoomMemberDataExternal& operator=(const RoomMemberDataExternal& from) { + CopyFrom(from); + return *this; + } + inline RoomMemberDataExternal& operator=(RoomMemberDataExternal&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::std::string& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString); + } + inline ::std::string* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::std::string>(); + } + + static const RoomMemberDataExternal& default_instance() { + return *reinterpret_cast( + &_RoomMemberDataExternal_default_instance_); + } + static constexpr int kIndexInFileMessages = 89; + friend void swap(RoomMemberDataExternal& a, RoomMemberDataExternal& b) { a.Swap(&b); } + inline void Swap(RoomMemberDataExternal* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(RoomMemberDataExternal* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + RoomMemberDataExternal* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::MessageLite::DefaultConstruct(arena); + } + void CopyFrom(const RoomMemberDataExternal& from); + void MergeFrom(const RoomMemberDataExternal& from) { RoomMemberDataExternal::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(RoomMemberDataExternal* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "np2_structs.RoomMemberDataExternal"; } + + explicit RoomMemberDataExternal(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + RoomMemberDataExternal(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const RoomMemberDataExternal& from); + RoomMemberDataExternal( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, RoomMemberDataExternal&& from) noexcept + : RoomMemberDataExternal(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kUserInfoFieldNumber = 1, + kRoleFieldNumber = 3, + kJoinDateFieldNumber = 2, + }; + // .np2_structs.UserInfo userInfo = 1; + bool has_userinfo() const; + void clear_userinfo() ; + const ::np2_structs::UserInfo& userinfo() const; + [[nodiscard]] ::np2_structs::UserInfo* PROTOBUF_NULLABLE release_userinfo(); + ::np2_structs::UserInfo* PROTOBUF_NONNULL mutable_userinfo(); + void set_allocated_userinfo(::np2_structs::UserInfo* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_userinfo(::np2_structs::UserInfo* PROTOBUF_NULLABLE value); + ::np2_structs::UserInfo* PROTOBUF_NULLABLE unsafe_arena_release_userinfo(); + + private: + const ::np2_structs::UserInfo& _internal_userinfo() const; + ::np2_structs::UserInfo* PROTOBUF_NONNULL _internal_mutable_userinfo(); + + public: + // .np2_structs.uint8 role = 3; + bool has_role() const; + void clear_role() ; + const ::np2_structs::uint8& role() const; + [[nodiscard]] ::np2_structs::uint8* PROTOBUF_NULLABLE release_role(); + ::np2_structs::uint8* PROTOBUF_NONNULL mutable_role(); + void set_allocated_role(::np2_structs::uint8* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_role(::np2_structs::uint8* PROTOBUF_NULLABLE value); + ::np2_structs::uint8* PROTOBUF_NULLABLE unsafe_arena_release_role(); + + private: + const ::np2_structs::uint8& _internal_role() const; + ::np2_structs::uint8* PROTOBUF_NONNULL _internal_mutable_role(); + + public: + // uint64 joinDate = 2; + void clear_joindate() ; + ::uint64_t joindate() const; + void set_joindate(::uint64_t value); + + private: + ::uint64_t _internal_joindate() const; + void _internal_set_joindate(::uint64_t value); + + public: + // @@protoc_insertion_point(class_scope:np2_structs.RoomMemberDataExternal) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<2, 3, + 2, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const RoomMemberDataExternal& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::np2_structs::UserInfo* PROTOBUF_NULLABLE userinfo_; + ::np2_structs::uint8* PROTOBUF_NULLABLE role_; + ::uint64_t joindate_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_np2_5fstructs_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataLite<35> RoomMemberDataExternal_class_data_; +// ------------------------------------------------------------------- + class RoomGroupPasswordConfig final : public ::google::protobuf::MessageLite /* @@protoc_insertion_point(class_definition:np2_structs.RoomGroupPasswordConfig) */ { public: @@ -16603,6 +16823,191 @@ class IntSearchFilter final : public ::google::protobuf::MessageLite extern const ::google::protobuf::internal::ClassDataLite<28> IntSearchFilter_class_data_; // ------------------------------------------------------------------- +class GetRoomMemberDataExternalListResponse final : public ::google::protobuf::MessageLite +/* @@protoc_insertion_point(class_definition:np2_structs.GetRoomMemberDataExternalListResponse) */ { + public: + inline GetRoomMemberDataExternalListResponse() : GetRoomMemberDataExternalListResponse(nullptr) {} + ~GetRoomMemberDataExternalListResponse() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(GetRoomMemberDataExternalListResponse* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(GetRoomMemberDataExternalListResponse)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR GetRoomMemberDataExternalListResponse(::google::protobuf::internal::ConstantInitialized); + + inline GetRoomMemberDataExternalListResponse(const GetRoomMemberDataExternalListResponse& from) : GetRoomMemberDataExternalListResponse(nullptr, from) {} + inline GetRoomMemberDataExternalListResponse(GetRoomMemberDataExternalListResponse&& from) noexcept + : GetRoomMemberDataExternalListResponse(nullptr, ::std::move(from)) {} + inline GetRoomMemberDataExternalListResponse& operator=(const GetRoomMemberDataExternalListResponse& from) { + CopyFrom(from); + return *this; + } + inline GetRoomMemberDataExternalListResponse& operator=(GetRoomMemberDataExternalListResponse&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::std::string& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString); + } + inline ::std::string* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::std::string>(); + } + + static const GetRoomMemberDataExternalListResponse& default_instance() { + return *reinterpret_cast( + &_GetRoomMemberDataExternalListResponse_default_instance_); + } + static constexpr int kIndexInFileMessages = 90; + friend void swap(GetRoomMemberDataExternalListResponse& a, GetRoomMemberDataExternalListResponse& b) { a.Swap(&b); } + inline void Swap(GetRoomMemberDataExternalListResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(GetRoomMemberDataExternalListResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + GetRoomMemberDataExternalListResponse* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::MessageLite::DefaultConstruct(arena); + } + void CopyFrom(const GetRoomMemberDataExternalListResponse& from); + void MergeFrom(const GetRoomMemberDataExternalListResponse& from) { GetRoomMemberDataExternalListResponse::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(GetRoomMemberDataExternalListResponse* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "np2_structs.GetRoomMemberDataExternalListResponse"; } + + explicit GetRoomMemberDataExternalListResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + GetRoomMemberDataExternalListResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const GetRoomMemberDataExternalListResponse& from); + GetRoomMemberDataExternalListResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, GetRoomMemberDataExternalListResponse&& from) noexcept + : GetRoomMemberDataExternalListResponse(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kMembersFieldNumber = 1, + }; + // repeated .np2_structs.RoomMemberDataExternal members = 1; + int members_size() const; + private: + int _internal_members_size() const; + + public: + void clear_members() ; + ::np2_structs::RoomMemberDataExternal* PROTOBUF_NONNULL mutable_members(int index); + ::google::protobuf::RepeatedPtrField<::np2_structs::RoomMemberDataExternal>* PROTOBUF_NONNULL mutable_members(); + + private: + const ::google::protobuf::RepeatedPtrField<::np2_structs::RoomMemberDataExternal>& _internal_members() const; + ::google::protobuf::RepeatedPtrField<::np2_structs::RoomMemberDataExternal>* PROTOBUF_NONNULL _internal_mutable_members(); + public: + const ::np2_structs::RoomMemberDataExternal& members(int index) const; + ::np2_structs::RoomMemberDataExternal* PROTOBUF_NONNULL add_members(); + const ::google::protobuf::RepeatedPtrField<::np2_structs::RoomMemberDataExternal>& members() const; + // @@protoc_insertion_point(class_scope:np2_structs.GetRoomMemberDataExternalListResponse) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 1, + 1, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const GetRoomMemberDataExternalListResponse& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedPtrField< ::np2_structs::RoomMemberDataExternal > members_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_np2_5fstructs_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataLite<50> GetRoomMemberDataExternalListResponse_class_data_; +// ------------------------------------------------------------------- + class CreateJoinRoomRequest final : public ::google::protobuf::MessageLite /* @@protoc_insertion_point(class_definition:np2_structs.CreateJoinRoomRequest) */ { public: @@ -38603,6 +39008,293 @@ MatchingSearchJoinRoomInfo::_internal_mutable_attr() { return &_impl_.attr_; } +// ------------------------------------------------------------------- + +// RoomMemberDataExternal + +// .np2_structs.UserInfo userInfo = 1; +inline bool RoomMemberDataExternal::has_userinfo() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000001U); + PROTOBUF_ASSUME(!value || _impl_.userinfo_ != nullptr); + return value; +} +inline void RoomMemberDataExternal::clear_userinfo() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.userinfo_ != nullptr) _impl_.userinfo_->Clear(); + ClearHasBit(_impl_._has_bits_[0], + 0x00000001U); +} +inline const ::np2_structs::UserInfo& RoomMemberDataExternal::_internal_userinfo() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::np2_structs::UserInfo* p = _impl_.userinfo_; + return p != nullptr ? *p : reinterpret_cast(::np2_structs::_UserInfo_default_instance_); +} +inline const ::np2_structs::UserInfo& RoomMemberDataExternal::userinfo() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:np2_structs.RoomMemberDataExternal.userInfo) + return _internal_userinfo(); +} +inline void RoomMemberDataExternal::unsafe_arena_set_allocated_userinfo( + ::np2_structs::UserInfo* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.userinfo_); + } + _impl_.userinfo_ = reinterpret_cast<::np2_structs::UserInfo*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:np2_structs.RoomMemberDataExternal.userInfo) +} +inline ::np2_structs::UserInfo* PROTOBUF_NULLABLE RoomMemberDataExternal::release_userinfo() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::np2_structs::UserInfo* released = _impl_.userinfo_; + _impl_.userinfo_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::np2_structs::UserInfo* PROTOBUF_NULLABLE RoomMemberDataExternal::unsafe_arena_release_userinfo() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:np2_structs.RoomMemberDataExternal.userInfo) + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::np2_structs::UserInfo* temp = _impl_.userinfo_; + _impl_.userinfo_ = nullptr; + return temp; +} +inline ::np2_structs::UserInfo* PROTOBUF_NONNULL RoomMemberDataExternal::_internal_mutable_userinfo() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.userinfo_ == nullptr) { + auto* p = ::google::protobuf::MessageLite::DefaultConstruct<::np2_structs::UserInfo>(GetArena()); + _impl_.userinfo_ = reinterpret_cast<::np2_structs::UserInfo*>(p); + } + return _impl_.userinfo_; +} +inline ::np2_structs::UserInfo* PROTOBUF_NONNULL RoomMemberDataExternal::mutable_userinfo() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::np2_structs::UserInfo* _msg = _internal_mutable_userinfo(); + // @@protoc_insertion_point(field_mutable:np2_structs.RoomMemberDataExternal.userInfo) + return _msg; +} +inline void RoomMemberDataExternal::set_allocated_userinfo(::np2_structs::UserInfo* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.userinfo_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + + _impl_.userinfo_ = reinterpret_cast<::np2_structs::UserInfo*>(value); + // @@protoc_insertion_point(field_set_allocated:np2_structs.RoomMemberDataExternal.userInfo) +} + +// uint64 joinDate = 2; +inline void RoomMemberDataExternal::clear_joindate() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.joindate_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], + 0x00000004U); +} +inline ::uint64_t RoomMemberDataExternal::joindate() const { + // @@protoc_insertion_point(field_get:np2_structs.RoomMemberDataExternal.joinDate) + return _internal_joindate(); +} +inline void RoomMemberDataExternal::set_joindate(::uint64_t value) { + _internal_set_joindate(value); + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + // @@protoc_insertion_point(field_set:np2_structs.RoomMemberDataExternal.joinDate) +} +inline ::uint64_t RoomMemberDataExternal::_internal_joindate() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.joindate_; +} +inline void RoomMemberDataExternal::_internal_set_joindate(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.joindate_ = value; +} + +// .np2_structs.uint8 role = 3; +inline bool RoomMemberDataExternal::has_role() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000002U); + PROTOBUF_ASSUME(!value || _impl_.role_ != nullptr); + return value; +} +inline void RoomMemberDataExternal::clear_role() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.role_ != nullptr) _impl_.role_->Clear(); + ClearHasBit(_impl_._has_bits_[0], + 0x00000002U); +} +inline const ::np2_structs::uint8& RoomMemberDataExternal::_internal_role() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::np2_structs::uint8* p = _impl_.role_; + return p != nullptr ? *p : reinterpret_cast(::np2_structs::_uint8_default_instance_); +} +inline const ::np2_structs::uint8& RoomMemberDataExternal::role() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:np2_structs.RoomMemberDataExternal.role) + return _internal_role(); +} +inline void RoomMemberDataExternal::unsafe_arena_set_allocated_role( + ::np2_structs::uint8* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.role_); + } + _impl_.role_ = reinterpret_cast<::np2_structs::uint8*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:np2_structs.RoomMemberDataExternal.role) +} +inline ::np2_structs::uint8* PROTOBUF_NULLABLE RoomMemberDataExternal::release_role() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + ::np2_structs::uint8* released = _impl_.role_; + _impl_.role_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::np2_structs::uint8* PROTOBUF_NULLABLE RoomMemberDataExternal::unsafe_arena_release_role() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:np2_structs.RoomMemberDataExternal.role) + + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + ::np2_structs::uint8* temp = _impl_.role_; + _impl_.role_ = nullptr; + return temp; +} +inline ::np2_structs::uint8* PROTOBUF_NONNULL RoomMemberDataExternal::_internal_mutable_role() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.role_ == nullptr) { + auto* p = ::google::protobuf::MessageLite::DefaultConstruct<::np2_structs::uint8>(GetArena()); + _impl_.role_ = reinterpret_cast<::np2_structs::uint8*>(p); + } + return _impl_.role_; +} +inline ::np2_structs::uint8* PROTOBUF_NONNULL RoomMemberDataExternal::mutable_role() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::np2_structs::uint8* _msg = _internal_mutable_role(); + // @@protoc_insertion_point(field_mutable:np2_structs.RoomMemberDataExternal.role) + return _msg; +} +inline void RoomMemberDataExternal::set_allocated_role(::np2_structs::uint8* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.role_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + + _impl_.role_ = reinterpret_cast<::np2_structs::uint8*>(value); + // @@protoc_insertion_point(field_set_allocated:np2_structs.RoomMemberDataExternal.role) +} + +// ------------------------------------------------------------------- + +// GetRoomMemberDataExternalListResponse + +// repeated .np2_structs.RoomMemberDataExternal members = 1; +inline int GetRoomMemberDataExternalListResponse::_internal_members_size() const { + return _internal_members().size(); +} +inline int GetRoomMemberDataExternalListResponse::members_size() const { + return _internal_members_size(); +} +inline void GetRoomMemberDataExternalListResponse::clear_members() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.members_.Clear(); + ClearHasBitForRepeated(_impl_._has_bits_[0], + 0x00000001U); +} +inline ::np2_structs::RoomMemberDataExternal* PROTOBUF_NONNULL GetRoomMemberDataExternalListResponse::mutable_members(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:np2_structs.GetRoomMemberDataExternalListResponse.members) + return _internal_mutable_members()->Mutable(index); +} +inline ::google::protobuf::RepeatedPtrField<::np2_structs::RoomMemberDataExternal>* PROTOBUF_NONNULL GetRoomMemberDataExternalListResponse::mutable_members() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBitForRepeated(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_mutable_list:np2_structs.GetRoomMemberDataExternalListResponse.members) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_members(); +} +inline const ::np2_structs::RoomMemberDataExternal& GetRoomMemberDataExternalListResponse::members(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:np2_structs.GetRoomMemberDataExternalListResponse.members) + return _internal_members().Get(index); +} +inline ::np2_structs::RoomMemberDataExternal* PROTOBUF_NONNULL GetRoomMemberDataExternalListResponse::add_members() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::np2_structs::RoomMemberDataExternal* _add = + _internal_mutable_members()->InternalAddWithArena( + ::google::protobuf::MessageLite::internal_visibility(), GetArena()); + SetHasBitForRepeated(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_add:np2_structs.GetRoomMemberDataExternalListResponse.members) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::np2_structs::RoomMemberDataExternal>& GetRoomMemberDataExternalListResponse::members() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:np2_structs.GetRoomMemberDataExternalListResponse.members) + return _internal_members(); +} +inline const ::google::protobuf::RepeatedPtrField<::np2_structs::RoomMemberDataExternal>& +GetRoomMemberDataExternalListResponse::_internal_members() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.members_; +} +inline ::google::protobuf::RepeatedPtrField<::np2_structs::RoomMemberDataExternal>* PROTOBUF_NONNULL +GetRoomMemberDataExternalListResponse::_internal_mutable_members() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.members_; +} + #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ diff --git a/rpcs3/Emu/NP/generated/np2_structs.proto b/rpcs3/Emu/NP/generated/np2_structs.proto index 46628781fb..fcb5c7304e 100644 --- a/rpcs3/Emu/NP/generated/np2_structs.proto +++ b/rpcs3/Emu/NP/generated/np2_structs.proto @@ -606,3 +606,14 @@ message MatchingSearchJoinRoomInfo { MatchingRoomStatus room = 1; repeated MatchingAttr attr = 2; } + +message RoomMemberDataExternal { + UserInfo userInfo = 1; + uint64 joinDate = 2; + uint8 role = 3; +} + +message GetRoomMemberDataExternalListResponse +{ + repeated RoomMemberDataExternal members = 1; +} diff --git a/rpcs3/Emu/NP/np_handler.cpp b/rpcs3/Emu/NP/np_handler.cpp index bc65f545b3..c4db3350c0 100644 --- a/rpcs3/Emu/NP/np_handler.cpp +++ b/rpcs3/Emu/NP/np_handler.cpp @@ -1127,6 +1127,7 @@ namespace np case rpcn::CommandType::LeaveRoom: reply_leave_room(req_id, error, reply_data); break; case rpcn::CommandType::SearchRoom: reply_search_room(req_id, error, reply_data); break; case rpcn::CommandType::GetRoomDataExternalList: reply_get_roomdata_external_list(req_id, error, reply_data); break; + case rpcn::CommandType::GetRoomMemberDataExternalList: reply_get_room_member_data_external_list(req_id, error, reply_data); break; case rpcn::CommandType::SetRoomDataExternal: reply_set_roomdata_external(req_id, error); break; case rpcn::CommandType::GetRoomDataInternal: reply_get_roomdata_internal(req_id, error, reply_data); break; case rpcn::CommandType::SetRoomDataInternal: reply_set_roomdata_internal(req_id, error); break; diff --git a/rpcs3/Emu/NP/np_handler.h b/rpcs3/Emu/NP/np_handler.h index 51d510b854..9c02007a9c 100644 --- a/rpcs3/Emu/NP/np_handler.h +++ b/rpcs3/Emu/NP/np_handler.h @@ -177,6 +177,7 @@ namespace np u32 leave_room(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2LeaveRoomRequest* req); u32 search_room(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SearchRoomRequest* req); u32 get_roomdata_external_list(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2GetRoomDataExternalListRequest* req); + u32 get_room_member_data_external_list(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2GetRoomMemberDataExternalListRequest* req); u32 set_roomdata_external(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SetRoomDataExternalRequest* req); u32 get_roomdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2GetRoomDataInternalRequest* req); u32 set_roomdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SetRoomDataInternalRequest* req); @@ -323,6 +324,7 @@ namespace np void reply_leave_room(u32 req_id, rpcn::ErrorType error, vec_stream& reply); void reply_search_room(u32 req_id, rpcn::ErrorType error, vec_stream& reply); void reply_get_roomdata_external_list(u32 req_id, rpcn::ErrorType error, vec_stream& reply); + void reply_get_room_member_data_external_list(u32 req_id, rpcn::ErrorType error, vec_stream& reply); void reply_set_roomdata_external(u32 req_id, rpcn::ErrorType error); void reply_get_roomdata_internal(u32 req_id, rpcn::ErrorType error, vec_stream& reply); void reply_set_roomdata_internal(u32 req_id, rpcn::ErrorType error); diff --git a/rpcs3/Emu/NP/np_requests.cpp b/rpcs3/Emu/NP/np_requests.cpp index 0ee7d1d0fc..20199889dc 100644 --- a/rpcs3/Emu/NP/np_requests.cpp +++ b/rpcs3/Emu/NP/np_requests.cpp @@ -445,6 +445,50 @@ namespace np cb_info_opt->queue_callback(req_id, event_key, 0, edata.size()); } + u32 np_handler::get_room_member_data_external_list(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2GetRoomMemberDataExternalListRequest* req) + { + const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataExternalList, true); + + if (!get_rpcn()->get_room_member_data_external_list(req_id, get_match2_context(ctx_id)->communicationId, req->roomId)) + { + rpcn_log.error("Disconnecting from RPCN!"); + is_psn_active = false; + } + + return req_id; + } + + void np_handler::reply_get_room_member_data_external_list(u32 req_id, rpcn::ErrorType error, vec_stream& reply) + { + auto cb_info_opt = take_pending_request(req_id); + + if (!cb_info_opt) + return; + + ensure(error == rpcn::ErrorType::NoError, "Unexpected error in GetRoomMemberDataExternalList reply"); + + if (error == rpcn::ErrorType::RoomMissing) + { + cb_info_opt->queue_callback(req_id, 0, SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM, 0); + return; + } + + const auto resp = reply.get_protobuf(); + ensure(!reply.is_error(), "Malformed reply to GetRoomMemberDataExternalList command"); + + const u32 event_key = get_event_key(); + auto [include_onlinename, include_avatarurl] = get_match2_context_options(cb_info_opt->ctx_id); + + auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_GetRoomMemberDataExternalList, sizeof(SceNpMatching2GetRoomMemberDataExternalListResponse)); + auto* sce_get_room_member_ext_resp = reinterpret_cast(edata.data()); + GetRoomMemberDataExternalListResponse_to_SceNpMatching2GetRoomMemberDataExternalListResponse(edata, *resp, sce_get_room_member_ext_resp, include_onlinename, include_avatarurl); + np_memory.shrink_allocation(edata.addr(), edata.size()); + + extra_nps::print_SceNpMatching2GetRoomMemberDataExternalListResponse(sce_get_room_member_ext_resp); + + cb_info_opt->queue_callback(req_id, event_key, 0, edata.size()); + } + u32 np_handler::set_roomdata_external(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SetRoomDataExternalRequest* req) { const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataExternal, false); diff --git a/rpcs3/Emu/NP/np_structs_extra.cpp b/rpcs3/Emu/NP/np_structs_extra.cpp index 52f394ff2e..58770c450f 100644 --- a/rpcs3/Emu/NP/np_structs_extra.cpp +++ b/rpcs3/Emu/NP/np_structs_extra.cpp @@ -195,6 +195,15 @@ namespace extra_nps } } + void print_SceNpMatching2RoomMemberDataExternal(const SceNpMatching2RoomMemberDataExternal* member) + { + sceNp2.warning("SceNpMatching2RoomMemberDataExternal:"); + sceNp2.warning("next: *0x%x", member->next); + print_SceNpUserInfo2(&member->userInfo); + sceNp2.warning("joinDate: %lld", member->joinDate.tick); + sceNp2.warning("role: %d", member->role); + } + void print_SceNpMatching2RoomMemberDataInternal(const SceNpMatching2RoomMemberDataInternal* member) { sceNp2.warning("SceNpMatching2RoomMemberDataInternal:"); @@ -397,6 +406,21 @@ namespace extra_nps } } + void print_SceNpMatching2GetRoomMemberDataExternalListResponse(const SceNpMatching2GetRoomMemberDataExternalListResponse* resp) + { + sceNp2.warning("SceNpMatching2GetRoomMemberDataExternalListResponse:"); + sceNp2.warning("roomMemberDataExternalNum: %d", resp->roomMemberDataExternalNum); + + vm::bptr cur_member = resp->roomMemberDataExternal; + + for (u32 i = 0; i < resp->roomMemberDataExternalNum && cur_member; i++) + { + sceNp2.warning("roomMemberDataExternal[%d]:", i); + print_SceNpMatching2RoomMemberDataExternal(cur_member.get_ptr()); + cur_member = cur_member->next; + } + } + void print_SceNpMatching2GetLobbyInfoListRequest(const SceNpMatching2GetLobbyInfoListRequest* resp) { sceNp2.warning("SceNpMatching2GetLobbyInfoListRequest:"); diff --git a/rpcs3/Emu/NP/np_structs_extra.h b/rpcs3/Emu/NP/np_structs_extra.h index 1c722a0cf2..45f4cffc4a 100644 --- a/rpcs3/Emu/NP/np_structs_extra.h +++ b/rpcs3/Emu/NP/np_structs_extra.h @@ -11,6 +11,7 @@ namespace extra_nps void print_SceNpMatching2RangeFilter(const SceNpMatching2RangeFilter* filt); void print_SceNpMatching2RoomDataInternal(const SceNpMatching2RoomDataInternal* room); void print_SceNpMatching2RoomDataExternal(const SceNpMatching2RoomDataExternal* room); + void print_SceNpMatching2RoomMemberDataExternal(const SceNpMatching2RoomMemberDataExternal* room); void print_SceNpMatching2RoomMemberDataInternal(const SceNpMatching2RoomMemberDataInternal* member); void print_SceNpMatching2CreateJoinRoomRequest(const SceNpMatching2CreateJoinRoomRequest* req); @@ -24,6 +25,7 @@ namespace extra_nps void print_SceNpMatching2SetRoomMemberDataInternalRequest(const SceNpMatching2SetRoomMemberDataInternalRequest* req); void print_SceNpMatching2GetRoomDataExternalListRequest(const SceNpMatching2GetRoomDataExternalListRequest* req); void print_SceNpMatching2GetRoomDataExternalListResponse(const SceNpMatching2GetRoomDataExternalListResponse* resp); + void print_SceNpMatching2GetRoomMemberDataExternalListResponse(const SceNpMatching2GetRoomMemberDataExternalListResponse* resp); void print_SceNpMatching2GetLobbyInfoListRequest(const SceNpMatching2GetLobbyInfoListRequest* resp); diff --git a/rpcs3/Emu/NP/pb_helpers.cpp b/rpcs3/Emu/NP/pb_helpers.cpp index e82fc2ec0a..41b0ca4579 100644 --- a/rpcs3/Emu/NP/pb_helpers.cpp +++ b/rpcs3/Emu/NP/pb_helpers.cpp @@ -171,6 +171,15 @@ namespace np } } + void RoomMemberDataExternal_to_SceNpMatching2RoomMemberDataExternal(event_data& edata, const np2_structs::RoomMemberDataExternal& member, SceNpMatching2RoomMemberDataExternal* member_info, bool include_onlinename, bool include_avatarurl) + { + ensure(member.has_userinfo()); + + UserInfo_to_SceNpUserInfo2(edata, member.userinfo(), &member_info->userInfo, include_onlinename, include_avatarurl); + member_info->joinDate.tick = member.joindate(); + member_info->role = member.role().value(); + } + void SearchRoomResponse_to_SceNpMatching2SearchRoomResponse(event_data& edata, const np2_structs::SearchRoomResponse& resp, SceNpMatching2SearchRoomResponse* search_resp) { search_resp->range.size = resp.rooms_size(); @@ -181,8 +190,7 @@ namespace np for (int i = 0; i < resp.rooms_size(); i++) { const auto& pb_room = resp.rooms(i); - SceNpMatching2RoomDataExternal* cur_room; - cur_room = edata.allocate(sizeof(SceNpMatching2RoomDataExternal), (i > 0) ? prev_room->next : search_resp->roomDataExternal); + SceNpMatching2RoomDataExternal* cur_room = edata.allocate(sizeof(SceNpMatching2RoomDataExternal), (i > 0) ? prev_room->next : search_resp->roomDataExternal); RoomDataExternal_to_SceNpMatching2RoomDataExternal(edata, pb_room, cur_room, true, true); prev_room = cur_room; } @@ -196,15 +204,28 @@ namespace np for (int i = 0; i < resp.rooms_size(); i++) { const auto& pb_room = resp.rooms(i); - SceNpMatching2RoomDataExternal* cur_room; - - cur_room = edata.allocate(sizeof(SceNpMatching2RoomDataExternal), (i > 0) ? prev_room->next : get_resp->roomDataExternal); + SceNpMatching2RoomDataExternal* cur_room = edata.allocate(sizeof(SceNpMatching2RoomDataExternal), (i > 0) ? prev_room->next : get_resp->roomDataExternal); RoomDataExternal_to_SceNpMatching2RoomDataExternal(edata, pb_room, cur_room, include_onlinename, include_avatarurl); prev_room = cur_room; } } + void GetRoomMemberDataExternalListResponse_to_SceNpMatching2GetRoomMemberDataExternalListResponse(event_data& edata, const np2_structs::GetRoomMemberDataExternalListResponse& resp, SceNpMatching2GetRoomMemberDataExternalListResponse* get_resp, bool include_onlinename, bool include_avatarurl) + { + get_resp->roomMemberDataExternalNum = resp.members_size(); + + SceNpMatching2RoomMemberDataExternal* prev_member = nullptr; + for (int i = 0; i < resp.members_size(); i++) + { + const auto& pb_member = resp.members(i); + SceNpMatching2RoomMemberDataExternal* cur_member = edata.allocate(sizeof(SceNpMatching2RoomMemberDataExternal), (i > 0) ? prev_member->next : get_resp->roomMemberDataExternal); + + RoomMemberDataExternal_to_SceNpMatching2RoomMemberDataExternal(edata, pb_member, cur_member, include_onlinename, include_avatarurl); + prev_member = cur_member; + } + } + u16 RoomDataInternal_to_SceNpMatching2RoomDataInternal(event_data& edata, const np2_structs::RoomDataInternal& resp, SceNpMatching2RoomDataInternal* room_info, const SceNpId& npid, bool include_onlinename, bool include_avatarurl) { u16 member_id = 0; diff --git a/rpcs3/Emu/NP/pb_helpers.h b/rpcs3/Emu/NP/pb_helpers.h index c7482d7bc4..dc869210e7 100644 --- a/rpcs3/Emu/NP/pb_helpers.h +++ b/rpcs3/Emu/NP/pb_helpers.h @@ -16,8 +16,10 @@ namespace np void UserInfo_to_SceNpUserInfo(const np2_structs::UserInfo& user, SceNpUserInfo* user_info); void UserInfo_to_SceNpUserInfo2(event_data& edata, const np2_structs::UserInfo& user, SceNpUserInfo2* user_info, bool include_onlinename, bool include_avatarurl); void RoomDataExternal_to_SceNpMatching2RoomDataExternal(event_data& edata, const np2_structs::RoomDataExternal& room, SceNpMatching2RoomDataExternal* room_info, bool include_onlinename, bool include_avatarurl); + void RoomMemberDataExternal_to_SceNpMatching2RoomMemberDataExternal(event_data& edata, const np2_structs::RoomMemberDataExternal& member, SceNpMatching2RoomMemberDataExternal* member_info, bool include_onlinename, bool include_avatarurl); void SearchRoomResponse_to_SceNpMatching2SearchRoomResponse(event_data& edata, const np2_structs::SearchRoomResponse& resp, SceNpMatching2SearchRoomResponse* search_resp); void GetRoomDataExternalListResponse_to_SceNpMatching2GetRoomDataExternalListResponse(event_data& edata, const np2_structs::GetRoomDataExternalListResponse& resp, SceNpMatching2GetRoomDataExternalListResponse* get_resp, bool include_onlinename, bool include_avatarurl); + void GetRoomMemberDataExternalListResponse_to_SceNpMatching2GetRoomMemberDataExternalListResponse(event_data& edata, const np2_structs::GetRoomMemberDataExternalListResponse& resp, SceNpMatching2GetRoomMemberDataExternalListResponse* get_resp, bool include_onlinename, bool include_avatarurl); u16 RoomDataInternal_to_SceNpMatching2RoomDataInternal(event_data& edata, const np2_structs::RoomDataInternal& resp, SceNpMatching2RoomDataInternal* room_resp, const SceNpId& npid, bool include_onlinename, bool include_avatarurl); void RoomMemberDataInternal_to_SceNpMatching2RoomMemberDataInternal(event_data& edata, const np2_structs::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 np2_structs::RoomMemberUpdateInfo& resp, SceNpMatching2RoomMemberUpdateInfo* room_info, bool include_onlinename, bool include_avatarurl); diff --git a/rpcs3/Emu/NP/rpcn_client.cpp b/rpcs3/Emu/NP/rpcn_client.cpp index cce4fa397b..c1126b8698 100644 --- a/rpcs3/Emu/NP/rpcn_client.cpp +++ b/rpcs3/Emu/NP/rpcn_client.cpp @@ -117,6 +117,7 @@ void fmt_class_string::format(std::string& out, u64 arg) case rpcn::CommandType::LeaveRoom: return "LeaveRoom"; case rpcn::CommandType::SearchRoom: return "SearchRoom"; case rpcn::CommandType::GetRoomDataExternalList: return "GetRoomDataExternalList"; + case rpcn::CommandType::GetRoomMemberDataExternalList: return "GetRoomMemberDataExternalList"; case rpcn::CommandType::SetRoomDataExternal: return "SetRoomDataExternal"; case rpcn::CommandType::GetRoomDataInternal: return "GetRoomDataInternal"; case rpcn::CommandType::SetRoomDataInternal: return "SetRoomDataInternal"; @@ -1915,6 +1916,16 @@ namespace rpcn return forge_request_with_com_id(serialized, communication_id, CommandType::GetRoomDataExternalList, req_id); } + bool rpcn_client::get_room_member_data_external_list(u32 req_id, const SceNpCommunicationId& communication_id, u64 room_id) + { + std::vector data(COMMUNICATION_ID_SIZE + sizeof(u64)); + + rpcn_client::write_communication_id(communication_id, data); + write_to_ptr>(data, COMMUNICATION_ID_SIZE, room_id); + + return forge_send(CommandType::GetRoomMemberDataExternalList, req_id, data); + } + bool rpcn_client::set_roomdata_external(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomDataExternalRequest* req) { np2_structs::SetRoomDataExternalRequest pb_req; diff --git a/rpcs3/Emu/NP/rpcn_client.h b/rpcs3/Emu/NP/rpcn_client.h index e3c3f47ba9..035dc9cf3c 100644 --- a/rpcs3/Emu/NP/rpcn_client.h +++ b/rpcs3/Emu/NP/rpcn_client.h @@ -329,6 +329,7 @@ namespace rpcn bool leave_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2LeaveRoomRequest* req); bool search_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SearchRoomRequest* req); bool get_roomdata_external_list(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2GetRoomDataExternalListRequest* req); + bool get_room_member_data_external_list(u32 req_id, const SceNpCommunicationId& communication_id, u64 room_id); bool set_roomdata_external(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomDataExternalRequest* req); bool get_roomdata_internal(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2GetRoomDataInternalRequest* req); bool set_roomdata_internal(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomDataInternalRequest* req); diff --git a/rpcs3/Emu/NP/rpcn_types.h b/rpcs3/Emu/NP/rpcn_types.h index 15fba827d5..28500462e6 100644 --- a/rpcs3/Emu/NP/rpcn_types.h +++ b/rpcs3/Emu/NP/rpcn_types.h @@ -68,6 +68,7 @@ namespace rpcn GetRoomInfoGUI, QuickMatchGUI, SearchJoinRoomGUI, + GetRoomMemberDataExternalList, }; enum class NotificationType : u16 From 96cf5c4e63a798ca8e83fcc070cb6e15f2918b0e Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Sat, 31 Jan 2026 03:51:45 +0100 Subject: [PATCH 23/40] Fix generic_async_transaction_context thread handling --- rpcs3/Emu/NP/np_contexts.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/NP/np_contexts.cpp b/rpcs3/Emu/NP/np_contexts.cpp index 8bcfd5f01c..46d773d127 100644 --- a/rpcs3/Emu/NP/np_contexts.cpp +++ b/rpcs3/Emu/NP/np_contexts.cpp @@ -17,7 +17,12 @@ generic_async_transaction_context::generic_async_transaction_context(const SceNp generic_async_transaction_context::~generic_async_transaction_context() { if (thread.joinable()) - thread.join(); + { + if (std::this_thread::get_id() == thread.get_id()) + thread.detach(); + else + thread.join(); + } } std::optional generic_async_transaction_context::get_transaction_status() From 1c08439907753a86ee1628f07d5fcbe86bfdda2f Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Sat, 31 Jan 2026 06:26:24 +0100 Subject: [PATCH 24/40] Force disable RPCN IPv6 support for now --- rpcs3/Emu/NP/rpcn_config.h | 2 +- rpcs3/rpcs3qt/rpcn_settings_dialog.cpp | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/rpcs3/Emu/NP/rpcn_config.h b/rpcs3/Emu/NP/rpcn_config.h index 0a8c7c9cc5..3ea6b707b1 100644 --- a/rpcs3/Emu/NP/rpcn_config.h +++ b/rpcs3/Emu/NP/rpcn_config.h @@ -10,7 +10,7 @@ struct cfg_rpcn : cfg::node cfg::string password{this, "Password", ""}; cfg::string token{this, "Token", ""}; cfg::string hosts{this, "Hosts", "Official RPCN Server|np.rpcs3.net"}; - cfg::_bool ipv6_support{this, "IPv6 support", true}; + cfg::_bool ipv6_support{this, "Experimental IPv6 support", false}; void load(); void save() const; diff --git a/rpcs3/rpcs3qt/rpcn_settings_dialog.cpp b/rpcs3/rpcs3qt/rpcn_settings_dialog.cpp index 24aa0767aa..53097f29fc 100644 --- a/rpcs3/rpcs3qt/rpcn_settings_dialog.cpp +++ b/rpcs3/rpcs3qt/rpcn_settings_dialog.cpp @@ -185,8 +185,8 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent) QPushButton* btn_test = new QPushButton(tr("Test Account")); QLabel* label_npid = new QLabel(); - QCheckBox* checkbox_disable_ipv6 = new QCheckBox(tr("Disable IPv6")); - checkbox_disable_ipv6->setCheckState(g_cfg_rpcn.get_ipv6_support() ? Qt::Unchecked : Qt::Checked); + // QCheckBox* checkbox_disable_ipv6 = new QCheckBox(tr("Enable IPv6(Experimental)")); + // checkbox_disable_ipv6->setCheckState(g_cfg_rpcn.get_ipv6_support() ? Qt::Checked : Qt::Unchecked); const auto update_npid_label = [label_npid]() { @@ -206,7 +206,7 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent) grp_buttons->setLayout(vbox_buttons); vbox_global->addWidget(grp_buttons); - vbox_global->addWidget(checkbox_disable_ipv6); + // vbox_global->addWidget(checkbox_disable_ipv6); setLayout(vbox_global); @@ -359,11 +359,11 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent) QMessageBox::information(this, tr("RPCN Account Valid!"), tr("Your account is valid!"), QMessageBox::Ok); }); - connect(checkbox_disable_ipv6, &QCheckBox::checkStateChanged, this, [this](Qt::CheckState state) - { - g_cfg_rpcn.set_ipv6_support(state == Qt::Unchecked); - g_cfg_rpcn.save(); - }); + // connect(checkbox_disable_ipv6, &QCheckBox::checkStateChanged, this, [this](Qt::CheckState state) + // { + // g_cfg_rpcn.set_ipv6_support(state == Qt::Checked); + // g_cfg_rpcn.save(); + // }); } void rpcn_account_dialog::refresh_combobox() From 588cf69dad726a4485af945ba0507193c526ccf7 Mon Sep 17 00:00:00 2001 From: Windsurf7 <70599421+Windsurf7@users.noreply.github.com> Date: Mon, 2 Feb 2026 11:21:02 +0300 Subject: [PATCH 25/40] Add mouse-based gyro emulation (#18113) This change adds a hardcoded mouse-based motion sensor emulation feature, inspired by how Cemu handles mouse-driven gyro input. While the game window is focused, holding the right mouse button enables gyro emulation: - Mouse X movement feeds Motion X - Mouse Y movement feeds Motion Z - Mouse Wheel feeds Motion Y The axis mapping and behavior were tested with the "Spark Runner" minigame in _Sly Cooper: Thieves in Time_ and _Bentley's Hackpack_. In accordance with this minigame, a top-down view motion control scheme relies on the X/Z axes. While the right mouse button is being held, mouse deltas are captured via the Qt native event filter and accumulated in the frontend, then consumed by the pad thread. On right mouse button release, motion values are reset to the neutral center to avoid residual drift. This input path is intentionally independent of pad configuration and works even when a keyboard-only profile is selected. This implementation thus resolves issue #13883 by allowing motion-only gameplay without requiring a physical motion-capable controller. --- rpcs3/Input/mouse_gyro_handler.cpp | 146 ++++++++++++++++++++++++++++ rpcs3/Input/mouse_gyro_handler.h | 33 +++++++ rpcs3/Input/pad_thread.cpp | 7 ++ rpcs3/Input/pad_thread.h | 5 + rpcs3/rpcs3.vcxproj | 2 + rpcs3/rpcs3.vcxproj.filters | 6 ++ rpcs3/rpcs3qt/CMakeLists.txt | 1 + rpcs3/rpcs3qt/gs_frame.cpp | 20 ++++ rpcs3/rpcs3qt/shortcut_settings.cpp | 2 + rpcs3/rpcs3qt/shortcut_settings.h | 1 + 10 files changed, 223 insertions(+) create mode 100644 rpcs3/Input/mouse_gyro_handler.cpp create mode 100644 rpcs3/Input/mouse_gyro_handler.h diff --git a/rpcs3/Input/mouse_gyro_handler.cpp b/rpcs3/Input/mouse_gyro_handler.cpp new file mode 100644 index 0000000000..6f1c7cd637 --- /dev/null +++ b/rpcs3/Input/mouse_gyro_handler.cpp @@ -0,0 +1,146 @@ +#include "mouse_gyro_handler.h" + +#include +#include +#include +#include + +#include + +void mouse_gyro_handler::clear() +{ + active = false; + reset = false; + gyro_x = DEFAULT_MOTION_X; + gyro_y = DEFAULT_MOTION_Y; + gyro_z = DEFAULT_MOTION_Z; +} + +bool mouse_gyro_handler::toggle_enabled() +{ + enabled = !enabled; + clear(); + return enabled; +} + +void mouse_gyro_handler::set_gyro_active() +{ + active = true; +} + +void mouse_gyro_handler::set_gyro_reset() +{ + active = false; + reset = true; +} + +void mouse_gyro_handler::set_gyro_xz(s32 off_x, s32 off_y) +{ + if (!active) + return; + + gyro_x = static_cast(std::clamp(off_x, 0, DEFAULT_MOTION_X * 2 - 1)); + gyro_z = static_cast(std::clamp(off_y, 0, DEFAULT_MOTION_Z * 2 - 1)); +} + +void mouse_gyro_handler::set_gyro_y(s32 steps) +{ + if (!active) + return; + + gyro_y = static_cast(std::clamp(gyro_y + steps, 0, DEFAULT_MOTION_Y * 2 - 1)); +} + +void mouse_gyro_handler::handle_event(QEvent* ev, const QWindow& win) +{ + if (!enabled) + return; + + // Mouse-based motion input. + // Captures mouse events while the game window is focused. + // Updates motion sensor values via mouse position and mouse wheel while RMB is held. + // Intentionally independent of chosen pad configuration. + switch (ev->type()) + { + case QEvent::MouseButtonPress: + { + auto* e = static_cast(ev); + if (e->button() == Qt::RightButton) + { + // Enable mouse-driven gyro emulation while RMB is held. + set_gyro_active(); + } + break; + } + case QEvent::MouseButtonRelease: + { + auto* e = static_cast(ev); + if (e->button() == Qt::RightButton) + { + // Disable gyro emulation and request a one-shot motion reset. + set_gyro_reset(); + } + break; + } + case QEvent::MouseMove: + { + auto* e = static_cast(ev); + + // Track cursor offset from window center. + const QPoint center(win.width() / 2, win.height() / 2); + const QPoint cur = e->position().toPoint(); + + const s32 off_x = cur.x() - center.x() + DEFAULT_MOTION_X; + const s32 off_y = cur.y() - center.y() + DEFAULT_MOTION_Z; + + // Determine motion from relative mouse position while gyro emulation is active. + set_gyro_xz(off_x, off_y); + + break; + } + case QEvent::Wheel: + { + auto* e = static_cast(ev); + + // Track mouse wheel steps. + const s32 steps = e->angleDelta().y() / 120; + + // Accumulate mouse wheel steps while gyro emulation is active. + set_gyro_y(steps); + + break; + } + default: + { + break; + } + } +} + +void mouse_gyro_handler::apply_gyro(const std::shared_ptr& pad) +{ + if (!enabled) + return; + + if (!pad || !pad->is_connected()) + return; + + // Inject mouse-based motion sensor values into pad sensors for gyro emulation. + // The Qt frontend maps cursor offset and wheel input to absolute motion values while RMB is held. + if (reset) + { + // RMB released → reset motion + pad->m_sensors[0].m_value = DEFAULT_MOTION_X; + pad->m_sensors[1].m_value = DEFAULT_MOTION_Y; + pad->m_sensors[2].m_value = DEFAULT_MOTION_Z; + clear(); + } + else + { + // RMB held → accumulate motion + // Axes have been chosen as tested in Sly 4 minigames. Top-down view motion uses X/Z axes. + pad->m_sensors[0].m_value = gyro_x; // Mouse X → Motion X + pad->m_sensors[1].m_value = gyro_y; // Mouse Wheel → Motion Y + pad->m_sensors[2].m_value = gyro_z; // Mouse Y → Motion Z + } +} diff --git a/rpcs3/Input/mouse_gyro_handler.h b/rpcs3/Input/mouse_gyro_handler.h new file mode 100644 index 0000000000..97a745d919 --- /dev/null +++ b/rpcs3/Input/mouse_gyro_handler.h @@ -0,0 +1,33 @@ +#pragma once + +#include "util/types.hpp" +#include "util/atomic.hpp" +#include "Emu/Io/pad_types.h" + +class QEvent; +class QWindow; + +// Mouse-based motion sensor emulation state. +class mouse_gyro_handler +{ +private: + atomic_t enabled = false; // Whether mouse-based gyro emulation mode has been enabled by using the associated hotkey + + atomic_t active = false; // Whether right mouse button is currently held (gyro active) + atomic_t reset = false; // One-shot reset request on right mouse button release + atomic_t gyro_x = DEFAULT_MOTION_X; // Accumulated from mouse X position relative to center + atomic_t gyro_y = DEFAULT_MOTION_Y; // Accumulated from mouse wheel delta + atomic_t gyro_z = DEFAULT_MOTION_Z; // Accumulated from mouse Y position relative to center + + void set_gyro_active(); + void set_gyro_reset(); + void set_gyro_xz(s32 off_x, s32 off_y); + void set_gyro_y(s32 steps); + +public: + void clear(); + bool toggle_enabled(); + + void handle_event(QEvent* ev, const QWindow& win); + void apply_gyro(const std::shared_ptr& pad); +}; diff --git a/rpcs3/Input/pad_thread.cpp b/rpcs3/Input/pad_thread.cpp index afc5a73fce..40887ae5fb 100644 --- a/rpcs3/Input/pad_thread.cpp +++ b/rpcs3/Input/pad_thread.cpp @@ -81,6 +81,9 @@ void pad_thread::Init() { std::lock_guard lock(pad::g_pad_mutex); + // Reset mouse-based gyro state + m_mouse_gyro.clear(); + // Cache old settings if possible std::array pad_settings; for (u32 i = 0; i < CELL_PAD_MAX_PORT_NUM; i++) // max 7 pads @@ -606,6 +609,10 @@ void pad_thread::operator()() if (Emu.IsRunning()) { update_pad_states(); + + // Apply mouse-based gyro emulation. + // Intentionally bound to Player 1 only. + m_mouse_gyro.apply_gyro(m_pads[0]); } m_info.now_connect = connected_devices + num_ldd_pad; diff --git a/rpcs3/Input/pad_thread.h b/rpcs3/Input/pad_thread.h index 7b0e0b79fb..20f53e9034 100644 --- a/rpcs3/Input/pad_thread.h +++ b/rpcs3/Input/pad_thread.h @@ -5,6 +5,7 @@ #include "Emu/Io/pad_types.h" #include "Emu/Io/pad_config.h" #include "Emu/Io/pad_config_types.h" +#include "Input/mouse_gyro_handler.h" #include "Utilities/mutex.h" #include @@ -41,6 +42,8 @@ public: static auto constexpr thread_name = "Pad Thread"sv; + mouse_gyro_handler& get_mouse_gyro() { return m_mouse_gyro; } + protected: void Init(); void InitLddPad(u32 handle, const u32* port_status); @@ -67,6 +70,8 @@ private: bool m_resume_emulation_flag = false; bool m_ps_button_pressed = false; atomic_t m_home_menu_open = false; + + mouse_gyro_handler m_mouse_gyro; }; namespace pad diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 5fbf0491e9..9749f60fcd 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -194,6 +194,7 @@ + @@ -1079,6 +1080,7 @@ $(QTDIR)\bin\moc.exe;%(FullPath) $(QTDIR)\bin\moc.exe;%(FullPath) + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 100a9b1d8f..a011ddf62e 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -1272,6 +1272,9 @@ Generated Files\Release + + Io + @@ -1511,6 +1514,9 @@ Io\camera + + Io + diff --git a/rpcs3/rpcs3qt/CMakeLists.txt b/rpcs3/rpcs3qt/CMakeLists.txt index a8fc4c5886..b59d6f7a11 100644 --- a/rpcs3/rpcs3qt/CMakeLists.txt +++ b/rpcs3/rpcs3qt/CMakeLists.txt @@ -157,6 +157,7 @@ add_library(rpcs3_ui STATIC ../Input/hid_pad_handler.cpp ../Input/keyboard_pad_handler.cpp ../Input/mm_joystick_handler.cpp + ../Input/mouse_gyro_handler.cpp ../Input/pad_thread.cpp ../Input/product_info.cpp ../Input/ps_move_calibration.cpp diff --git a/rpcs3/rpcs3qt/gs_frame.cpp b/rpcs3/rpcs3qt/gs_frame.cpp index db66ce68a4..6557168cce 100644 --- a/rpcs3/rpcs3qt/gs_frame.cpp +++ b/rpcs3/rpcs3qt/gs_frame.cpp @@ -19,6 +19,7 @@ #include "Emu/RSX/Overlays/overlay_message.h" #include "Emu/Io/interception.h" #include "Emu/Io/recording_config.h" +#include "Input/pad_thread.h" #include #include @@ -402,6 +403,15 @@ void gs_frame::handle_shortcut(gui::shortcuts::shortcut shortcut_key, const QKey audio::change_volume(-5); break; } + case gui::shortcuts::shortcut::gw_toggle_mouse_gyro: + { + if (auto* pad_thr = pad::get_pad_thread(true)) + { + const bool mouse_gyro_enabled = pad_thr->get_mouse_gyro().toggle_enabled(); + gui_log.notice("Mouse-based gyro emulation %s", mouse_gyro_enabled ? "enabled" : "disabled"); + } + break; + } default: { break; @@ -1216,6 +1226,16 @@ bool gs_frame::event(QEvent* ev) // This will make the cursor visible again if it was hidden by the mouse idle timeout handle_cursor(visibility(), false, false, true); } + + // Handle events for mouse-based gyro emulation. + if (Emu.IsRunning()) + { + if (auto* pad_thr = pad::get_pad_thread(true)) + { + pad_thr->get_mouse_gyro().handle_event(ev, *this); + } + } + return QWindow::event(ev); } diff --git a/rpcs3/rpcs3qt/shortcut_settings.cpp b/rpcs3/rpcs3qt/shortcut_settings.cpp index 039f493dae..64feb94777 100644 --- a/rpcs3/rpcs3qt/shortcut_settings.cpp +++ b/rpcs3/rpcs3qt/shortcut_settings.cpp @@ -37,6 +37,7 @@ void fmt_class_string::format(std::string& out, u64 arg) case shortcut::gw_mute_unmute: return "gw_mute_unmute"; case shortcut::gw_volume_up: return "gw_volume_up"; case shortcut::gw_volume_down: return "gw_volume_down"; + case shortcut::gw_toggle_mouse_gyro: return "gw_toggle_mouse_gyro"; case shortcut::count: return "count"; } @@ -88,6 +89,7 @@ shortcut_settings::shortcut_settings() { shortcut::gw_mute_unmute, shortcut_info{ "gw_mute_unmute", tr("Mute/Unmute Audio"), "Ctrl+Shift+M", shortcut_handler_id::game_window, false } }, { shortcut::gw_volume_up, shortcut_info{ "gw_volume_up", tr("Volume Up"), "Ctrl+Shift++", shortcut_handler_id::game_window, true } }, { shortcut::gw_volume_down, shortcut_info{ "gw_volume_down", tr("Volume Down"), "Ctrl+Shift+-", shortcut_handler_id::game_window, true } }, + { shortcut::gw_toggle_mouse_gyro, shortcut_info{ "gw_toggle_mouse_gyro", tr("Toggle Mouse-based Gyro"), "Ctrl+G", shortcut_handler_id::game_window, false } }, }) { } diff --git a/rpcs3/rpcs3qt/shortcut_settings.h b/rpcs3/rpcs3qt/shortcut_settings.h index db6458accb..be14ee1e30 100644 --- a/rpcs3/rpcs3qt/shortcut_settings.h +++ b/rpcs3/rpcs3qt/shortcut_settings.h @@ -46,6 +46,7 @@ namespace gui gw_mute_unmute, gw_volume_up, gw_volume_down, + gw_toggle_mouse_gyro, count }; From ad90f8b44bdf29ce55c6a9b9ad855bde8ce66752 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 1 Feb 2026 20:20:20 +0300 Subject: [PATCH 26/40] rsx: Conservative MM flush during CPU handling of nv3089_image_in --- rpcs3/Emu/RSX/NV47/HW/nv3089.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/RSX/NV47/HW/nv3089.cpp b/rpcs3/Emu/RSX/NV47/HW/nv3089.cpp index 111611d887..6ac502b462 100644 --- a/rpcs3/Emu/RSX/NV47/HW/nv3089.cpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv3089.cpp @@ -4,6 +4,7 @@ #include "Emu/RSX/RSXThread.h" #include "Emu/RSX/Core/RSXReservationLock.hpp" #include "Emu/RSX/Common/tiled_dma_copy.hpp" +#include "Emu/RSX/Host/MM.h" #include "context_accessors.define.h" @@ -581,9 +582,11 @@ namespace rsx const u16 out_h = REGS(ctx)->blit_engine_output_height(); // Lock here. RSX cannot execute any locking operations from this point, including ZCULL read barriers + const u32 read_length = src.pitch * src.height; + const u32 write_length = dst.pitch * dst.clip_height; auto res = ::rsx::reservation_lock( - dst.rsx_address, dst.pitch * dst.clip_height, - src.rsx_address, src.pitch * src.height); + dst.rsx_address, write_length, + src.rsx_address, read_length); if (!g_cfg.video.force_cpu_blit_processing && (dst.dma == CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER || src.dma == CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER) && @@ -593,6 +596,14 @@ namespace rsx return; } + // Conservative MM flush + rsx::simple_array flush_mm_ranges = + { + utils::address_range64::start_length(reinterpret_cast(dst.pixels), write_length), + utils::address_range64::start_length(reinterpret_cast(src.pixels), read_length) + }; + rsx::mm_flush(flush_mm_ranges); + std::vector mirror_tmp; bool src_is_temp = false; @@ -619,7 +630,7 @@ namespace rsx const bool interpolate = in_inter == blit_engine::transfer_interpolator::foh; auto real_dst = dst.pixels; - const auto tiled_region = RSX(ctx)->get_tiled_memory_region(utils::address_range32::start_length(dst.rsx_address, dst.pitch * dst.clip_height)); + const auto tiled_region = RSX(ctx)->get_tiled_memory_region(utils::address_range32::start_length(dst.rsx_address, write_length)); std::vector tmp; if (tiled_region) From 55aae4dd4067a21adf0ad18c183b15989c12b215 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 2 Feb 2026 20:10:25 +0300 Subject: [PATCH 27/40] vk: Fix NVIDIA crash when resizing the game window quickly --- rpcs3/Emu/RSX/VK/VKGSRender.h | 2 +- rpcs3/Emu/RSX/VK/VKPresent.cpp | 31 +++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index faae1bb78f..0c93741fcb 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -221,7 +221,7 @@ private: void frame_context_cleanup(vk::frame_context_t *ctx); void advance_queued_frames(); void present(vk::frame_context_t *ctx); - void reinitialize_swapchain(); + bool reinitialize_swapchain(); vk::viewable_image* get_present_source(vk::present_surface_info* info, const rsx::avconf& avconfig); diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index f9fbb114ed..5761a99120 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -33,7 +33,7 @@ namespace } } -void VKGSRender::reinitialize_swapchain() +bool VKGSRender::reinitialize_swapchain() { m_swapchain_dims.width = m_frame->client_width(); m_swapchain_dims.height = m_frame->client_height(); @@ -44,7 +44,7 @@ void VKGSRender::reinitialize_swapchain() if (m_swapchain_dims.width == 0 || m_swapchain_dims.height == 0) { swapchain_unavailable = true; - return; + return false; } // NOTE: This operation will create a hard sync point @@ -97,7 +97,7 @@ void VKGSRender::reinitialize_swapchain() { rsx_log.warning("Swapchain initialization failed. Request ignored [%dx%d]", m_swapchain_dims.width, m_swapchain_dims.height); swapchain_unavailable = true; - return; + return false; } // Re-initialize CPU frame contexts @@ -135,6 +135,7 @@ void VKGSRender::reinitialize_swapchain() swapchain_unavailable = false; should_reinitialize_swapchain = false; + return true; } void VKGSRender::present(vk::frame_context_t *ctx) @@ -426,11 +427,32 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) if (swapchain_unavailable || should_reinitialize_swapchain) { - reinitialize_swapchain(); + // Reinitializing the swapchain is a failable operation. However, not all failures are fatal (e.g minimized window). + // In the worst case, we can have the driver refuse to create the swapchain while we already deleted the previous one. + // In such scenarios, we have to retry a few times before giving up as we cannot proceed without a swapchain. + for (int i = 0; i < 10; ++i) + { + if (reinitialize_swapchain() || m_current_frame) + { + // If m_current_frame exists, then the initialization failure is non-fatal. Proceed as usual. + break; + } + + if (Emu.IsStopped()) + { + m_frame->flip(m_context); + rsx::thread::flip(info); + return; + } + + std::this_thread::sleep_for(100ms); + } } m_profiler.start(); + ensure(m_current_frame, "Invalid swapchain setup. Resizing the game window failed."); + if (m_current_frame == &m_aux_frame_context) { m_current_frame = &m_frame_context_storage[m_current_queue_index]; @@ -582,6 +604,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) rsx_log.warning("vkAcquireNextImageKHR failed with VK_ERROR_OUT_OF_DATE_KHR. Flip request ignored until surface is recreated."); swapchain_unavailable = true; reinitialize_swapchain(); + ensure(m_current_frame, "Could not reinitialize swapchain after VK_ERROR_OUT_OF_DATE_KHR signal!"); continue; default: vk::die_with_error(status); From 8ba48932d3b809feb1caad17790d07bebf6ae225 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 2 Feb 2026 09:38:44 +0100 Subject: [PATCH 28/40] Qt: try to fix update downloader --- rpcs3/rpcs3qt/downloader.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rpcs3/rpcs3qt/downloader.cpp b/rpcs3/rpcs3qt/downloader.cpp index dd861da73e..ae97dc8f77 100644 --- a/rpcs3/rpcs3qt/downloader.cpp +++ b/rpcs3/rpcs3qt/downloader.cpp @@ -99,7 +99,7 @@ void downloader::start(const std::string& url, bool follow_location, bool show_p // The downloader's signals are expected to be disconnected and customized before start is called. // Therefore we need to (re)connect its signal(s) here and not in the constructor. - connect(this, &downloader::signal_buffer_update, this, &downloader::handle_buffer_update); + connect(this, &downloader::signal_buffer_update, this, &downloader::handle_buffer_update, static_cast(Qt::QueuedConnection | Qt::UniqueConnection)); if (show_progress_dialog) { @@ -169,7 +169,7 @@ usz downloader::update_buffer(char* data, usz size) const auto old_size = m_curl_buf.size(); const auto new_size = old_size + size; m_curl_buf.resize(static_cast(new_size)); - memcpy(m_curl_buf.data() + old_size, data, size); + std::memcpy(m_curl_buf.data() + old_size, data, size); int max = 0; @@ -197,6 +197,5 @@ void downloader::handle_buffer_update(int size, int max) const { m_progress_dialog->SetRange(0, max > 0 ? max : m_progress_dialog->maximum()); m_progress_dialog->SetValue(size); - QApplication::processEvents(); } } From f1e679d9819dc1be5b097d068ef5e62d7f97a2ba Mon Sep 17 00:00:00 2001 From: trautamaki <13891897+trautamaki@users.noreply.github.com> Date: Tue, 3 Feb 2026 09:00:48 +0200 Subject: [PATCH 29/40] Switch from FFmpeg av_opt_set_* to swr_alloc_set_opts2 (#18138) ffmpeg 7 doesn't allow to set in_channel_count and out_channel_count anymore --- rpcs3/util/media_utils.cpp | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/rpcs3/util/media_utils.cpp b/rpcs3/util/media_utils.cpp index 571eaa74fd..284f6eb758 100644 --- a/rpcs3/util/media_utils.cpp +++ b/rpcs3/util/media_utils.cpp @@ -575,34 +575,28 @@ namespace utils return; } - // Prepare resampler - av.swr = swr_alloc(); - if (!av.swr) - { - media_log.error("audio_decoder: Failed to allocate resampler for stream #%u in file '%s'", stream_index, path); - has_error = true; - return; - } - const int dst_channels = 2; const AVChannelLayout dst_channel_layout = AV_CHANNEL_LAYOUT_STEREO; const AVSampleFormat dst_format = AV_SAMPLE_FMT_FLT; - int set_err = 0; - if ((set_err = av_opt_set_int(av.swr, "in_channel_count", stream->codecpar->ch_layout.nb_channels, 0)) || - (set_err = av_opt_set_int(av.swr, "out_channel_count", dst_channels, 0)) || - (set_err = av_opt_set_chlayout(av.swr, "in_channel_layout", &stream->codecpar->ch_layout, 0)) || - (set_err = av_opt_set_chlayout(av.swr, "out_channel_layout", &dst_channel_layout, 0)) || - (set_err = av_opt_set_int(av.swr, "in_sample_rate", stream->codecpar->sample_rate, 0)) || - (set_err = av_opt_set_int(av.swr, "out_sample_rate", sample_rate, 0)) || - (set_err = av_opt_set_sample_fmt(av.swr, "in_sample_fmt", static_cast(stream->codecpar->format), 0)) || - (set_err = av_opt_set_sample_fmt(av.swr, "out_sample_fmt", dst_format, 0))) + const int set_err = swr_alloc_set_opts2(&av.swr, &dst_channel_layout, dst_format, + sample_rate, &stream->codecpar->ch_layout, + static_cast(stream->codecpar->format), + stream->codecpar->sample_rate, 0, nullptr); + if (set_err < 0) { media_log.error("audio_decoder: Failed to set resampler options: Error: %d='%s'", set_err, av_error_to_string(set_err)); has_error = true; return; } + if (!av.swr) + { + media_log.error("audio_decoder: Failed to allocate resampler for stream #%u in file '%s'", stream_index, path); + has_error = true; + return; + } + if (int err = swr_init(av.swr); err < 0 || !swr_is_initialized(av.swr)) { media_log.error("audio_decoder: Resampler has not been properly initialized: %d='%s'", err, av_error_to_string(err)); From 622fe1ce478025adaede0d01fdf019af7af3ab5d Mon Sep 17 00:00:00 2001 From: Megamouse Date: Tue, 3 Feb 2026 07:26:09 +0100 Subject: [PATCH 30/40] Qt: don't filter log if the input dialog was canceled --- rpcs3/rpcs3qt/log_viewer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rpcs3/rpcs3qt/log_viewer.cpp b/rpcs3/rpcs3qt/log_viewer.cpp index 3a566937a7..753f8cc0f5 100644 --- a/rpcs3/rpcs3qt/log_viewer.cpp +++ b/rpcs3/rpcs3qt/log_viewer.cpp @@ -187,7 +187,10 @@ void log_viewer::show_context_menu(const QPoint& pos) connect(filter, &QAction::triggered, this, [this]() { - m_filter_term = QInputDialog::getText(this, tr("Filter log"), tr("Enter text"), QLineEdit::EchoMode::Normal, m_filter_term); + bool ok = false; + QString filter_term = QInputDialog::getText(this, tr("Filter log"), tr("Enter text"), QLineEdit::EchoMode::Normal, m_filter_term, &ok); + if (!ok) return; + m_filter_term = std::move(filter_term); filter_log(); }); From 3eb8fdaef4582d29f02c02e443506b25398063fe Mon Sep 17 00:00:00 2001 From: Megamouse Date: Tue, 3 Feb 2026 07:38:01 +0100 Subject: [PATCH 31/40] Qt: simplify log level filtering in log viewer --- rpcs3/rpcs3qt/log_viewer.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/rpcs3/rpcs3qt/log_viewer.cpp b/rpcs3/rpcs3qt/log_viewer.cpp index 753f8cc0f5..8934ef0a7b 100644 --- a/rpcs3/rpcs3qt/log_viewer.cpp +++ b/rpcs3/rpcs3qt/log_viewer.cpp @@ -325,22 +325,17 @@ void log_viewer::filter_log() const auto add_line = [this, &result, &excluded_log_levels, ×tamp_regexp, &thread_regexp](QString& line) { - bool exclude_line = false; - - for (const QString& log_level_prefix : excluded_log_levels) + if (!line.isEmpty()) { - if (line.startsWith(log_level_prefix)) + for (QStringView log_level_prefix : excluded_log_levels) { - exclude_line = true; - break; + if (line.startsWith(log_level_prefix)) + { + return; + } } } - if (exclude_line) - { - return; - } - if (m_filter_term.isEmpty() || line.contains(m_filter_term)) { if (line.isEmpty()) From 294050986f58baa71fdc15a05559120a40b3a22a Mon Sep 17 00:00:00 2001 From: Megamouse Date: Tue, 3 Feb 2026 08:24:42 +0100 Subject: [PATCH 32/40] Qt: allow to exclude strings in log viewer --- rpcs3/rpcs3qt/log_viewer.cpp | 96 ++++++++++++++++++++++++++---------- rpcs3/rpcs3qt/log_viewer.h | 3 ++ 2 files changed, 72 insertions(+), 27 deletions(-) diff --git a/rpcs3/rpcs3qt/log_viewer.cpp b/rpcs3/rpcs3qt/log_viewer.cpp index 8934ef0a7b..b69c07901e 100644 --- a/rpcs3/rpcs3qt/log_viewer.cpp +++ b/rpcs3/rpcs3qt/log_viewer.cpp @@ -28,7 +28,8 @@ LOG_CHANNEL(gui_log, "GUI"); log_viewer::log_viewer(std::shared_ptr gui_settings) : m_gui_settings(std::move(gui_settings)) { - setWindowTitle(tr("Log Viewer")); + update_title(); + setObjectName("log_viewer"); setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_StyledBackground); @@ -59,15 +60,33 @@ log_viewer::log_viewer(std::shared_ptr gui_settings) connect(m_log_text, &QWidget::customContextMenuRequested, this, &log_viewer::show_context_menu); } +void log_viewer::update_title() +{ + QString suffix; + + if (!m_filter_term.isEmpty()) + { + suffix = tr(" | Filter '%0'").arg(m_filter_term); + } + + if (!m_exclude_term.isEmpty()) + { + suffix += tr(" | Exclude '%0'").arg(m_exclude_term); + } + + setWindowTitle(tr("Log Viewer%0").arg(suffix)); +} + void log_viewer::show_context_menu(const QPoint& pos) { QMenu menu; - QAction* clear = new QAction(tr("&Clear")); - QAction* copy = new QAction(tr("&Copy")); - QAction* open = new QAction(tr("&Open log file")); - QAction* save = new QAction(tr("&Save filtered log")); - QAction* filter = new QAction(tr("&Filter log")); - QAction* config = new QAction(tr("&Check config")); + QAction* clear = new QAction(tr("&Clear")); + QAction* copy = new QAction(tr("&Copy")); + QAction* open = new QAction(tr("&Open log file")); + QAction* save = new QAction(tr("&Save filtered log")); + QAction* filter = new QAction(tr("&Filter log%0").arg(m_filter_term.isEmpty() ? "" : QString(" (%0)").arg(m_filter_term))); + QAction* exclude = new QAction(tr("&Exclude%0").arg(m_exclude_term.isEmpty() ? "" : QString(" (%0)").arg(m_exclude_term))); + QAction* config = new QAction(tr("&Check config")); QAction* timestamps = new QAction(tr("&Show Timestamps")); timestamps->setCheckable(true); @@ -91,7 +110,7 @@ void log_viewer::show_context_menu(const QPoint& pos) QAction* trace_act = new QAction(tr("Trace"), log_level_acts); log_level_acts->setExclusive(false); - auto init_action = [this](QAction* act, logs::level logLevel) + const auto init_action = [this](QAction* act, logs::level logLevel) { act->setCheckable(true); act->setChecked(m_log_levels.test(static_cast(logLevel))); @@ -120,6 +139,7 @@ void log_viewer::show_context_menu(const QPoint& pos) menu.addAction(open); menu.addAction(config); menu.addAction(filter); + menu.addAction(exclude); menu.addAction(save); menu.addSeparator(); menu.addAction(timestamps); @@ -191,6 +211,18 @@ void log_viewer::show_context_menu(const QPoint& pos) QString filter_term = QInputDialog::getText(this, tr("Filter log"), tr("Enter text"), QLineEdit::EchoMode::Normal, m_filter_term, &ok); if (!ok) return; m_filter_term = std::move(filter_term); + update_title(); + filter_log(); + }); + + connect(exclude, &QAction::triggered, this, [this]() + { + bool ok = false; + QString exclude_term = QInputDialog::getText(this, tr("Exclude"), tr("Enter text (comma separated)"), QLineEdit::EchoMode::Normal, m_exclude_term, &ok); + if (!ok) return; + m_exclude_term = std::move(exclude_term); + m_exclude_terms = m_exclude_term.split(',', Qt::SkipEmptyParts); + update_title(); filter_log(); }); @@ -312,7 +344,7 @@ void log_viewer::filter_log() if (!m_log_levels.test(static_cast(logs::level::notice))) excluded_log_levels.push_back("·! "); if (!m_log_levels.test(static_cast(logs::level::trace))) excluded_log_levels.push_back("·T "); - if (m_filter_term.isEmpty() && excluded_log_levels.empty() && m_show_timestamps && m_show_threads && !m_last_actions_only) + if (m_filter_term.isEmpty() && m_exclude_terms.isEmpty() && excluded_log_levels.empty() && m_show_timestamps && m_show_threads && !m_last_actions_only) { set_text_and_keep_position(m_full_log); return; @@ -334,30 +366,40 @@ void log_viewer::filter_log() return; } } + + for (QStringView term : m_exclude_terms) + { + if (line.contains(term)) + { + return; + } + } } - if (m_filter_term.isEmpty() || line.contains(m_filter_term)) + if (!m_filter_term.isEmpty() && !line.contains(m_filter_term)) { - if (line.isEmpty()) - { - result += "\n"; - return; - } + return; + } - if (!m_show_timestamps) - { - line.remove(timestamp_regexp); - } + if (line.isEmpty()) + { + result += "\n"; + return; + } - if (!m_show_threads) - { - line.remove(thread_regexp); - } + if (!m_show_timestamps) + { + line.remove(timestamp_regexp); + } - if (!line.isEmpty()) - { - result += line + "\n"; - } + if (!m_show_threads) + { + line.remove(thread_regexp); + } + + if (!line.isEmpty()) + { + result += line + "\n"; } }; diff --git a/rpcs3/rpcs3qt/log_viewer.h b/rpcs3/rpcs3qt/log_viewer.h index 85ece2688b..d6ba2ff2a4 100644 --- a/rpcs3/rpcs3qt/log_viewer.h +++ b/rpcs3/rpcs3qt/log_viewer.h @@ -23,6 +23,7 @@ private Q_SLOTS: void show_context_menu(const QPoint& pos); private: + void update_title(); void set_text_and_keep_position(const QString& text); void filter_log(); bool is_valid_file(const QMimeData& md, bool save = false); @@ -30,6 +31,8 @@ private: std::shared_ptr m_gui_settings; QString m_path_last; QString m_filter_term; + QString m_exclude_term; + QStringList m_exclude_terms; QString m_full_log; QPlainTextEdit* m_log_text; LogHighlighter* m_log_highlighter; From 98aaafe4a4ba7f0b28686bbe91141123ccef0f46 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 19 Jan 2026 08:28:08 +0100 Subject: [PATCH 33/40] Update libpng to 1.6.54 --- 3rdparty/libpng/libpng | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdparty/libpng/libpng b/3rdparty/libpng/libpng index 4e3f57d50f..02f2b4f469 160000 --- a/3rdparty/libpng/libpng +++ b/3rdparty/libpng/libpng @@ -1 +1 @@ -Subproject commit 4e3f57d50f552841550a36eabbb3fbcecacb7750 +Subproject commit 02f2b4f4699f0ef9111a6534f093b53732df4452 From 7a6b34cac398c415d6efb728c2789ad998319019 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Tue, 3 Feb 2026 08:47:55 +0100 Subject: [PATCH 34/40] Update Qt to 6.10.2 --- .github/workflows/rpcs3.yml | 6 +++--- BUILDING.md | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/rpcs3.yml b/.github/workflows/rpcs3.yml index 1cd5bfbfd8..90ee8555ad 100644 --- a/.github/workflows/rpcs3.yml +++ b/.github/workflows/rpcs3.yml @@ -134,7 +134,7 @@ jobs: runs-on: macos-14 env: CCACHE_DIR: /tmp/ccache_dir - QT_VER: '6.10.1' + QT_VER: '6.10.2' QT_VER_MAIN: '6' LLVM_COMPILER_VER: '21' RELEASE_MESSAGE: ../GitHubReleaseMessage.txt @@ -213,9 +213,9 @@ jobs: env: COMPILER: msvc QT_VER_MAIN: '6' - QT_VER: '6.10.1' + QT_VER: '6.10.2' QT_VER_MSVC: 'msvc2022' - QT_DATE: '202511161843' + QT_DATE: '202601261212' LLVM_VER: '19.1.7' VULKAN_VER: '1.3.268.0' VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5' diff --git a/BUILDING.md b/BUILDING.md index 26295d0a16..b31b3fee4e 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -20,26 +20,26 @@ The following tools are required to build RPCS3 on Windows 10 or later: with standalone **CMake** tool. - [Python 3.6+](https://www.python.org/downloads/) (add to PATH) -- [Qt 6.10.1](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt) +- [Qt 6.10.2](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt) - [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (see "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0. The `sln` solution available only on **Visual Studio** is the preferred building solution. It easily allows to build the **RPCS3** application in `Release` and `Debug` mode. In order to build **RPCS3** with the `sln` solution (with **Visual Studio**), **Qt** libs need to be detected. To detect the libs: -- add and set the `QTDIR` environment variable, e.g. `\6.10.1\msvc2022_64\` +- add and set the `QTDIR` environment variable, e.g. `\6.10.2\msvc2022_64\` - or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2022) **NOTE:** If you have issues with the **Visual Studio Qt Plugin**, you may want to uninstall it and install the [Legacy Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.LEGACYQtVisualStudioTools2022) instead. In order to build **RPCS3** with the `CMake` solution (with both **Visual Studio** and standalone **CMake** tool): -- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `\6.10.1\msvc2022_64\` +- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `\6.10.2\msvc2022_64\` ### Linux These are the essentials tools to build RPCS3 on Linux. Some of them can be installed through your favorite package manager: - Clang 17+ or GCC 13+ - [CMake 3.28.0+](https://www.cmake.org/download/) -- [Qt 6.10.1](https://www.qt.io/download-qt-installer) +- [Qt 6.10.2](https://www.qt.io/download-qt-installer) - [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0. - [SDL3](https://github.com/libsdl-org/SDL/releases) (for the FAudio backend) @@ -123,7 +123,7 @@ Start **Visual Studio**, click on `Open a project or solution` and select the `r ##### Configuring the Qt Plugin (if used) 1) go to `Extensions->Qt VS Tools->Qt Versions` -2) add the path to your Qt installation with compiler e.g. `\6.10.1\msvc2022_64`, version will fill in automatically +2) add the path to your Qt installation with compiler e.g. `\6.10.2\msvc2022_64`, version will fill in automatically 3) go to `Extensions->Qt VS Tools->Options->Legacy Project Format`. (Only available in the **Legacy Qt Plugin**) 4) set `Build: Run pre-build setup` to `true`. (Only available in the **Legacy Qt Plugin**) From 43b2ce65773d2edc00a4499b40607cbdc7e70c81 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Tue, 3 Feb 2026 09:37:39 +0100 Subject: [PATCH 35/40] MouseHandler: minor cleanup --- rpcs3/Emu/Io/MouseHandler.cpp | 6 +++--- rpcs3/Emu/Io/MouseHandler.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rpcs3/Emu/Io/MouseHandler.cpp b/rpcs3/Emu/Io/MouseHandler.cpp index 9fd37463cd..7c4edcb449 100644 --- a/rpcs3/Emu/Io/MouseHandler.cpp +++ b/rpcs3/Emu/Io/MouseHandler.cpp @@ -33,12 +33,12 @@ void MouseHandlerBase::save(utils::serial& ar) bool MouseHandlerBase::is_time_for_update(double elapsed_time_ms) { - steady_clock::time_point now = steady_clock::now(); - const double elapsed_ms = (now - last_update).count() / 1'000'000.; + const steady_clock::time_point now = steady_clock::now(); + const double elapsed_ms = (now - m_last_update).count() / 1'000'000.; if (elapsed_ms > elapsed_time_ms) { - last_update = now; + m_last_update = now; return true; } return false; diff --git a/rpcs3/Emu/Io/MouseHandler.h b/rpcs3/Emu/Io/MouseHandler.h index 6a77f44d0e..4b31a6a60d 100644 --- a/rpcs3/Emu/Io/MouseHandler.h +++ b/rpcs3/Emu/Io/MouseHandler.h @@ -128,7 +128,7 @@ class MouseHandlerBase protected: MouseInfo m_info{}; std::vector m_mice; - steady_clock::time_point last_update{}; + steady_clock::time_point m_last_update{}; bool is_time_for_update(double elapsed_time_ms = 10.0); // 4-10 ms, let's use 10 for now From ebf9374ccdfe9bc1d8a9535d6b3c5335e03e9ac6 Mon Sep 17 00:00:00 2001 From: silviolet Date: Tue, 3 Feb 2026 19:27:17 -0500 Subject: [PATCH 36/40] Fixed typos in rpcs3/System.cpp - changed string containing a typo buyes -> bytes - capitalized ps2/ps3 to PS2/PS3 --- rpcs3/Emu/System.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index b204cc38b9..717e4ab59a 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -252,7 +252,7 @@ void init_fxo_for_exec(utils::serial* ar, bool full = false) // Reserved area if (!load_and_check_reserved(*ar, advance)) { - sys_log.error("Potential failure to load savestate: padding buyes are not 0. %s", *ar); + sys_log.error("Potential failure to load savestate: padding bytes are not 0. %s", *ar); } } } @@ -310,7 +310,7 @@ static void fixup_settings(const psf::registry* _psf) if (g_cfg.net.net_active == np_internet_status::disabled && g_cfg.net.psn_status != np_psn_status::disabled) { - sys_log.warning("Net status was set to disconnected so psn status was disabled"); + sys_log.warning("Net status was set to disconnected so PSN status was disabled."); g_cfg.net.psn_status.set(np_psn_status::disabled); } } @@ -4642,7 +4642,7 @@ game_boot_result Emulator::InsertDisc(const std::string& path) else { // TODO: find out where other discs are mounted - sys_log.todo("Mounting non-ps2/ps3 disc in dev_bdvd. Is this correct? (path='%s')", disc_root); + sys_log.todo("Mounting non-PS2/PS3 disc in dev_bdvd. Is this correct? (path='%s')", disc_root); ensure(vfs::mount("/dev_bdvd", disc_root)); } From 93fd33a19aa6f9b0c3e6ff34c13af824c2e226ff Mon Sep 17 00:00:00 2001 From: Malcolm Date: Fri, 6 Feb 2026 02:22:27 +0000 Subject: [PATCH 37/40] ARM: Use ISB instead of yield in place of x86 pause ISB isn't an exact match for pause, but it does slow down execution at least a litle. Unfortunately, yield does nothing on machines without SMT (99% of aarch64 machines) --- rpcs3/util/asm.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/util/asm.hpp b/rpcs3/util/asm.hpp index 56aa955652..0aea4c10c2 100644 --- a/rpcs3/util/asm.hpp +++ b/rpcs3/util/asm.hpp @@ -175,7 +175,7 @@ namespace utils inline void pause() { #if defined(ARCH_ARM64) - __asm__ volatile("yield"); + __asm__ volatile("isb" ::: "memory"); #elif defined(ARCH_X64) _mm_pause(); #else From 93dbdead24e1474a94c59fffc1f6cfb25abe488b Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Fri, 6 Feb 2026 06:52:00 +0100 Subject: [PATCH 38/40] Improve add friend logging/dialogs --- rpcs3/Emu/NP/rpcn_client.cpp | 17 ++++---- rpcs3/Emu/NP/rpcn_client.h | 2 +- rpcs3/rpcs3qt/rpcn_settings_dialog.cpp | 54 +++++++++++++++++++------- rpcs3/rpcs3qt/rpcn_settings_dialog.h | 1 + 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/rpcs3/Emu/NP/rpcn_client.cpp b/rpcs3/Emu/NP/rpcn_client.cpp index c1126b8698..d7bb274c66 100644 --- a/rpcs3/Emu/NP/rpcn_client.cpp +++ b/rpcs3/Emu/NP/rpcn_client.cpp @@ -1467,7 +1467,7 @@ namespace rpcn return error; } - bool rpcn_client::add_friend(const std::string& friend_username) + std::optional rpcn_client::add_friend(const std::string& friend_username) { std::vector data; std::copy(friend_username.begin(), friend_username.end(), std::back_inserter(data)); @@ -1478,19 +1478,18 @@ namespace rpcn std::vector packet_data; if (!forge_send_reply(CommandType::AddFriend, req_id, data, packet_data)) { - return false; + return std::nullopt; } vec_stream reply(packet_data); - auto error = static_cast(reply.get()); + const auto error = static_cast(reply.get()); - if (error != rpcn::ErrorType::NoError) - { - return false; - } + if (error == ErrorType::NoError) + rpcn_log.success("add_friend(\"%s\") succeeded", friend_username); + else + rpcn_log.error("add_friend(\"%s\") failed with error: %s", error); - rpcn_log.success("You have successfully added \"%s\" as a friend", friend_username); - return true; + return error; } bool rpcn_client::remove_friend(const std::string& friend_username) diff --git a/rpcs3/Emu/NP/rpcn_client.h b/rpcs3/Emu/NP/rpcn_client.h index 035dc9cf3c..56ba17d04d 100644 --- a/rpcs3/Emu/NP/rpcn_client.h +++ b/rpcs3/Emu/NP/rpcn_client.h @@ -293,7 +293,7 @@ namespace rpcn ErrorType send_reset_token(std::string_view npid, std::string_view email); ErrorType reset_password(std::string_view npid, std::string_view token, std::string_view password); ErrorType delete_account(); - bool add_friend(const std::string& friend_username); + std::optional add_friend(const std::string& friend_username); bool remove_friend(const std::string& friend_username); u32 get_num_friends(); diff --git a/rpcs3/rpcs3qt/rpcn_settings_dialog.cpp b/rpcs3/rpcs3qt/rpcn_settings_dialog.cpp index 53097f29fc..6de6007b31 100644 --- a/rpcs3/rpcs3qt/rpcn_settings_dialog.cpp +++ b/rpcs3/rpcs3qt/rpcn_settings_dialog.cpp @@ -1262,13 +1262,10 @@ rpcn_friends_dialog::rpcn_friends_dialog(QWidget* parent) connect(accept_request_action, &QAction::triggered, this, [this, str_sel_friend]() { - if (!m_rpcn->add_friend(str_sel_friend)) - { - QMessageBox::critical(this, tr("Error adding a friend!"), tr("An error occurred while trying to add a friend!"), QMessageBox::Ok); - } - else + if (add_friend_with_error_dialog(str_sel_friend)) { QMessageBox::information(this, tr("Friend added!"), tr("You've successfully added a friend!"), QMessageBox::Ok); + return; } }); @@ -1304,11 +1301,8 @@ rpcn_friends_dialog::rpcn_friends_dialog(QWidget* parent) connect(send_friend_request_action, &QAction::triggered, this, [this, str_sel_friend]() { - if (!m_rpcn->add_friend(str_sel_friend)) - { - QMessageBox::critical(this, tr("Error sending a friend request!"), tr("An error occurred while trying to send a friend request!"), QMessageBox::Ok); + if (!add_friend_with_error_dialog(str_sel_friend)) return; - } QString qstr_friend = QString::fromStdString(str_sel_friend); add_update_list(m_lst_requests, qstr_friend, m_icon_request_sent, QVariant(false)); @@ -1341,11 +1335,7 @@ rpcn_friends_dialog::rpcn_friends_dialog(QWidget* parent) QMessageBox::critical(this, tr("Error validating username!"), tr("The username you entered is invalid!"), QMessageBox::Ok); } - if (!m_rpcn->add_friend(str_friend_username)) - { - QMessageBox::critical(this, tr("Error adding friend!"), tr("An error occurred while adding a friend!"), QMessageBox::Ok); - } - else + if (add_friend_with_error_dialog(str_friend_username)) { add_update_list(m_lst_requests, QString::fromStdString(str_friend_username), m_icon_request_sent, QVariant(false)); QMessageBox::information(this, tr("Friend added!"), tr("Friend was successfully added!"), QMessageBox::Ok); @@ -1360,6 +1350,42 @@ rpcn_friends_dialog::~rpcn_friends_dialog() m_rpcn->remove_friend_cb(friend_callback, this); } +bool rpcn_friends_dialog::add_friend_with_error_dialog(const std::string& friend_username) +{ + QString err_msg; + const auto opt_error = m_rpcn->add_friend(friend_username); + + if (opt_error.has_value()) + { + const auto error = opt_error.value(); + + if (error != rpcn::ErrorType::NoError) + { + switch (error) + { + case rpcn::ErrorType::NotFound: err_msg = tr("The specified username does not exist."); break; + case rpcn::ErrorType::InvalidInput: err_msg = tr("You cannot add yourself as a friend."); break; + case rpcn::ErrorType::Blocked: err_msg = tr("You or the other user have the other blocked."); break; + case rpcn::ErrorType::AlreadyFriend: err_msg = tr("You are already friends with this user."); break; + case rpcn::ErrorType::DbFail: err_msg = tr("A database error occurred. Please try again later."); break; + default: err_msg = tr("An unexpected error occurred."); break; + } + } + } + else + { + err_msg = tr("Failed to send the friend request."); + } + + if (!err_msg.isEmpty()) + { + QMessageBox::critical(this, tr("Friend Request Failed"), err_msg, QMessageBox::Ok); + return false; + } + + return true; +} + bool rpcn_friends_dialog::is_ok() const { return m_rpcn_ok; diff --git a/rpcs3/rpcs3qt/rpcn_settings_dialog.h b/rpcs3/rpcs3qt/rpcn_settings_dialog.h index 89d8253220..c28828e410 100644 --- a/rpcs3/rpcs3qt/rpcn_settings_dialog.h +++ b/rpcs3/rpcs3qt/rpcn_settings_dialog.h @@ -121,6 +121,7 @@ public: private: void add_update_list(QListWidget* list, const QString& name, const QIcon& icon, const QVariant& data); void remove_list(QListWidget* list, const QString& name); + bool add_friend_with_error_dialog(const std::string& friend_username); private Q_SLOTS: void add_update_friend(const QString& name, bool status); From aeaa62a28c36f352d5c2bf6bb4e1cadc4600ff00 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 8 Feb 2026 14:35:28 +0300 Subject: [PATCH 39/40] rsx/sync: Do not allow short-circuiting behavior when releasing GCM labels via host queue --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 4 ++-- rpcs3/Emu/RSX/GL/GLGSRender.h | 2 +- rpcs3/Emu/RSX/NV47/HW/nv406e.cpp | 4 ++-- rpcs3/Emu/RSX/NV47/HW/nv4097.cpp | 10 +++++----- rpcs3/Emu/RSX/NV47/HW/nv47_sync.hpp | 4 ++-- rpcs3/Emu/RSX/RSXThread.h | 2 +- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 11 ++++------- rpcs3/Emu/RSX/VK/VKGSRender.h | 2 +- 8 files changed, 18 insertions(+), 21 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index acf258cc56..ebff202303 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -1351,7 +1351,7 @@ void GLGSRender::notify_tile_unbound(u32 tile) } } -bool GLGSRender::release_GCM_label(u32 address, u32 args) +bool GLGSRender::release_GCM_label(u32 type, u32 address, u32 args) { if (!backend_config.supports_host_gpu_labels) { @@ -1360,7 +1360,7 @@ bool GLGSRender::release_GCM_label(u32 address, u32 args) auto host_ctx = ensure(m_host_dma_ctrl->host_ctx()); - if (host_ctx->texture_loads_completed()) + if (type == NV4097_TEXTURE_READ_SEMAPHORE_RELEASE && host_ctx->texture_loads_completed()) { // We're about to poll waiting for GPU state, ensure the context is still valid. gl::check_state(); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 5627216055..a05eb0bf3d 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -206,7 +206,7 @@ public: void discard_occlusion_query(rsx::reports::occlusion_query_info* query) override; // DMA - bool release_GCM_label(u32 address, u32 data) override; + bool release_GCM_label(u32 type, u32 address, u32 data) override; void enqueue_host_context_write(u32 offset, u32 size, const void* data); void on_guest_texture_read(); diff --git a/rpcs3/Emu/RSX/NV47/HW/nv406e.cpp b/rpcs3/Emu/RSX/NV47/HW/nv406e.cpp index cbb04d140a..4307cc8289 100644 --- a/rpcs3/Emu/RSX/NV47/HW/nv406e.cpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv406e.cpp @@ -86,7 +86,7 @@ namespace rsx RSX(ctx)->performance_counters.idle_time += (get_system_time() - start); } - void semaphore_release(context* ctx, u32 /*reg*/, u32 arg) + void semaphore_release(context* ctx, u32 reg, u32 arg) { const u32 offset = REGS(ctx)->semaphore_offset_406e(); @@ -122,7 +122,7 @@ namespace rsx arg = 1; } - util::write_gcm_label(ctx, addr, arg); + util::write_gcm_label(ctx, reg, addr, arg); } } } diff --git a/rpcs3/Emu/RSX/NV47/HW/nv4097.cpp b/rpcs3/Emu/RSX/NV47/HW/nv4097.cpp index 929925bcb1..17ee040f8c 100644 --- a/rpcs3/Emu/RSX/NV47/HW/nv4097.cpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv4097.cpp @@ -690,7 +690,7 @@ namespace rsx }); } - void texture_read_semaphore_release(context* ctx, u32 /*reg*/, u32 arg) + void texture_read_semaphore_release(context* ctx, u32 reg, u32 arg) { // Pipeline barrier seems to be equivalent to a SHADER_READ stage barrier. // Ideally the GPU only needs to have cached all textures declared up to this point before writing the label. @@ -715,15 +715,15 @@ namespace rsx if (g_cfg.video.strict_rendering_mode) [[ unlikely ]] { - util::write_gcm_label(ctx, addr, arg); + util::write_gcm_label(ctx, reg, addr, arg); } else { - util::write_gcm_label(ctx, addr, arg); + util::write_gcm_label(ctx, reg, addr, arg); } } - void back_end_write_semaphore_release(context* ctx, u32 /*reg*/, u32 arg) + void back_end_write_semaphore_release(context* ctx, u32 reg, u32 arg) { // Full pipeline barrier. GPU must flush pipeline before writing the label @@ -744,7 +744,7 @@ namespace rsx } const u32 val = (arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff); - util::write_gcm_label(ctx, addr, val); + util::write_gcm_label(ctx, reg, addr, val); } void sync(context* ctx, u32, u32) diff --git a/rpcs3/Emu/RSX/NV47/HW/nv47_sync.hpp b/rpcs3/Emu/RSX/NV47/HW/nv47_sync.hpp index 9f39f84c00..fe2522c31c 100644 --- a/rpcs3/Emu/RSX/NV47/HW/nv47_sync.hpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv47_sync.hpp @@ -13,13 +13,13 @@ namespace rsx namespace util { template - static void write_gcm_label(context* ctx, u32 address, u32 data) + static void write_gcm_label(context* ctx, u32 type, u32 address, u32 data) { const bool is_flip_sema = (address == (RSX(ctx)->label_addr + 0x10) || address == (RSX(ctx)->device_addr + 0x30)); if (!is_flip_sema) { // First, queue the GPU work. If it flushes the queue for us, the following routines will be faster. - const bool handled = RSX(ctx)->get_backend_config().supports_host_gpu_labels && RSX(ctx)->release_GCM_label(address, data); + const bool handled = RSX(ctx)->get_backend_config().supports_host_gpu_labels && RSX(ctx)->release_GCM_label(type, address, data); if (vm::_ref(address) == data) { diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 4f965dee80..4b2de0acc4 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -380,7 +380,7 @@ namespace rsx flags32_t read_barrier(u32 memory_address, u32 memory_range, bool unconditional); virtual void write_barrier(u32 /*memory_address*/, u32 /*memory_range*/) {} virtual void sync_hint(FIFO::interrupt_hint hint, reports::sync_hint_payload_t payload); - virtual bool release_GCM_label(u32 /*address*/, u32 /*value*/) { return false; } + virtual bool release_GCM_label(u32 /*type*/, u32 /*address*/, u32 /*value*/) { return false; } protected: diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index cba661a64b..8d90f9a09f 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1541,7 +1541,7 @@ std::pair VKGSRender::map_host_object_data( return { m_host_dma_ctrl->host_ctx(), m_host_object_data->value }; } -bool VKGSRender::release_GCM_label(u32 address, u32 args) +bool VKGSRender::release_GCM_label(u32 type, u32 address, u32 args) { if (!backend_config.supports_host_gpu_labels) { @@ -1550,7 +1550,7 @@ bool VKGSRender::release_GCM_label(u32 address, u32 args) auto host_ctx = ensure(m_host_dma_ctrl->host_ctx()); - if (host_ctx->texture_loads_completed()) + if (type == NV4097_TEXTURE_READ_SEMAPHORE_RELEASE && host_ctx->texture_loads_completed()) { // All texture loads already seen by the host GPU // Wait for all previously submitted labels to be flushed @@ -1572,13 +1572,10 @@ bool VKGSRender::release_GCM_label(u32 address, u32 args) const auto release_event_id = host_ctx->on_label_acquire(); + vk::insert_global_memory_barrier(*m_current_command_buffer); + if (host_ctx->has_unflushed_texture_loads()) { - if (vk::is_renderpass_open(*m_current_command_buffer)) - { - vk::end_renderpass(*m_current_command_buffer); - } - vkCmdUpdateBuffer(*m_current_command_buffer, mapping.second->value, mapping.first, 4, &write_data); flush_command_queue(); } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 0c93741fcb..f9feedc35a 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -254,7 +254,7 @@ public: // Sync void write_barrier(u32 address, u32 range) override; void sync_hint(rsx::FIFO::interrupt_hint hint, rsx::reports::sync_hint_payload_t payload) override; - bool release_GCM_label(u32 address, u32 data) override; + bool release_GCM_label(u32 type, u32 address, u32 data) override; void begin_occlusion_query(rsx::reports::occlusion_query_info* query) override; void end_occlusion_query(rsx::reports::occlusion_query_info* query) override; From 3bb21db71b4c6f73d6777ec4e7b1a2c3c3cdbe57 Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Mon, 9 Feb 2026 05:23:27 +0100 Subject: [PATCH 40/40] Guard async transactions against spurious wakeups --- rpcs3/Emu/NP/np_contexts.cpp | 2 +- rpcs3/Emu/NP/np_requests.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/NP/np_contexts.cpp b/rpcs3/Emu/NP/np_contexts.cpp index 46d773d127..f43d02c362 100644 --- a/rpcs3/Emu/NP/np_contexts.cpp +++ b/rpcs3/Emu/NP/np_contexts.cpp @@ -46,7 +46,7 @@ error_code generic_async_transaction_context::wait_for_completion() return *result; } - completion_cond.wait(lock); + completion_cond.wait(lock, [this] { return result.has_value(); }); return *result; } diff --git a/rpcs3/Emu/NP/np_requests.cpp b/rpcs3/Emu/NP/np_requests.cpp index 20199889dc..3f21f24cd3 100644 --- a/rpcs3/Emu/NP/np_requests.cpp +++ b/rpcs3/Emu/NP/np_requests.cpp @@ -951,13 +951,16 @@ namespace np { thread_base::set_name("NP Trans Worker"); - auto res = trans_ctx->wake_cond.wait_for(lock, std::chrono::microseconds(trans_ctx->timeout)); + bool has_value = trans_ctx->wake_cond.wait_for(lock, std::chrono::microseconds(trans_ctx->timeout), [&] + { + return trans_ctx->result.has_value(); + }); { std::lock_guard lock_threads(this->mutex_async_transactions); this->async_transactions.erase(req_id); } - if (res == std::cv_status::timeout) + if (!has_value) { trans_ctx->result = SCE_NP_COMMUNITY_ERROR_TIMEOUT; return;