From 4f2324cae7181bcb8c274840b17fe86d34cbf54a Mon Sep 17 00:00:00 2001 From: FlexBy420 <68403300+FlexBy420@users.noreply.github.com> Date: Sat, 24 May 2025 14:52:22 +0200 Subject: [PATCH 001/384] Remove roadmap link from README Roadmap was removed from the website as it wasn't updated in years. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 669a0879a1..c47af8d204 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,6 @@ If you want to contribute as a developer, please take a look at the following pa * [Coding Style](https://github.com/RPCS3/rpcs3/wiki/Coding-Style) * [Developer Information](https://github.com/RPCS3/rpcs3/wiki/Developer-Information) -* [Roadmap](https://rpcs3.net/roadmap) You should also contact any of the developers in the forums or in the Discord server to learn more about the current state of the emulator. From da273761d17ab5a033815ee954a8f1759a3943da Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sat, 24 May 2025 04:45:35 +0200 Subject: [PATCH 002/384] Fix some static analysis warnings --- rpcs3/Emu/RSX/Program/CgBinaryProgram.h | 8 ++-- rpcs3/Emu/RSX/RSXZCULL.h | 3 +- rpcs3/Emu/RSX/VK/vkutils/garbage_collector.h | 2 +- rpcs3/rpcs3qt/memory_viewer_panel.cpp | 42 +++++++++++--------- rpcs3/rpcs3qt/midi_creator.cpp | 7 ++-- rpcs3/rpcs3qt/recvmessage_dialog_frame.h | 2 +- rpcs3/rpcs3qt/skylander_dialog.cpp | 5 ++- 7 files changed, 36 insertions(+), 33 deletions(-) diff --git a/rpcs3/Emu/RSX/Program/CgBinaryProgram.h b/rpcs3/Emu/RSX/Program/CgBinaryProgram.h index 56d8f4d70b..f956c93035 100644 --- a/rpcs3/Emu/RSX/Program/CgBinaryProgram.h +++ b/rpcs3/Emu/RSX/Program/CgBinaryProgram.h @@ -143,10 +143,10 @@ class CgBinaryDisasm std::vector m_loop_end_offsets; // VP members - u32 m_sca_opcode; - u32 m_vec_opcode; - static const usz m_max_instr_count = 512; - usz m_instr_count; + u32 m_sca_opcode = 0; + u32 m_vec_opcode = 0; + static constexpr usz m_max_instr_count = 512; + usz m_instr_count = 0; std::vector m_data; public: diff --git a/rpcs3/Emu/RSX/RSXZCULL.h b/rpcs3/Emu/RSX/RSXZCULL.h index 4627fa2ca5..679357b457 100644 --- a/rpcs3/Emu/RSX/RSXZCULL.h +++ b/rpcs3/Emu/RSX/RSXZCULL.h @@ -18,9 +18,8 @@ namespace rsx static inline std::string_view location_tostring(u32 location) { - ensure(location < 2); constexpr const char* location_names[2] = { "CELL_GCM_LOCATION_LOCAL", "CELL_GCM_LOCATION_MAIN" }; - return location_names[location]; + return ::at32(location_names, location); } static inline u32 classify_location(u32 address) diff --git a/rpcs3/Emu/RSX/VK/vkutils/garbage_collector.h b/rpcs3/Emu/RSX/VK/vkutils/garbage_collector.h index 3ca3c5e02c..48d531f18d 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/garbage_collector.h +++ b/rpcs3/Emu/RSX/VK/vkutils/garbage_collector.h @@ -16,7 +16,7 @@ namespace vk disposable_t() = delete; disposable_t(const disposable_t&) = delete; - disposable_t(disposable_t&& other) : + disposable_t(disposable_t&& other) noexcept : ptr(std::exchange(other.ptr, nullptr)), deleter(other.deleter) {} diff --git a/rpcs3/rpcs3qt/memory_viewer_panel.cpp b/rpcs3/rpcs3qt/memory_viewer_panel.cpp index c381b18404..d2d03f01b9 100644 --- a/rpcs3/rpcs3qt/memory_viewer_panel.cpp +++ b/rpcs3/rpcs3qt/memory_viewer_panel.cpp @@ -425,7 +425,7 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, std::shared_ptrtext()).toULong(&ok, 16); @@ -433,17 +433,17 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, std::shared_ptr(&QSpinBox::valueChanged), [=, this]() + connect(sb_words, static_cast(&QSpinBox::valueChanged), this, [=, this]() { m_colcount = 1 << sb_words->value(); ShowMemory(); }); - connect(b_prev, &QAbstractButton::clicked, [this]() { scroll(-1); }); - connect(b_next, &QAbstractButton::clicked, [this]() { scroll(1); }); - connect(b_fprev, &QAbstractButton::clicked, [this]() { scroll(m_rowcount * -1); }); - connect(b_fnext, &QAbstractButton::clicked, [this]() { scroll(m_rowcount); }); - connect(b_img, &QAbstractButton::clicked, [=, this]() + connect(b_prev, &QAbstractButton::clicked, this, [this]() { scroll(-1); }); + connect(b_next, &QAbstractButton::clicked, this, [this]() { scroll(1); }); + connect(b_fprev, &QAbstractButton::clicked, this, [this]() { scroll(m_rowcount * -1); }); + connect(b_fnext, &QAbstractButton::clicked, this, [this]() { scroll(m_rowcount); }); + connect(b_img, &QAbstractButton::clicked, this, [=, this]() { const color_format format = cbox_img_mode->currentData().value(); const int sizex = sb_img_size_x->value(); @@ -580,7 +580,7 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, std::shared_ptr(id); - connect(this, &memory_viewer_panel::finished, [handle_ptr = std::move(handle_ptr), id, this](int) + connect(this, &memory_viewer_panel::finished, this, [handle_ptr = std::move(handle_ptr), id, this](int) { if (m_search_thread) { @@ -617,7 +617,7 @@ memory_viewer_panel::~memory_viewer_panel() void memory_viewer_panel::wheelEvent(QWheelEvent *event) { - // Set some scrollspeed modifiers: + // Set some scroll speed modifiers: u32 step_size = 1; if (event->modifiers().testFlag(Qt::ControlModifier)) step_size *= m_rowcount; @@ -986,6 +986,7 @@ void memory_viewer_panel::ShowImage(QWidget* parent, u32 addr, color_format form const u32 memsize = utils::mul_saturate(utils::mul_saturate(texel_bytes, width), height); if (memsize == 0) { + gui_log.error("Can not show image. memsize is 0 (texel_bytes=%d, width=%d, height=%d)", texel_bytes, width, height); return; } @@ -993,6 +994,7 @@ void memory_viewer_panel::ShowImage(QWidget* parent, u32 addr, color_format form if (!originalBuffer) { + gui_log.error("Can not show image. originalBuffer is null (addr=%d, memsize=%d)", addr, memsize); return; } @@ -1001,6 +1003,7 @@ void memory_viewer_panel::ShowImage(QWidget* parent, u32 addr, color_format form if (!convertedBuffer) { // OOM or invalid memory address, give up + gui_log.error("Can not show image. convertedBuffer is null (addr=%d, memsize=%d)", addr, memsize); return; } @@ -1014,7 +1017,7 @@ void memory_viewer_panel::ShowImage(QWidget* parent, u32 addr, color_format form { const u32 offset = y * pitch; const u32 offset_new = y * pitch_new; - for (u32 x = 0, x_new = 0; x < pitch; x += 3, x_new += 4) + for (u32 x = 0, x_new = 0; x < pitch && x_new < pitch_new; x += 3, x_new += 4) { convertedBuffer[offset_new + x_new + 0] = originalBuffer[offset + x + 2]; convertedBuffer[offset_new + x_new + 1] = originalBuffer[offset + x + 1]; @@ -1116,19 +1119,20 @@ void memory_viewer_panel::ShowImage(QWidget* parent, u32 addr, color_format form } // Flip vertically - if (flipv && height > 1 && memsize > 1) + if (flipv && width > 0 && height > 1 && memsize > 1) { const u32 pitch = width * 4; + std::vector tmp_row(pitch); + for (u32 y = 0; y < height / 2; y++) { - const u32 offset = y * pitch; - const u32 flip_offset = (height - y - 1) * pitch; - for (u32 x = 0; x < pitch; x++) - { - const u8 tmp = convertedBuffer[offset + x]; - convertedBuffer[offset + x] = convertedBuffer[flip_offset + x]; - convertedBuffer[flip_offset + x] = tmp; - } + u8* row_top = &convertedBuffer[y * pitch]; + u8* row_bottom = &convertedBuffer[(height - y - 1) * pitch]; + + // Swap rows + std::memcpy(tmp_row.data(), row_top, pitch); + std::memcpy(row_top, row_bottom, pitch); + std::memcpy(row_bottom, tmp_row.data(), pitch); } } diff --git a/rpcs3/rpcs3qt/midi_creator.cpp b/rpcs3/rpcs3qt/midi_creator.cpp index 0a61eeae9b..57476af3d6 100644 --- a/rpcs3/rpcs3qt/midi_creator.cpp +++ b/rpcs3/rpcs3qt/midi_creator.cpp @@ -86,13 +86,12 @@ std::array midi_creator::get_selection_list() con std::string midi_creator::set_device(u32 num, const midi_device& device) { - ensure(num < m_sel_list.size()); - - m_sel_list[num] = device; + midi_device& dev = ::at32(m_sel_list, num); + dev = device; if (device.name == get_none().toStdString()) { - m_sel_list[num].name.clear(); + dev.name.clear(); } std::string result; diff --git a/rpcs3/rpcs3qt/recvmessage_dialog_frame.h b/rpcs3/rpcs3qt/recvmessage_dialog_frame.h index 10b9bd87e9..16303daa46 100644 --- a/rpcs3/rpcs3qt/recvmessage_dialog_frame.h +++ b/rpcs3/rpcs3qt/recvmessage_dialog_frame.h @@ -11,7 +11,7 @@ struct recvmessage_signal_struct { shared_ptr> msg; - u64 msg_id; + u64 msg_id = 0; }; Q_DECLARE_METATYPE(recvmessage_signal_struct); diff --git a/rpcs3/rpcs3qt/skylander_dialog.cpp b/rpcs3/rpcs3qt/skylander_dialog.cpp index beebb8a965..94d9025a17 100644 --- a/rpcs3/rpcs3qt/skylander_dialog.cpp +++ b/rpcs3/rpcs3qt/skylander_dialog.cpp @@ -17,7 +17,7 @@ skylander_dialog* skylander_dialog::inst = nullptr; std::optional> skylander_dialog::sky_slots[UI_SKY_NUM]; QString last_skylander_path; -const std::map, const std::string> list_skylanders = { +static const std::map, const std::string> list_skylanders = { {{0, 0x0000}, "Whirlwind"}, {{0, 0x1801}, "Series 2 Whirlwind"}, {{0, 0x1C02}, "Polar Whirlwind"}, @@ -502,7 +502,8 @@ const std::map, const std::string> list_sk u16 skylander_crc16(u16 init_value, const u8* buffer, u32 size) { - const unsigned short CRC_CCITT_TABLE[256] = {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, + constexpr unsigned short CRC_CCITT_TABLE[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, From 09ab5477e881b0592f336122799165e52bd03157 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sat, 24 May 2025 04:45:54 +0200 Subject: [PATCH 003/384] rsx: use more const ref --- rpcs3/Emu/RSX/GL/GLDraw.cpp | 8 ++++---- rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp | 6 +++--- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 2 +- rpcs3/Emu/RSX/GL/GLTexture.cpp | 2 +- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 2 +- rpcs3/Emu/RSX/VK/VKResourceManager.cpp | 2 +- rpcs3/Emu/RSX/VK/vkutils/image.cpp | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index 1a0515ef48..955bfbd59b 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -569,7 +569,7 @@ void GLGSRender::emit_geometry(u32 sub_index) if (vertex_state && !m_vertex_layout.validate()) { // No vertex inputs enabled - // Execute remainining pipeline barriers with NOP draw + // Execute remaining pipeline barriers with NOP draw do { draw_call.execute_pipeline_dependencies(m_ctx); @@ -619,9 +619,9 @@ void GLGSRender::emit_geometry(u32 sub_index) } else { - const auto subranges = draw_call.get_subranges(); + const auto& subranges = draw_call.get_subranges(); const auto draw_count = subranges.size(); - const auto driver_caps = gl::get_driver_caps(); + const auto& driver_caps = gl::get_driver_caps(); bool use_draw_arrays_fallback = false; m_scratch_buffer.resize(draw_count * 24); @@ -631,7 +631,7 @@ void GLGSRender::emit_geometry(u32 sub_index) u32 first = 0; u32 dst_index = 0; - for (const auto &range : subranges) + for (const auto& range : subranges) { firsts[dst_index] = first; counts[dst_index] = range.count; diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index 3f65be3bae..3c95d571d3 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -33,7 +33,7 @@ void GLFragmentDecompilerThread::insertHeader(std::stringstream & OS) if (device_props.has_native_half_support) { - const auto driver_caps = gl::get_driver_caps(); + const auto& driver_caps = gl::get_driver_caps(); if (driver_caps.NV_gpu_shader5_supported) { required_extensions.push_back("GL_NV_gpu_shader5"); @@ -47,7 +47,7 @@ void GLFragmentDecompilerThread::insertHeader(std::stringstream & OS) if (properties.multisampled_sampler_mask) { // Requires this extension or GLSL 450 - const auto driver_caps = gl::get_driver_caps(); + const auto& driver_caps = gl::get_driver_caps(); if (driver_caps.glsl_version.version >= 450) { gl_version = 450; @@ -366,7 +366,7 @@ void GLFragmentProgram::Decompile(const RSXFragmentProgram& prog) if (g_cfg.video.shader_precision == gpu_preset_level::low) { - const auto driver_caps = gl::get_driver_caps(); + const auto& driver_caps = gl::get_driver_caps(); decompiler.device_props.has_native_half_support = driver_caps.NV_gpu_shader5_supported || driver_caps.AMD_gpu_shader_half_float_supported; decompiler.device_props.has_low_precision_rounding = driver_caps.vendor_NVIDIA; } diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 6101bd70c1..b6c27c4dd8 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -148,7 +148,7 @@ void GLGSRender::on_init_thread() rsx_log.success("GL VERSION: %s", reinterpret_cast(glGetString(GL_VERSION))); rsx_log.success("GLSL VERSION: %s", reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION))); - auto& gl_caps = gl::get_driver_caps(); + const auto& gl_caps = gl::get_driver_caps(); std::vector exception_reasons; if (!gl_caps.ARB_texture_buffer_object_supported) diff --git a/rpcs3/Emu/RSX/GL/GLTexture.cpp b/rpcs3/Emu/RSX/GL/GLTexture.cpp index a0711d52d7..0c34690bf4 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.cpp +++ b/rpcs3/Emu/RSX/GL/GLTexture.cpp @@ -582,7 +582,7 @@ namespace gl const std::vector &input_layouts, bool is_swizzled, GLenum gl_format, GLenum gl_type, rsx::simple_array& staging_buffer) { - const auto driver_caps = gl::get_driver_caps(); + const auto& driver_caps = gl::get_driver_caps(); rsx::texture_uploader_capabilities caps { .supports_byteswap = true, diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 2c7699407e..9ac52774ea 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -565,7 +565,7 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar) m_fragment_texture_params_buffer_info = { m_fragment_texture_params_ring_info.heap->value, 0, 16 }; m_raster_env_buffer_info = { m_raster_env_ring_info.heap->value, 0, 128 }; - const auto limits = m_device->gpu().get_limits(); + const auto& limits = m_device->gpu().get_limits(); m_texbuffer_view_size = std::min(limits.maxTexelBufferElements, VK_ATTRIB_RING_BUFFER_SIZE_M * 0x100000u); if (m_texbuffer_view_size < 0x800000) diff --git a/rpcs3/Emu/RSX/VK/VKResourceManager.cpp b/rpcs3/Emu/RSX/VK/VKResourceManager.cpp index 3c9eff4ef3..9d34509a09 100644 --- a/rpcs3/Emu/RSX/VK/VKResourceManager.cpp +++ b/rpcs3/Emu/RSX/VK/VKResourceManager.cpp @@ -50,7 +50,7 @@ namespace vk { // For any managed resources, try to keep the number of unused/idle resources as low as possible. // Improves search times as well as keeping us below the hardware limit. - const auto limits = get_current_renderer()->gpu().get_limits(); + const auto& limits = get_current_renderer()->gpu().get_limits(); const auto allocated_sampler_count = vmm_get_application_pool_usage(VMM_ALLOCATION_POOL_SAMPLER); const auto max_allowed_samplers = std::min((limits.maxSamplerAllocationCount * 3u) / 4u, 2048u); diff --git a/rpcs3/Emu/RSX/VK/vkutils/image.cpp b/rpcs3/Emu/RSX/VK/vkutils/image.cpp index 3146552f56..1aa90648ce 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/image.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/image.cpp @@ -11,7 +11,7 @@ namespace vk { void image::validate(const vk::render_device& dev, const VkImageCreateInfo& info) const { - const auto gpu_limits = dev.gpu().get_limits(); + const auto& gpu_limits = dev.gpu().get_limits(); u32 longest_dim, dim_limit; switch (info.imageType) From 3aba805bc976fbb51b5d4202c9222af5eb24f781 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sat, 24 May 2025 04:46:51 +0200 Subject: [PATCH 004/384] rsx: Fix use after move warning --- rpcs3/Emu/RSX/Common/surface_store.h | 1 + 1 file changed, 1 insertion(+) diff --git a/rpcs3/Emu/RSX/Common/surface_store.h b/rpcs3/Emu/RSX/Common/surface_store.h index 35813965e0..9b266a54ed 100644 --- a/rpcs3/Emu/RSX/Common/surface_store.h +++ b/rpcs3/Emu/RSX/Common/surface_store.h @@ -504,6 +504,7 @@ namespace rsx { // Exchange this surface with the invalidated one surface = std::move(old_surface_storage); + old_surface_storage = {}; } else { From 3e674a896f9e70ee7112c89c0a2a07f0df4d2326 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sat, 24 May 2025 04:47:26 +0200 Subject: [PATCH 005/384] Minor struct memory layout optimization --- rpcs3/Emu/Io/pad_types.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/Io/pad_types.h b/rpcs3/Emu/Io/pad_types.h index 710edb2743..e6761a295f 100644 --- a/rpcs3/Emu/Io/pad_types.h +++ b/rpcs3/Emu/Io/pad_types.h @@ -459,11 +459,11 @@ struct VibrateMotor struct ps_move_data { - bool external_device_connected = false; u32 external_device_id = 0; - std::array external_device_data{}; std::array external_device_read{}; // CELL_GEM_EXTERNAL_PORT_DEVICE_INFO_SIZE std::array external_device_write{}; // CELL_GEM_EXTERNAL_PORT_OUTPUT_SIZE + std::array external_device_data{}; + bool external_device_connected = false; bool external_device_read_requested = false; bool external_device_write_requested = false; From 1ff6bdd77799b817b9002b00d2bdfc05a2638f77 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 25 May 2025 20:00:19 +0300 Subject: [PATCH 006/384] rsx: Flush MM queue before applying nv3089 block transfers --- rpcs3/Emu/RSX/Host/MM.cpp | 25 +++++++++++++++++++++++++ rpcs3/Emu/RSX/Host/MM.h | 4 ++++ rpcs3/Emu/RSX/NV47/HW/nv0039.cpp | 8 ++++++++ 3 files changed, 37 insertions(+) diff --git a/rpcs3/Emu/RSX/Host/MM.cpp b/rpcs3/Emu/RSX/Host/MM.cpp index cf21b6e046..613f05e828 100644 --- a/rpcs3/Emu/RSX/Host/MM.cpp +++ b/rpcs3/Emu/RSX/Host/MM.cpp @@ -90,6 +90,31 @@ namespace rsx } } + void mm_flush(const rsx::simple_array& ranges) + { + std::lock_guard lock(g_mprotect_queue_lock); + if (g_deferred_mprotect_queue.empty()) + { + return; + } + + const auto ranges64 = ranges.map([](const auto& r) + { + const u64 start = reinterpret_cast(vm::base(r.start)); + const u64 end = start + r.length(); + return std::make_pair(start, end); + }); + + for (const auto& block : g_deferred_mprotect_queue) + { + if (ranges64.any(FN(block.overlaps(x.first, x.second)))) + { + mm_flush_mprotect_queue_internal(); + return; + } + } + } + void mm_flush_lazy() { if (!g_cfg.video.multithreaded_rsx) diff --git a/rpcs3/Emu/RSX/Host/MM.h b/rpcs3/Emu/RSX/Host/MM.h index e9415a685f..0c70a81aa5 100644 --- a/rpcs3/Emu/RSX/Host/MM.h +++ b/rpcs3/Emu/RSX/Host/MM.h @@ -3,6 +3,9 @@ #include #include +#include "Emu/RSX/Common/simple_array.hpp" +#include "Utilities/address_range.h" + namespace rsx { struct MM_block @@ -36,5 +39,6 @@ namespace rsx void mm_protect(void* start, u64 length, utils::protection prot); void mm_flush_lazy(); void mm_flush(u32 vm_address); + void mm_flush(const rsx::simple_array& ranges); void mm_flush(); } diff --git a/rpcs3/Emu/RSX/NV47/HW/nv0039.cpp b/rpcs3/Emu/RSX/NV47/HW/nv0039.cpp index fb20d93a69..831fa60adc 100644 --- a/rpcs3/Emu/RSX/NV47/HW/nv0039.cpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv0039.cpp @@ -3,6 +3,7 @@ #include "Emu/RSX/RSXThread.h" #include "Emu/RSX/Core/RSXReservationLock.hpp" +#include "Emu/RSX/Host/MM.h" #include "context_accessors.define.h" @@ -57,6 +58,13 @@ namespace rsx auto res = ::rsx::reservation_lock(write_address, write_length, read_address, read_length); + rsx::simple_array flush_mm_ranges = + { + utils::address_range::start_length(write_address, write_length).to_page_range(), + utils::address_range::start_length(read_address, read_length).to_page_range() + }; + rsx::mm_flush(flush_mm_ranges); + u8 *dst = vm::_ptr(write_address); const u8 *src = vm::_ptr(read_address); From 79bcb7790c069e7fbae08a7119c30ddfff9b9b1e Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 26 May 2025 01:48:55 +0300 Subject: [PATCH 007/384] rsx/util: Add unit tests for address ranges --- Utilities/address_range.h | 14 + rpcs3/tests/rpcs3_test.vcxproj | 1 + rpcs3/tests/test_address_range.cpp | 450 +++++++++++++++++++++++++++++ 3 files changed, 465 insertions(+) create mode 100644 rpcs3/tests/test_address_range.cpp diff --git a/Utilities/address_range.h b/Utilities/address_range.h index 71fbd4a382..e1e48bb00c 100644 --- a/Utilities/address_range.h +++ b/Utilities/address_range.h @@ -529,6 +529,20 @@ namespace utils return !cur.valid() || cur.inside(range); }); } + + // Count valid entries + usz valid_count() const + { + usz count = 0; + for (const auto& e : data) + { + if (e.valid()) + { + count++; + } + } + return count; + } }; diff --git a/rpcs3/tests/rpcs3_test.vcxproj b/rpcs3/tests/rpcs3_test.vcxproj index 3351d9d8b8..d59172a231 100644 --- a/rpcs3/tests/rpcs3_test.vcxproj +++ b/rpcs3/tests/rpcs3_test.vcxproj @@ -89,6 +89,7 @@ + diff --git a/rpcs3/tests/test_address_range.cpp b/rpcs3/tests/test_address_range.cpp new file mode 100644 index 0000000000..292f8c11bf --- /dev/null +++ b/rpcs3/tests/test_address_range.cpp @@ -0,0 +1,450 @@ +#include + +#define private public +#include "Utilities/address_range.h" +#undef private + +using namespace utils; + +namespace utils +{ + TEST(AddressRange, Constructors) + { + // Default constructor + address_range empty; + EXPECT_FALSE(empty.valid()); + EXPECT_EQ(empty.start, umax); + EXPECT_EQ(empty.end, 0); + + // Static factory methods + address_range r1 = address_range::start_length(0x1000, 0x1000); + EXPECT_EQ(r1.start, 0x1000); + EXPECT_EQ(r1.end, 0x1FFF); + EXPECT_EQ(r1.length(), 0x1000); + EXPECT_TRUE(r1.valid()); + + address_range r2 = address_range::start_end(0x2000, 0x2FFF); + EXPECT_EQ(r2.start, 0x2000); + EXPECT_EQ(r2.end, 0x2FFF); + EXPECT_EQ(r2.length(), 0x1000); + EXPECT_TRUE(r2.valid()); + + // Edge cases + address_range zero_length = address_range::start_length(0x1000, 0); + EXPECT_FALSE(zero_length.valid()); + + address_range single_byte = address_range::start_length(0x1000, 1); + EXPECT_TRUE(single_byte.valid()); + EXPECT_EQ(single_byte.start, 0x1000); + EXPECT_EQ(single_byte.end, 0x1000); + EXPECT_EQ(single_byte.length(), 1); + } + + TEST(AddressRange, LengthAndBoundaries) + { + address_range r = address_range::start_length(0x1000, 0x1000); + + // Test length + EXPECT_EQ(r.length(), 0x1000); + + // Test set_length + r.set_length(0x2000); + EXPECT_EQ(r.start, 0x1000); + EXPECT_EQ(r.end, 0x2FFF); + EXPECT_EQ(r.length(), 0x2000); + + // Test next_address and prev_address + EXPECT_EQ(r.next_address(), 0x3000); + EXPECT_EQ(r.prev_address(), 0xFFF); + } + + TEST(AddressRange, Overlapping) + { + address_range r1 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + + // Complete overlap + address_range r2 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + EXPECT_TRUE(r1.overlaps(r2)); + EXPECT_TRUE(r2.overlaps(r1)); + + // Partial overlap at start + address_range r3 = address_range::start_length(0x800, 0x1000); // 0x800-0x17FF + EXPECT_TRUE(r1.overlaps(r3)); + EXPECT_TRUE(r3.overlaps(r1)); + + // Partial overlap at end + address_range r4 = address_range::start_length(0x1800, 0x1000); // 0x1800-0x27FF + EXPECT_TRUE(r1.overlaps(r4)); + EXPECT_TRUE(r4.overlaps(r1)); + + // No overlap, before + address_range r5 = address_range::start_length(0x0, 0x1000); // 0x0-0xFFF + EXPECT_FALSE(r1.overlaps(r5)); + EXPECT_FALSE(r5.overlaps(r1)); + + // No overlap, after + address_range r6 = address_range::start_length(0x2000, 0x1000); // 0x2000-0x2FFF + EXPECT_FALSE(r1.overlaps(r6)); + EXPECT_FALSE(r6.overlaps(r1)); + + // Single address overlap at start + address_range r7 = address_range::start_length(0x800, 0x801); // 0x800-0x1000 + EXPECT_TRUE(r1.overlaps(r7)); + EXPECT_TRUE(r7.overlaps(r1)); + + // Single address overlap at end + address_range r8 = address_range::start_length(0x1FFF, 0x1000); // 0x1FFF-0x2FFE + EXPECT_TRUE(r1.overlaps(r8)); + EXPECT_TRUE(r8.overlaps(r1)); + + // Address overlap test + EXPECT_TRUE(r1.overlaps(0x1000)); // Start boundary + EXPECT_TRUE(r1.overlaps(0x1FFF)); // End boundary + EXPECT_TRUE(r1.overlaps(0x1800)); // Middle + EXPECT_FALSE(r1.overlaps(0xFFF)); // Just before + EXPECT_FALSE(r1.overlaps(0x2000)); // Just after + } + + TEST(AddressRange, Inside) + { + address_range r1 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + + // Same range + address_range r2 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + EXPECT_TRUE(r1.inside(r2)); + EXPECT_TRUE(r2.inside(r1)); + + // Smaller range inside + address_range r3 = address_range::start_length(0x1200, 0x800); // 0x1200-0x19FF + EXPECT_TRUE(r3.inside(r1)); + EXPECT_FALSE(r1.inside(r3)); + + // Larger range outside + address_range r4 = address_range::start_length(0x800, 0x2000); // 0x800-0x27FF + EXPECT_TRUE(r1.inside(r4)); + EXPECT_FALSE(r4.inside(r1)); + + // Partially overlapping + address_range r5 = address_range::start_length(0x1800, 0x1000); // 0x1800-0x27FF + EXPECT_FALSE(r1.inside(r5)); + EXPECT_FALSE(r5.inside(r1)); + + // No overlap + address_range r6 = address_range::start_length(0x3000, 0x1000); // 0x3000-0x3FFF + EXPECT_FALSE(r1.inside(r6)); + EXPECT_FALSE(r6.inside(r1)); + } + + TEST(AddressRange, Touches) + { + address_range r1 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + + // Same range (overlaps) + address_range r2 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + EXPECT_TRUE(r1.touches(r2)); + + // Overlapping ranges + address_range r3 = address_range::start_length(0x1800, 0x1000); // 0x1800-0x27FF + EXPECT_TRUE(r1.touches(r3)); + + // Adjacent at end of r1 + address_range r4 = address_range::start_length(0x2000, 0x1000); // 0x2000-0x2FFF + EXPECT_TRUE(r1.touches(r4)); + EXPECT_TRUE(r4.touches(r1)); + + // Adjacent at start of r1 + address_range r5 = address_range::start_length(0x0, 0x1000); // 0x0-0xFFF + EXPECT_TRUE(r1.touches(r5)); + EXPECT_TRUE(r5.touches(r1)); + + // Not touching + address_range r6 = address_range::start_length(0x3000, 0x1000); // 0x3000-0x3FFF + EXPECT_FALSE(r1.touches(r6)); + EXPECT_FALSE(r6.touches(r1)); + } + + TEST(AddressRange, Distance) + { + address_range r1 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + + // Touching ranges + address_range r2 = address_range::start_length(0x2000, 0x1000); // 0x2000-0x2FFF + EXPECT_EQ(r1.distance(r2), 0); + EXPECT_EQ(r2.distance(r1), 0); + EXPECT_EQ(r1.signed_distance(r2), 0); + EXPECT_EQ(r2.signed_distance(r1), 0); + + // Gap of 0x1000 (r3 after r1) + address_range r3 = address_range::start_length(0x3000, 0x1000); // 0x3000-0x3FFF + EXPECT_EQ(r1.distance(r3), 0x1000); + EXPECT_EQ(r3.distance(r1), 0x1000); + EXPECT_EQ(r1.signed_distance(r3), 0x1000); + EXPECT_EQ(r3.signed_distance(r1), -0x1000); + + // Gap of 0x1000 (r4 before r1) + address_range r4 = address_range::start_end(0, 0xEFF); // 0x0-0xEFF + EXPECT_EQ(r1.distance(r4), 0x100); + EXPECT_EQ(r4.distance(r1), 0x100); + EXPECT_EQ(r1.signed_distance(r4), -0x100); + EXPECT_EQ(r4.signed_distance(r1), 0x100); + + // Overlapping ranges + address_range r5 = address_range::start_length(0x1800, 0x1000); // 0x1800-0x27FF + EXPECT_EQ(r1.distance(r5), 0); + EXPECT_EQ(r5.distance(r1), 0); + EXPECT_EQ(r1.signed_distance(r5), 0); + EXPECT_EQ(r5.signed_distance(r1), 0); + } + + TEST(AddressRange, MinMax) + { + address_range r1 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + address_range r2 = address_range::start_length(0x1800, 0x1000); // 0x1800-0x27FF + + // Get min-max + address_range min_max = r1.get_min_max(r2); + EXPECT_EQ(min_max.start, 0x1000); + EXPECT_EQ(min_max.end, 0x27FF); + + // Set min-max + address_range r3 = address_range::start_length(0x2000, 0x1000); // 0x2000-0x2FFF + r3.set_min_max(r1); + EXPECT_EQ(r3.start, 0x1000); + EXPECT_EQ(r3.end, 0x2FFF); + + // Test with invalid ranges + address_range empty; + address_range min_max2 = r1.get_min_max(empty); + EXPECT_EQ(min_max2.start, r1.start); + EXPECT_EQ(min_max2.end, r1.end); + + address_range min_max3 = empty.get_min_max(r1); + EXPECT_EQ(min_max3.start, r1.start); + EXPECT_EQ(min_max3.end, r1.end); + + address_range min_max4 = empty.get_min_max(empty); + EXPECT_EQ(min_max4.start, umax); + EXPECT_EQ(min_max4.end, 0); + } + + TEST(AddressRange, Intersect) + { + address_range r1 = address_range::start_length(0x1000, 0x2000); // 0x1000-0x2FFF + + // Complete overlap + address_range r2 = address_range::start_length(0x0, 0x4000); // 0x0-0x3FFF + address_range i1 = r1.get_intersect(r2); + EXPECT_EQ(i1.start, 0x1000); + EXPECT_EQ(i1.end, 0x2FFF); + + // Partial overlap at start + address_range r3 = address_range::start_length(0x0, 0x2000); // 0x0-0x1FFF + address_range i2 = r1.get_intersect(r3); + EXPECT_EQ(i2.start, 0x1000); + EXPECT_EQ(i2.end, 0x1FFF); + + // Partial overlap at end + address_range r4 = address_range::start_length(0x2000, 0x2000); // 0x2000-0x3FFF + address_range i3 = r1.get_intersect(r4); + EXPECT_EQ(i3.start, 0x2000); + EXPECT_EQ(i3.end, 0x2FFF); + + // No overlap + address_range r5 = address_range::start_length(0x4000, 0x1000); // 0x4000-0x4FFF + address_range i4 = r1.get_intersect(r5); + EXPECT_FALSE(i4.valid()); + + // Test intersect method + address_range r6 = address_range::start_length(0x1000, 0x2000); // 0x1000-0x2FFF + r6.intersect(r3); + EXPECT_EQ(r6.start, 0x1000); + EXPECT_EQ(r6.end, 0x1FFF); + } + + TEST(AddressRange, Validity) + { + // Valid range + address_range r1 = address_range::start_length(0x1000, 0x1000); + EXPECT_TRUE(r1.valid()); + + // Invalid range (default constructor) + address_range r2; + EXPECT_FALSE(r2.valid()); + + // Invalid range (start > end) + address_range r3 = address_range::start_end(0x2000, 0x1000); + EXPECT_FALSE(r3.valid()); + + // Invalidate + r1.invalidate(); + EXPECT_FALSE(r1.valid()); + EXPECT_EQ(r1.start, umax); + EXPECT_EQ(r1.end, 0); + } + + TEST(AddressRange, Comparison) + { + address_range r1 = address_range::start_length(0x1000, 0x1000); + address_range r2 = address_range::start_length(0x1000, 0x1000); + address_range r3 = address_range::start_length(0x2000, 0x1000); + + EXPECT_TRUE(r1 == r2); + EXPECT_FALSE(r1 == r3); + } + + TEST(AddressRange, StringRepresentation) + { + address_range r1 = address_range::start_length(0x1000, 0x1000); + std::string str = r1.str(); + + // The exact format may vary, but it should contain the start and end addresses + EXPECT_NE(str.find("1000"), std::string::npos); + EXPECT_NE(str.find("1fff"), std::string::npos); + } + + // Tests for address_range_vector + TEST(AddressRangeVector, BasicOperations) + { + address_range_vector vec; + EXPECT_TRUE(vec.empty()); + EXPECT_EQ(vec.size(), 0); + + // Add a range + vec.merge(address_range::start_length(0x1000, 0x1000)); + EXPECT_FALSE(vec.empty()); + EXPECT_EQ(vec.size(), 1); + + // Clear + vec.clear(); + EXPECT_TRUE(vec.empty()); + EXPECT_EQ(vec.size(), 0); + } + + TEST(AddressRangeVector, MergeOperations) + { + address_range_vector vec; + + // Add non-touching ranges + vec.merge(address_range::start_length(0x1000, 0x1000)); // 0x1000-0x1FFF + vec.merge(address_range::start_length(0x3000, 0x1000)); // 0x3000-0x3FFF + EXPECT_EQ(vec.valid_count(), 2); + + // Add a range that touches the first range + vec.merge(address_range::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF + // Should merge all three ranges + EXPECT_EQ(vec.valid_count(), 1); + EXPECT_TRUE(vec.contains(address_range::start_end(0x1000, 0x3FFF))); + + // Add a non-touching range + vec.merge(address_range::start_length(0x5000, 0x1000)); // 0x5000-0x5FFF + EXPECT_EQ(vec.valid_count(), 2); + + // Add an overlapping range + vec.merge(address_range::start_length(0x4000, 0x2000)); // 0x4000-0x5FFF + EXPECT_EQ(vec.valid_count(), 1); + EXPECT_TRUE(vec.contains(address_range::start_end(0x1000, 0x5FFF))); + } + + TEST(AddressRangeVector, ExcludeOperations) + { + address_range_vector vec; + vec.merge(address_range::start_length(0x1000, 0x4000)); // 0x1000-0x4FFF + + // Exclude from the middle + vec.exclude(address_range::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF + EXPECT_EQ(vec.valid_count(), 2); + + auto it = vec.begin(); + EXPECT_EQ(it->start, 0x1000); + EXPECT_EQ(it->end, 0x1FFF); + ++it; + EXPECT_EQ(it->start, 0x3000); + EXPECT_EQ(it->end, 0x4FFF); + + // Exclude from the start + vec.exclude(address_range::start_length(0x1000, 0x1000)); // 0x1000-0x1FFF + EXPECT_EQ(vec.valid_count(), 1); + EXPECT_TRUE(vec.contains(address_range::start_end(0x3000, 0x4FFF))); + + // Exclude from the end + vec.exclude(address_range::start_length(0x4000, 0x1000)); // 0x4000-0x4FFF + EXPECT_EQ(vec.valid_count(), 1); + EXPECT_TRUE(vec.contains(address_range::start_end(0x3000, 0x3FFF))); + + // Exclude entire range + vec.exclude(address_range::start_length(0x3000, 0x1000)); // 0x3000-0x3FFF + EXPECT_EQ(vec.valid_count(), 0); + + // Test excluding with another vector + vec.merge(address_range::start_length(0x1000, 0x4000)); // 0x1000-0x4FFF + + address_range_vector vec2; + vec2.merge(address_range::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF + vec2.merge(address_range::start_length(0x4000, 0x1000)); // 0x4000-0x4FFF + + vec.exclude(vec2); + EXPECT_EQ(vec.valid_count(), 2); + + EXPECT_TRUE(vec.contains(address_range::start_end(0x1000, 0x1FFF))); + EXPECT_TRUE(vec.contains(address_range::start_end(0x3000, 0x3FFF))); + } + + TEST(AddressRangeVector, ConsistencyCheck) + { + address_range_vector vec; + vec.merge(address_range::start_length(0x1000, 0x1000)); // 0x1000-0x1FFF + vec.merge(address_range::start_length(0x3000, 0x1000)); // 0x3000-0x3FFF + + EXPECT_TRUE(vec.check_consistency()); + + // This would cause inconsistency, but merge should handle it + vec.merge(address_range::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF + EXPECT_TRUE(vec.check_consistency()); + EXPECT_EQ(vec.valid_count(), 1); + } + + TEST(AddressRangeVector, OverlapsAndContains) + { + address_range_vector vec; + vec.merge(address_range::start_length(0x1000, 0x1000)); // 0x1000-0x1FFF + vec.merge(address_range::start_length(0x3000, 0x1000)); // 0x3000-0x3FFF + + // Test overlaps with range + EXPECT_TRUE(vec.overlaps(address_range::start_length(0x1500, 0x1000))); // 0x1500-0x24FF + EXPECT_TRUE(vec.overlaps(address_range::start_length(0x3500, 0x1000))); // 0x3500-0x44FF + EXPECT_FALSE(vec.overlaps(address_range::start_length(0x2000, 0x1000))); // 0x2000-0x2FFF + + // Test contains + EXPECT_TRUE(vec.contains(address_range::start_length(0x1000, 0x1000))); // 0x1000-0x1FFF + EXPECT_TRUE(vec.contains(address_range::start_length(0x3000, 0x1000))); // 0x3000-0x3FFF + EXPECT_FALSE(vec.contains(address_range::start_length(0x1500, 0x1000))); // 0x1500-0x24FF + + // Test overlaps with another vector + address_range_vector vec2; + vec2.merge(address_range::start_length(0x1500, 0x1000)); // 0x1500-0x24FF + EXPECT_TRUE(vec.overlaps(vec2)); + + address_range_vector vec3; + vec3.merge(address_range::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF + EXPECT_FALSE(vec.overlaps(vec3)); + + // Test inside + address_range big_range = address_range::start_length(0x0, 0x5000); // 0x0-0x4FFF + EXPECT_TRUE(vec.inside(big_range)); + + address_range small_range = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + EXPECT_FALSE(vec.inside(small_range)); + } + + // Test the std::hash implementation for address_range + TEST(AddressRange, Hash) + { + address_range r1 = address_range::start_length(0x1000, 0x1000); + address_range r2 = address_range::start_length(0x1000, 0x1000); + address_range r3 = address_range::start_length(0x2000, 0x1000); + + std::hash hasher; + EXPECT_EQ(hasher(r1), hasher(r2)); + EXPECT_NE(hasher(r1), hasher(r3)); + } +} From 4f7c82ba8a55bde72bb1e20356313f1ec3850cec Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 26 May 2025 02:49:20 +0300 Subject: [PATCH 008/384] utils: Rename address_range to address_range32 to allow implementation of address_range16 and address_range64 --- Utilities/address_range.h | 90 ++++---- rpcs3/Emu/Cell/PPUModule.cpp | 4 +- rpcs3/Emu/Cell/SPUCommonRecompiler.cpp | 2 +- rpcs3/Emu/Cell/SPULLVMRecompiler.cpp | 4 +- rpcs3/Emu/Cell/SPURecompiler.h | 2 +- rpcs3/Emu/Cell/lv2/sys_rsx.cpp | 4 +- rpcs3/Emu/Memory/vm.cpp | 8 +- rpcs3/Emu/Memory/vm.h | 2 +- rpcs3/Emu/RSX/Common/ranged_map.hpp | 8 +- rpcs3/Emu/RSX/Common/surface_cache_dma.hpp | 10 +- rpcs3/Emu/RSX/Common/surface_store.h | 36 ++-- rpcs3/Emu/RSX/Common/surface_utils.h | 8 +- rpcs3/Emu/RSX/Common/texture_cache.cpp | 10 +- rpcs3/Emu/RSX/Common/texture_cache.h | 86 ++++---- rpcs3/Emu/RSX/Common/texture_cache_checker.h | 12 +- rpcs3/Emu/RSX/Common/texture_cache_helpers.h | 8 +- .../Emu/RSX/Common/texture_cache_predictor.h | 6 +- rpcs3/Emu/RSX/Common/texture_cache_utils.h | 62 +++--- rpcs3/Emu/RSX/Core/RSXContext.cpp | 8 +- rpcs3/Emu/RSX/Core/RSXContext.h | 4 +- rpcs3/Emu/RSX/Core/RSXReservationLock.hpp | 6 +- rpcs3/Emu/RSX/GL/GLDMA.cpp | 10 +- rpcs3/Emu/RSX/GL/GLDMA.h | 6 +- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 2 +- rpcs3/Emu/RSX/GL/GLGSRender.h | 2 +- rpcs3/Emu/RSX/GL/GLPresent.cpp | 2 +- rpcs3/Emu/RSX/GL/GLRenderTargets.cpp | 4 +- rpcs3/Emu/RSX/GL/GLTextureCache.h | 8 +- rpcs3/Emu/RSX/GL/glutils/ring_buffer.cpp | 4 +- rpcs3/Emu/RSX/GL/glutils/ring_buffer.h | 2 +- rpcs3/Emu/RSX/Host/MM.cpp | 2 +- rpcs3/Emu/RSX/Host/MM.h | 2 +- rpcs3/Emu/RSX/NV47/HW/nv0039.cpp | 6 +- rpcs3/Emu/RSX/NV47/HW/nv3089.cpp | 6 +- rpcs3/Emu/RSX/RSXOffload.cpp | 4 +- rpcs3/Emu/RSX/RSXOffload.h | 2 +- rpcs3/Emu/RSX/RSXThread.cpp | 10 +- rpcs3/Emu/RSX/RSXThread.h | 4 +- rpcs3/Emu/RSX/RSXZCULL.cpp | 2 +- rpcs3/Emu/RSX/VK/VKDMA.cpp | 18 +- rpcs3/Emu/RSX/VK/VKDMA.h | 14 +- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 10 +- rpcs3/Emu/RSX/VK/VKGSRender.h | 4 +- rpcs3/Emu/RSX/VK/VKHelpers.h | 2 +- rpcs3/Emu/RSX/VK/VKPresent.cpp | 2 +- rpcs3/Emu/RSX/VK/VKRenderTargets.cpp | 4 +- rpcs3/Emu/RSX/VK/VKTexture.cpp | 2 +- rpcs3/Emu/RSX/VK/VKTextureCache.cpp | 8 +- rpcs3/Emu/RSX/VK/VKTextureCache.h | 8 +- rpcs3/Emu/RSX/rsx_utils.h | 14 +- rpcs3/tests/test_address_range.cpp | 192 +++++++++--------- 51 files changed, 368 insertions(+), 368 deletions(-) diff --git a/Utilities/address_range.h b/Utilities/address_range.h index e1e48bb00c..1ac39c26a1 100644 --- a/Utilities/address_range.h +++ b/Utilities/address_range.h @@ -37,7 +37,7 @@ namespace utils /** * Address Range utility class */ - class address_range + class address_range32 { public: u32 start = umax; // First address in range @@ -60,13 +60,13 @@ namespace utils return (start1 >= start2 && end1 <= end2); } - constexpr address_range(u32 _start, u32 _end) : start(_start), end(_end) {} + constexpr address_range32(u32 _start, u32 _end) : start(_start), end(_end) {} public: // Constructors - constexpr address_range() = default; + constexpr address_range32() = default; - static constexpr address_range start_length(u32 _start, u32 _length) + static constexpr address_range32 start_length(u32 _start, u32 _length) { if (!_length) { @@ -76,7 +76,7 @@ namespace utils return {_start, _start + (_length - 1)}; } - static constexpr address_range start_end(u32 _start, u32 _end) + static constexpr address_range32 start_end(u32 _start, u32 _end) { return {_start, _end}; } @@ -105,7 +105,7 @@ namespace utils } // Overlapping checks - bool overlaps(const address_range &other) const + bool overlaps(const address_range32 &other) const { AUDIT(valid() && other.valid()); return range_overlaps(start, end, other.start, other.end); @@ -117,7 +117,7 @@ namespace utils return address_overlaps(addr, start, end); } - bool inside(const address_range &other) const + bool inside(const address_range32 &other) const { AUDIT(valid() && other.valid()); return range_inside_range(start, end, other.start, other.end); @@ -126,7 +126,7 @@ namespace utils inline bool inside(const address_range_vector &vec) const; inline bool overlaps(const address_range_vector &vec) const; - bool touches(const address_range &other) const + bool touches(const address_range32 &other) const { AUDIT(valid() && other.valid()); // returns true if there is overlap, or if sections are side-by-side @@ -134,7 +134,7 @@ namespace utils } // Utilities - s32 signed_distance(const address_range &other) const + s32 signed_distance(const address_range32 &other) const { if (touches(other)) { @@ -152,7 +152,7 @@ namespace utils return -static_cast(start - other.end - 1); } - u32 distance(const address_range &other) const + u32 distance(const address_range32 &other) const { if (touches(other)) { @@ -170,7 +170,7 @@ namespace utils return (start - other.end - 1); } - address_range get_min_max(const address_range &other) const + address_range32 get_min_max(const address_range32 &other) const { return { std::min(valid() ? start : umax, other.valid() ? other.start : umax), @@ -178,7 +178,7 @@ namespace utils }; } - void set_min_max(const address_range &other) + void set_min_max(const address_range32 &other) { *this = get_min_max(other); } @@ -188,7 +188,7 @@ namespace utils return (valid() && is_page_aligned(start) && is_page_aligned(length())); } - address_range to_page_range() const + address_range32 to_page_range() const { AUDIT(valid()); return { page_start(start), page_end(end) }; @@ -202,7 +202,7 @@ namespace utils AUDIT(is_page_range()); } - address_range get_intersect(const address_range &clamp) const + address_range32 get_intersect(const address_range32 &clamp) const { if (!valid() || !clamp.valid()) { @@ -212,7 +212,7 @@ namespace utils return { std::max(start, clamp.start), std::min(end, clamp.end) }; } - void intersect(const address_range &clamp) + void intersect(const address_range32 &clamp) { if (!clamp.valid()) { @@ -238,7 +238,7 @@ namespace utils } // Comparison Operators - bool operator ==(const address_range& other) const + bool operator ==(const address_range32& other) const { return (start == other.start && end == other.end); } @@ -252,21 +252,21 @@ namespace utils } }; - static inline address_range page_for(u32 addr) + static inline address_range32 page_for(u32 addr) { - return address_range::start_end(page_start(addr), page_end(addr)); + return address_range32::start_end(page_start(addr), page_end(addr)); } /** * Address Range Vector utility class * - * Collection of address_range objects. Allows for merging and removing ranges from the set. + * Collection of address_range32 objects. Allows for merging and removing ranges from the set. */ class address_range_vector { public: - using vector_type = std::vector; + using vector_type = std::vector; using iterator = vector_type::iterator; using const_iterator = vector_type::const_iterator; using size_type = vector_type::size_type; @@ -280,8 +280,8 @@ namespace utils inline void clear() { data.clear(); } inline size_type size() const { return data.size(); } inline bool empty() const { return data.empty(); } - inline address_range& operator[](size_type n) { return data[n]; } - inline const address_range& operator[](size_type n) const { return data[n]; } + inline address_range32& operator[](size_type n) { return data[n]; } + inline const address_range32& operator[](size_type n) const { return data[n]; } inline iterator begin() { return data.begin(); } inline const_iterator begin() const { return data.begin(); } inline iterator end() { return data.end(); } @@ -289,7 +289,7 @@ namespace utils // Search for ranges that touch new_range. If found, merge instead of adding new_range. // When adding a new range, re-use invalid ranges whenever possible - void merge(const address_range &new_range) + void merge(const address_range32 &new_range) { // Note the case where we have // AAAA BBBB @@ -301,8 +301,8 @@ namespace utils return; } - address_range *found = nullptr; - address_range *invalid = nullptr; + address_range32 *found = nullptr; + address_range32 *invalid = nullptr; for (auto &existing : data) { @@ -349,20 +349,20 @@ namespace utils void merge(const address_range_vector &other) { - for (const address_range &new_range : other) + for (const address_range32 &new_range : other) { merge(new_range); } } // Exclude a given range from data - void exclude(const address_range &exclusion) + void exclude(const address_range32 &exclusion) { // Note the case where we have // AAAAAAA // EEE // where data={A} and exclusion=E. - // In this case, we need to reduce A to the head (before E starts), and then create a new address_range B for the tail (after E ends), i.e. + // In this case, we need to reduce A to the head (before E starts), and then create a new address_range32 B for the tail (after E ends), i.e. // AA BB // EEE @@ -371,13 +371,13 @@ namespace utils return; } - address_range *invalid = nullptr; // try to re-use an invalid range instead of calling push_back + address_range32 *invalid = nullptr; // try to re-use an invalid range instead of calling push_back // We use index access because we might have to push_back within the loop, which could invalidate the iterators size_type _size = data.size(); for (size_type n = 0; n < _size; ++n) { - address_range &existing = data[n]; + address_range32 &existing = data[n]; if (!existing.valid()) { @@ -430,7 +430,7 @@ namespace utils else { // IMPORTANT: adding to data invalidates "existing". This must be done last! - data.push_back(address_range::start_end(exclusion.next_address(), tail_end)); + data.push_back(address_range32::start_end(exclusion.next_address(), tail_end)); } } } @@ -440,7 +440,7 @@ namespace utils void exclude(const address_range_vector &other) { - for (const address_range &exclusion : other) + for (const address_range32 &exclusion : other) { exclude(exclusion); } @@ -478,25 +478,25 @@ namespace utils } // Test for overlap with a given range - bool overlaps(const address_range &range) const + bool overlaps(const address_range32 &range) const { - return std::any_of(data.cbegin(), data.cend(), [&range](const address_range& cur) + return std::any_of(data.cbegin(), data.cend(), [&range](const address_range32& cur) { return cur.valid() && cur.overlaps(range); }); } - // Test for overlap with a given address_range vector + // Test for overlap with a given address_range32 vector bool overlaps(const address_range_vector &other) const { - for (const address_range &rng1 : data) + for (const address_range32 &rng1 : data) { if (!rng1.valid()) { continue; } - for (const address_range &rng2 : other.data) + for (const address_range32 &rng2 : other.data) { if (!rng2.valid()) { @@ -513,18 +513,18 @@ namespace utils } // Test if a given range is fully contained inside this vector - bool contains(const address_range &range) const + bool contains(const address_range32 &range) const { - return std::any_of(this->begin(), this->end(), [&range](const address_range& cur) + return std::any_of(this->begin(), this->end(), [&range](const address_range32& cur) { return cur.valid() && cur.inside(range); }); } // Test if all ranges in this vector are full contained inside a specific range - bool inside(const address_range &range) const + bool inside(const address_range32 &range) const { - return std::all_of(this->begin(), this->end(), [&range](const address_range& cur) + return std::all_of(this->begin(), this->end(), [&range](const address_range32& cur) { return !cur.valid() || cur.inside(range); }); @@ -547,12 +547,12 @@ namespace utils // These declarations must be done after address_range_vector has been defined - bool address_range::inside(const address_range_vector &vec) const + bool address_range32::inside(const address_range_vector &vec) const { return vec.contains(*this); } - bool address_range::overlaps(const address_range_vector &vec) const + bool address_range32::overlaps(const address_range_vector &vec) const { return vec.overlaps(*this); } @@ -565,9 +565,9 @@ namespace std static_assert(sizeof(usz) >= 2 * sizeof(u32), "usz must be at least twice the size of u32"); template <> - struct hash + struct hash { - usz operator()(const utils::address_range& k) const + usz operator()(const utils::address_range32& k) const { // we can guarantee a unique hash since our type is 64 bits and usz as well return (usz{ k.start } << 32) | usz{ k.end }; diff --git a/rpcs3/Emu/Cell/PPUModule.cpp b/rpcs3/Emu/Cell/PPUModule.cpp index eca1177768..65ab0fe18d 100644 --- a/rpcs3/Emu/Cell/PPUModule.cpp +++ b/rpcs3/Emu/Cell/PPUModule.cpp @@ -2088,7 +2088,7 @@ bool ppu_load_exec(const ppu_exec_object& elf, bool virtual_load, const std::str { if (prog.p_type == 0x1u /* LOAD */ && prog.p_memsz) { - using addr_range = utils::address_range; + using addr_range = utils::address_range32; const addr_range r = addr_range::start_length(static_cast(prog.p_vaddr), static_cast(prog.p_memsz)); @@ -2852,7 +2852,7 @@ std::pair, CellError> ppu_load_overlay(const ppu_exec_ob { if (prog.p_type == 0x1u /* LOAD */ && prog.p_memsz) { - using addr_range = utils::address_range; + using addr_range = utils::address_range32; const addr_range r = addr_range::start_length(::narrow(prog.p_vaddr), ::narrow(prog.p_memsz)); diff --git a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp index d73efc8e84..41e81ac4e2 100644 --- a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp @@ -8314,7 +8314,7 @@ void spu_recompiler_base::add_pattern(bool fill_all, inst_attr attr, u32 start, end = start; } - m_patterns[start] = pattern_info{utils::address_range::start_end(start, end)}; + m_patterns[start] = pattern_info{utils::address_range32::start_end(start, end)}; for (u32 i = start; i <= (fill_all ? end : start); i += 4) { diff --git a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp index 0df3e3a854..cc2fea2d38 100644 --- a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp @@ -1083,7 +1083,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator m_ir->SetInsertPoint(_body); } - void putllc16_pattern(const spu_program& /*prog*/, utils::address_range range) + void putllc16_pattern(const spu_program& /*prog*/, utils::address_range32 range) { // Prevent store elimination m_block->store_context_ctr[s_reg_mfc_eal]++; @@ -1376,7 +1376,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator m_ir->SetInsertPoint(_final); } - void putllc0_pattern(const spu_program& /*prog*/, utils::address_range /*range*/) + void putllc0_pattern(const spu_program& /*prog*/, utils::address_range32 /*range*/) { // Prevent store elimination m_block->store_context_ctr[s_reg_mfc_eal]++; diff --git a/rpcs3/Emu/Cell/SPURecompiler.h b/rpcs3/Emu/Cell/SPURecompiler.h index 03b69583d8..ddee888b1e 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.h +++ b/rpcs3/Emu/Cell/SPURecompiler.h @@ -397,7 +397,7 @@ protected: struct pattern_info { - utils::address_range range; + utils::address_range32 range; }; std::unordered_map m_patterns; diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp index 0c912490bd..4ef4e04d85 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp @@ -716,7 +716,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 //const u32 bank = (((a4 >> 32) & 0xFFFFFFFF) >> 4) & 0xF; const bool bound = ((a4 >> 32) & 0x3) != 0; - const auto range = utils::address_range::start_length(offset, size); + const auto range = utils::address_range32::start_length(offset, size); if (bound) { @@ -800,7 +800,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 if (bound) { - const auto cull_range = utils::address_range::start_length(cullStart, width * height); + const auto cull_range = utils::address_range32::start_length(cullStart, width * height); // cullStart is an offset inside ZCULL RAM which is 3MB long, check bounds // width and height are not allowed to be zero (checked by range.valid()) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 891f0910c1..d7109bf78a 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -342,7 +342,7 @@ namespace vm utils::prefetch_read(g_range_lock_set + 2); utils::prefetch_read(g_range_lock_set + 4); - const auto range = utils::address_range::start_length(addr, size); + const auto range = utils::address_range32::start_length(addr, size); u64 to_clear = get_range_lock_bits(false).load(); @@ -350,7 +350,7 @@ namespace vm { to_clear = for_all_range_locks(to_clear, [&](u32 addr2, u32 size2) { - if (range.overlaps(utils::address_range::start_length(addr2, size2))) [[unlikely]] + if (range.overlaps(utils::address_range32::start_length(addr2, size2))) [[unlikely]] { return 1; } @@ -1816,7 +1816,7 @@ namespace vm static bool _test_map(u32 addr, u32 size) { - const auto range = utils::address_range::start_length(addr, size); + const auto range = utils::address_range32::start_length(addr, size); if (!range.valid()) { @@ -1830,7 +1830,7 @@ namespace vm continue; } - if (range.overlaps(utils::address_range::start_length(block->addr, block->size))) + if (range.overlaps(utils::address_range32::start_length(block->addr, block->size))) { return false; } diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 2b2eccc24d..98800055a5 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -22,7 +22,7 @@ void ppubreak(ppu_thread& ppu); namespace utils { class shm; - class address_range; + class address_range32; } namespace vm diff --git a/rpcs3/Emu/RSX/Common/ranged_map.hpp b/rpcs3/Emu/RSX/Common/ranged_map.hpp index 8103e36972..cd728ad48a 100644 --- a/rpcs3/Emu/RSX/Common/ranged_map.hpp +++ b/rpcs3/Emu/RSX/Common/ranged_map.hpp @@ -36,7 +36,7 @@ namespace rsx return block_id * BlockSize; } - void broadcast_insert(const utils::address_range& range) + void broadcast_insert(const utils::address_range32& range) { const auto head_block = block_for(range.start); for (auto meta = &m_metadata[head_block]; meta <= &m_metadata[block_for(range.end)]; ++meta) @@ -98,7 +98,7 @@ namespace rsx m_it = where; } - void begin_range(const utils::address_range& range) + void begin_range(const utils::address_range32& range) { const auto start_block_id = range.start / BlockSize; const auto& metadata = m_metadata_ptr[start_block_id]; @@ -177,7 +177,7 @@ namespace rsx std::for_each(m_metadata.begin(), m_metadata.end(), [&](auto& meta) { meta.id = static_cast(&meta - m_metadata.data()); }); } - void emplace(const utils::address_range& range, T&& value) + void emplace(const utils::address_range32& range, T&& value) { broadcast_insert(range); m_data[block_for(range.start)].insert_or_assign(range.start, std::forward(value)); @@ -220,7 +220,7 @@ namespace rsx m_data[block_for(address)].erase(address); } - iterator begin_range(const utils::address_range& range) + iterator begin_range(const utils::address_range32& range) { iterator ret = { this }; ret.begin_range(range); diff --git a/rpcs3/Emu/RSX/Common/surface_cache_dma.hpp b/rpcs3/Emu/RSX/Common/surface_cache_dma.hpp index a4aa58b3e3..02c507fde2 100644 --- a/rpcs3/Emu/RSX/Common/surface_cache_dma.hpp +++ b/rpcs3/Emu/RSX/Common/surface_cache_dma.hpp @@ -49,7 +49,7 @@ namespace rsx } } - surface_cache_dma& with_range(command_list_type cmd, const utils::address_range& range) + surface_cache_dma& with_range(command_list_type cmd, const utils::address_range32& range) { // Prepare underlying memory so that the range specified is provisioned and contiguous // 1. Check if we have a pre-existing bo layer @@ -57,7 +57,7 @@ namespace rsx if (this_entry) { const auto bo = this_entry.get(); - const auto buffer_range = utils::address_range::start_length(bo.base_address, ::size32(*bo)); + const auto buffer_range = utils::address_range32::start_length(bo.base_address, ::size32(*bo)); if (range.inside(buffer_range)) { @@ -94,11 +94,11 @@ namespace rsx return *this; } - utils::address_range to_block_range(const utils::address_range& range) + utils::address_range32 to_block_range(const utils::address_range32& range) { u32 start = block_address(block_for(range.start)); u32 end = block_address(block_for(range.end + BlockSize - 1)); - return utils::address_range::start_end(start, end - 1); + return utils::address_range32::start_end(start, end - 1); } std::tuple get(u32 address) @@ -107,7 +107,7 @@ namespace rsx return { block.get(), block.base_address - address }; } - void touch(const utils::address_range& range) + void touch(const utils::address_range32& range) { const u64 stamp = rsx::get_shared_tag(); for (usz i = block_for(range.start); i <= block_for(range.end); i++) diff --git a/rpcs3/Emu/RSX/Common/surface_store.h b/rpcs3/Emu/RSX/Common/surface_store.h index 9b266a54ed..ce1e9083e9 100644 --- a/rpcs3/Emu/RSX/Common/surface_store.h +++ b/rpcs3/Emu/RSX/Common/surface_store.h @@ -52,8 +52,8 @@ namespace rsx surface_ranged_map m_render_targets_storage = {}; surface_ranged_map m_depth_stencil_storage = {}; - rsx::address_range m_render_targets_memory_range; - rsx::address_range m_depth_stencil_memory_range; + rsx::address_range32 m_render_targets_memory_range; + rsx::address_range32 m_depth_stencil_memory_range; surface_cache_dma_map m_dma_block; @@ -244,7 +244,7 @@ namespace rsx template void intersect_surface_region(command_list_type cmd, u32 address, surface_type new_surface, surface_type prev_surface) { - auto scan_list = [&new_surface, address](const rsx::address_range& mem_range, + auto scan_list = [&new_surface, address](const rsx::address_range32& mem_range, surface_ranged_map& data) -> std::vector> { std::vector> result; @@ -277,7 +277,7 @@ namespace rsx } // Range check - const rsx::address_range this_range = surface->get_memory_range(); + const rsx::address_range32 this_range = surface->get_memory_range(); if (!this_range.overlaps(mem_range)) { continue; @@ -290,7 +290,7 @@ namespace rsx return result; }; - const rsx::address_range mem_range = new_surface->get_memory_range(); + const rsx::address_range32 mem_range = new_surface->get_memory_range(); auto list1 = scan_list(mem_range, m_render_targets_storage); auto list2 = scan_list(mem_range, m_depth_stencil_storage); @@ -410,7 +410,7 @@ namespace rsx // Workaround. Preserve new surface tag value because pitch convert is unimplemented u64 new_content_tag = 0; - address_range* storage_bounds; + address_range32* storage_bounds; surface_ranged_map* primary_storage; surface_ranged_map* secondary_storage; if constexpr (depth) @@ -488,7 +488,7 @@ namespace rsx { // Range test const auto aa_factor_v = get_aa_factor_v(antialias); - rsx::address_range range = rsx::address_range::start_length(address, static_cast(pitch * height * aa_factor_v)); + rsx::address_range32 range = rsx::address_range32::start_length(address, static_cast(pitch * height * aa_factor_v)); *storage_bounds = range.get_min_max(*storage_bounds); // Search invalidated resources for a suitable surface @@ -629,10 +629,10 @@ namespace rsx invalidated_resources.push_back(std::move(storage)); } - int remove_duplicates_fast_impl(std::vector& sections, const rsx::address_range& range) + int remove_duplicates_fast_impl(std::vector& sections, const rsx::address_range32& range) { // Range tests to check for gaps - std::list m_ranges; + std::list m_ranges; bool invalidate_sections = false; int removed_count = 0; @@ -696,7 +696,7 @@ namespace rsx return removed_count; } - void remove_duplicates_fallback_impl(std::vector& sections, const rsx::address_range& range) + void remove_duplicates_fallback_impl(std::vector& sections, const rsx::address_range32& range) { // Originally used to debug crashes but this function breaks often enough that I'll leave the checks in for now. // Safe to remove after some time if no asserts are reported. @@ -866,10 +866,10 @@ namespace rsx } std::tuple, std::vector> - find_overlapping_set(const utils::address_range& range) const + find_overlapping_set(const utils::address_range32& range) const { std::vector color_result, depth_result; - utils::address_range result_range; + utils::address_range32 result_range; if (m_render_targets_memory_range.valid() && range.overlaps(m_render_targets_memory_range)) @@ -904,7 +904,7 @@ namespace rsx void write_to_dma_buffers( command_list_type command_list, - const utils::address_range& range) + const utils::address_range32& range) { auto block_range = m_dma_block.to_block_range(range); auto [color_data, depth_stencil_data] = find_overlapping_set(block_range); @@ -1102,7 +1102,7 @@ namespace rsx return {}; } - const auto test_range = utils::address_range::start_length(texaddr, (required_pitch * required_height) - (required_pitch - surface_internal_pitch)); + const auto test_range = utils::address_range32::start_length(texaddr, (required_pitch * required_height) - (required_pitch - surface_internal_pitch)); auto process_list_function = [&](surface_ranged_map& data, bool is_depth) { @@ -1237,7 +1237,7 @@ namespace rsx void check_for_duplicates(std::vector& sections) { - utils::address_range test_range; + utils::address_range32 test_range; for (const auto& section : sections) { const auto range = section.surface->get_memory_range(); @@ -1294,7 +1294,7 @@ namespace rsx void invalidate_all() { // Unbind and invalidate all resources - auto free_resource_list = [&](auto &data, const utils::address_range& range) + auto free_resource_list = [&](auto &data, const utils::address_range32& range) { for (auto it = data.begin_range(range); it != data.end(); ++it) { @@ -1317,7 +1317,7 @@ namespace rsx } } - void invalidate_range(const rsx::address_range& range) + void invalidate_range(const rsx::address_range32& range) { for (auto it = m_render_targets_storage.begin_range(range); it != m_render_targets_storage.end(); ++it) { @@ -1383,7 +1383,7 @@ namespace rsx void collapse_dirty_surfaces(command_list_type cmd, problem_severity severity) { - auto process_list_function = [&](surface_ranged_map& data, const utils::address_range& range) + auto process_list_function = [&](surface_ranged_map& data, const utils::address_range32& range) { for (auto It = data.begin_range(range); It != data.end();) { diff --git a/rpcs3/Emu/RSX/Common/surface_utils.h b/rpcs3/Emu/RSX/Common/surface_utils.h index 03c5b5e6f2..bf7dee2db3 100644 --- a/rpcs3/Emu/RSX/Common/surface_utils.h +++ b/rpcs3/Emu/RSX/Common/surface_utils.h @@ -146,7 +146,7 @@ namespace rsx u8 samples_x = 1; u8 samples_y = 1; - rsx::address_range memory_range; + rsx::address_range32 memory_range; std::unique_ptr> resolve_surface; surface_sample_layout sample_layout = surface_sample_layout::null; @@ -367,7 +367,7 @@ namespace rsx const u32 internal_height = get_surface_height(); const u32 excess = (rsx_pitch - native_pitch); - memory_range = rsx::address_range::start_length(base_addr, internal_height * rsx_pitch - excess); + memory_range = rsx::address_range32::start_length(base_addr, internal_height * rsx_pitch - excess); } void sync_tag() @@ -419,7 +419,7 @@ namespace rsx const u32 internal_height = get_surface_height(); const u32 excess = (rsx_pitch - native_pitch); - memory_range = rsx::address_range::start_length(base_addr, internal_height * rsx_pitch - excess); + memory_range = rsx::address_range32::start_length(base_addr, internal_height * rsx_pitch - excess); } void sync_tag() @@ -658,7 +658,7 @@ namespace rsx return { 0, 0, internal_width, internal_height }; } - inline rsx::address_range get_memory_range() const + inline rsx::address_range32 get_memory_range() const { return memory_range; } diff --git a/rpcs3/Emu/RSX/Common/texture_cache.cpp b/rpcs3/Emu/RSX/Common/texture_cache.cpp index d1cdd25a34..ab884c407b 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.cpp +++ b/rpcs3/Emu/RSX/Common/texture_cache.cpp @@ -7,7 +7,7 @@ namespace rsx { constexpr u32 min_lockable_data_size = 4096; // Increasing this value has worse results even on systems with pages > 4k - void buffered_section::init_lockable_range(const address_range& range) + void buffered_section::init_lockable_range(const address_range32& range) { locked_range = range.to_page_range(); AUDIT((locked_range.start == page_start(range.start)) || (locked_range.start == next_page(range.start))); @@ -15,11 +15,11 @@ namespace rsx ensure(locked_range.is_page_range()); } - void buffered_section::reset(const address_range& memory_range) + void buffered_section::reset(const address_range32& memory_range) { ensure(memory_range.valid() && locked == false); - cpu_range = address_range(memory_range); + cpu_range = address_range32(memory_range); confirmed_range.invalidate(); locked_range.invalidate(); @@ -110,7 +110,7 @@ namespace rsx } else { - confirmed_range = address_range::start_length(cpu_range.start + new_confirm.first, new_confirm.second); + confirmed_range = address_range32::start_length(cpu_range.start + new_confirm.first, new_confirm.second); ensure(!locked || locked_range.inside(confirmed_range.to_page_range())); } @@ -139,7 +139,7 @@ namespace rsx locked = false; } - const address_range& buffered_section::get_bounds(section_bounds bounds) const + const address_range32& buffered_section::get_bounds(section_bounds bounds) const { switch (bounds) { diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index a5ed283534..2eeab39ecb 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -65,8 +65,8 @@ namespace rsx u32 num_discarded = 0; u64 cache_tag = 0; - address_range fault_range; - address_range invalidate_range; + address_range32 fault_range; + address_range32 invalidate_range; void clear_sections() { @@ -136,7 +136,7 @@ namespace rsx struct intersecting_set { rsx::simple_array sections = {}; - address_range invalidate_range = {}; + address_range32 invalidate_range = {}; bool has_flushables = false; }; @@ -150,7 +150,7 @@ namespace rsx u16 x = 0; u16 y = 0; - utils::address_range cache_range; + utils::address_range32 cache_range; bool do_not_cache = false; deferred_subresource() = default; @@ -445,8 +445,8 @@ namespace rsx atomic_t m_cache_update_tag = {0}; - address_range read_only_range; - address_range no_access_range; + address_range32 read_only_range; + address_range32 no_access_range; //Map of messages to only emit once std::unordered_set m_once_only_messages_set; @@ -455,7 +455,7 @@ namespace rsx bool read_only_tex_invalidate = false; //Store of all objects in a flush_always state. A lazy readback is attempted every draw call - std::unordered_map m_flush_always_cache; + std::unordered_map m_flush_always_cache; u64 m_flush_always_update_timestamp = 0; //Memory usage @@ -484,11 +484,11 @@ namespace rsx virtual image_view_type create_temporary_subresource_view(commandbuffer_type&, image_resource_type* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h, const texture_channel_remap_t& remap_vector) = 0; virtual image_view_type create_temporary_subresource_view(commandbuffer_type&, image_storage_type* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h, const texture_channel_remap_t& remap_vector) = 0; virtual void release_temporary_subresource(image_view_type rsc) = 0; - virtual section_storage_type* create_new_texture(commandbuffer_type&, const address_range &rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, u32 gcm_format, + virtual section_storage_type* create_new_texture(commandbuffer_type&, const address_range32 &rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, u32 gcm_format, rsx::texture_upload_context context, rsx::texture_dimension_extended type, bool swizzled, component_order swizzle_flags, rsx::flags32_t flags) = 0; - virtual section_storage_type* upload_image_from_cpu(commandbuffer_type&, const address_range &rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, u32 gcm_format, texture_upload_context context, + virtual section_storage_type* upload_image_from_cpu(commandbuffer_type&, const address_range32 &rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, u32 gcm_format, texture_upload_context context, const std::vector& subresource_layout, rsx::texture_dimension_extended type, bool swizzled) = 0; - virtual section_storage_type* create_nul_section(commandbuffer_type&, const address_range &rsx_range, const image_section_attributes_t& attrs, const GCM_tile_reference& tile, bool memory_load) = 0; + virtual section_storage_type* create_nul_section(commandbuffer_type&, const address_range32 &rsx_range, const image_section_attributes_t& attrs, const GCM_tile_reference& tile, bool memory_load) = 0; virtual void set_component_order(section_storage_type& section, u32 gcm_format, component_order expected) = 0; virtual void insert_texture_barrier(commandbuffer_type&, image_storage_type* tex, bool strong_ordering = true) = 0; virtual image_view_type generate_cubemap_from_images(commandbuffer_type&, u32 gcm_format, u16 size, const std::vector& sources, const texture_channel_remap_t& remap_vector) = 0; @@ -545,7 +545,7 @@ namespace rsx * Internal implementation methods and helpers */ - inline bool region_intersects_cache(const address_range &test_range, bool is_writing) + inline bool region_intersects_cache(const address_range32 &test_range, bool is_writing) { AUDIT(test_range.valid()); @@ -751,7 +751,7 @@ namespace rsx for (const auto &excluded : data.sections_to_exclude) { ensure(excluded->is_locked(true)); - address_range exclusion_range = excluded->get_locked_range(); + address_range32 exclusion_range = excluded->get_locked_range(); // We need to make sure that the exclusion range is *inside* invalidate range exclusion_range.intersect(data.invalidate_range); @@ -824,14 +824,14 @@ namespace rsx // Return a set containing all sections that should be flushed/unprotected/reprotected atomic_t m_last_section_cache_tag = 0; - intersecting_set get_intersecting_set(const address_range &fault_range) + intersecting_set get_intersecting_set(const address_range32 &fault_range) { AUDIT(fault_range.is_page_range()); const u64 cache_tag = ++m_last_section_cache_tag; intersecting_set result = {}; - address_range &invalidate_range = result.invalidate_range; + address_range32 &invalidate_range = result.invalidate_range; invalidate_range = fault_range; // Sections fully inside this range will be invalidated, others will be deemed false positives // Loop through cache and find pages that overlap the invalidate_range @@ -920,7 +920,7 @@ namespace rsx template thrashed_set invalidate_range_impl_base( commandbuffer_type& cmd, - const address_range &fault_range_in, + const address_range32 &fault_range_in, invalidation_cause cause, std::function on_data_transfer_completed = {}, Args&&... extras) @@ -932,7 +932,7 @@ namespace rsx AUDIT(cause.valid()); AUDIT(fault_range_in.valid()); - address_range fault_range = fault_range_in.to_page_range(); + address_range32 fault_range = fault_range_in.to_page_range(); intersecting_set trampled_set = get_intersecting_set(fault_range); @@ -1005,7 +1005,7 @@ namespace rsx #endif // If invalidate_range is fault_range, we can stop now - const address_range invalidate_range = trampled_set.invalidate_range; + const address_range32 invalidate_range = trampled_set.invalidate_range; if (invalidate_range == fault_range) { result.violation_handled = true; @@ -1187,7 +1187,7 @@ namespace rsx } template - std::vector find_texture_from_range(const address_range &test_range, u32 required_pitch = 0, u32 context_mask = 0xFF) + std::vector find_texture_from_range(const address_range32 &test_range, u32 required_pitch = 0, u32 context_mask = 0xFF) { std::vector results; @@ -1239,7 +1239,7 @@ namespace rsx return nullptr; } - section_storage_type* find_cached_texture(const address_range &range, const image_section_attributes_t& attr, bool create_if_not_found, bool confirm_dimensions, bool allow_dirty) + section_storage_type* find_cached_texture(const address_range32 &range, const image_section_attributes_t& attr, bool create_if_not_found, bool confirm_dimensions, bool allow_dirty) { auto &block = m_storage.block_for(range); @@ -1329,7 +1329,7 @@ namespace rsx return tex; } - section_storage_type* find_flushable_section(const address_range &memory_range) + section_storage_type* find_flushable_section(const address_range32 &memory_range) { auto &block = m_storage.block_for(memory_range); for (auto &tex : block) @@ -1345,7 +1345,7 @@ namespace rsx } template - void lock_memory_region(commandbuffer_type& cmd, image_storage_type* image, const address_range &rsx_range, bool is_active_surface, u16 width, u16 height, u32 pitch, Args&&... extras) + void lock_memory_region(commandbuffer_type& cmd, image_storage_type* image, const address_range32 &rsx_range, bool is_active_surface, u16 width, u16 height, u32 pitch, Args&&... extras) { AUDIT(g_cfg.video.write_color_buffers || g_cfg.video.write_depth_buffer); // this method is only called when either WCB or WDB are enabled @@ -1414,7 +1414,7 @@ namespace rsx } template - void commit_framebuffer_memory_region(commandbuffer_type& cmd, const address_range &rsx_range, Args&&... extras) + void commit_framebuffer_memory_region(commandbuffer_type& cmd, const address_range32 &rsx_range, Args&&... extras) { AUDIT(!g_cfg.video.write_color_buffers || !g_cfg.video.write_depth_buffer); @@ -1426,7 +1426,7 @@ namespace rsx } template - void discard_framebuffer_memory_region(commandbuffer_type& /*cmd*/, const address_range& rsx_range, Args&&... /*extras*/) + void discard_framebuffer_memory_region(commandbuffer_type& /*cmd*/, const address_range32& rsx_range, Args&&... /*extras*/) { if (g_cfg.video.write_color_buffers || g_cfg.video.write_depth_buffer) { @@ -1439,7 +1439,7 @@ namespace rsx } } - void set_memory_read_flags(const address_range &memory_range, memory_read_flags flags) + void set_memory_read_flags(const address_range32 &memory_range, memory_read_flags flags) { std::lock_guard lock(m_cache_mutex); @@ -1492,7 +1492,7 @@ namespace rsx private: inline void update_flush_always_cache(section_storage_type §ion, bool add) { - const address_range& range = section.get_section_range(); + const address_range32& range = section.get_section_range(); if (add) { // Add to m_flush_always_cache @@ -1529,7 +1529,7 @@ namespace rsx template thrashed_set invalidate_range( commandbuffer_type& cmd, - const address_range &range, + const address_range32 &range, invalidation_cause cause, std::function on_data_transfer_completed = {}, Args&&... extras) @@ -1568,7 +1568,7 @@ namespace rsx } template - bool flush_if_cache_miss_likely(commandbuffer_type& cmd, const address_range &range, Args&&... extras) + bool flush_if_cache_miss_likely(commandbuffer_type& cmd, const address_range32 &range, Args&&... extras) { u32 cur_flushes_this_frame = (m_flushes_this_frame + m_speculations_this_frame); @@ -1834,7 +1834,7 @@ namespace rsx m_uncached_subresources.clear(); } - void notify_surface_changed(const utils::address_range& range) + void notify_surface_changed(const utils::address_range32& range) { for (auto It = m_temporary_subresource_cache.begin(); It != m_temporary_subresource_cache.end();) { @@ -1858,7 +1858,7 @@ namespace rsx const size3f& scale, const texture_channel_remap_t& remap, const texture_cache_search_options& options, - const utils::address_range& memory_range, + const utils::address_range32& memory_range, rsx::texture_dimension_extended extended_dimension, SurfaceStoreType& m_rtts, Args&&... /*extras*/) { @@ -2362,7 +2362,7 @@ namespace rsx extended_dimension = std::max(extended_dimension, rsx::texture_dimension_extended::texture_dimension_2d); } - const auto lookup_range = utils::address_range::start_length(attributes.address, attributes.pitch * required_surface_height); + const auto lookup_range = utils::address_range32::start_length(attributes.address, attributes.pitch * required_surface_height); reader_lock lock(m_cache_mutex); auto result = fast_texture_search(cmd, attributes, scale, tex.decoded_remap(), @@ -2439,7 +2439,7 @@ namespace rsx attr2.pitch = attr2.width * attr2.bpp; } - const auto range = utils::address_range::start_length(attr2.address, attr2.pitch * attr2.height); + const auto range = utils::address_range32::start_length(attr2.address, attr2.pitch * attr2.height); auto ret = fast_texture_search(cmd, attr2, scale, tex.decoded_remap(), options, range, extended_dimension, m_rtts, std::forward(extras)...); @@ -2477,7 +2477,7 @@ namespace rsx } const u32 cache_end = attr2.address + (attr2.pitch * attr2.height); - result.external_subresource_desc.cache_range = utils::address_range::start_end(attributes.address, cache_end); + result.external_subresource_desc.cache_range = utils::address_range32::start_end(attributes.address, cache_end); result.external_subresource_desc.sections_to_copy = std::move(sections); return result; @@ -2498,7 +2498,7 @@ namespace rsx lock.upgrade(); // Invalidate - const address_range tex_range = address_range::start_length(attributes.address, tex_size); + const address_range32 tex_range = address_range32::start_length(attributes.address, tex_size); invalidate_range_impl_base(cmd, tex_range, invalidation_cause::read, {}, std::forward(extras)...); // Upload from CPU. Note that sRGB conversion is handled in the FS @@ -2595,7 +2595,7 @@ namespace rsx src_address += (src.width - src_w) * src_bpp; } - const auto get_tiled_region = [&](const utils::address_range& range) + const auto get_tiled_region = [&](const utils::address_range32& range) { auto rsxthr = rsx::get_current_renderer(); return rsxthr->get_tiled_memory_region(range); @@ -2683,7 +2683,7 @@ namespace rsx return true; }; - auto validate_fbo_integrity = [&](const utils::address_range& range, bool is_depth_texture) + auto validate_fbo_integrity = [&](const utils::address_range32& range, bool is_depth_texture) { const bool will_upload = is_depth_texture ? !!g_cfg.video.read_depth_buffer : !!g_cfg.video.read_color_buffers; if (!will_upload) @@ -2705,8 +2705,8 @@ namespace rsx }; // Check tiled mem - const auto dst_tile = get_tiled_region(utils::address_range::start_length(dst_address, dst.pitch * dst.clip_height)); - const auto src_tile = get_tiled_region(utils::address_range::start_length(src_address, src.pitch * src.height)); + const auto dst_tile = get_tiled_region(utils::address_range32::start_length(dst_address, dst.pitch * dst.clip_height)); + const auto src_tile = get_tiled_region(utils::address_range32::start_length(src_address, src.pitch * src.height)); const auto dst_is_tiled = !!dst_tile; const auto src_is_tiled = !!src_tile; @@ -2735,7 +2735,7 @@ namespace rsx // If we have a pitched write, or a suspiciously large transfer, we likely have a valid write. // Invalidate surfaces in range. Sample tests should catch overlaps in theory. - m_rtts.invalidate_range(utils::address_range::start_length(dst_address, dst.pitch * dst_h)); + m_rtts.invalidate_range(utils::address_range32::start_length(dst_address, dst.pitch * dst_h)); } // FBO re-validation. It is common for GPU and CPU data to desync as we do not have a way to share memory pages directly between the two (in most setups) @@ -2863,7 +2863,7 @@ namespace rsx const auto src_payload_length = (src.pitch * (src_h - 1) + (src_w * src_bpp)); const auto dst_payload_length = (dst.pitch * (dst_h - 1) + (dst_w * dst_bpp)); - const auto dst_range = address_range::start_length(dst_address, dst_payload_length); + const auto dst_range = address_range32::start_length(dst_address, dst_payload_length); if (!use_null_region && !dst_is_render_target) { @@ -3035,7 +3035,7 @@ namespace rsx { // NOTE: Src address already takes into account the flipped nature of the overlap! const u32 lookup_mask = rsx::texture_upload_context::blit_engine_src | rsx::texture_upload_context::blit_engine_dst | rsx::texture_upload_context::shader_read; - auto overlapping_surfaces = find_texture_from_range(address_range::start_length(src_address, src_payload_length), src.pitch, lookup_mask); + auto overlapping_surfaces = find_texture_from_range(address_range32::start_length(src_address, src_payload_length), src.pitch, lookup_mask); auto old_src_area = src_area; for (const auto &surface : overlapping_surfaces) @@ -3168,7 +3168,7 @@ namespace rsx subresource_layout.push_back(subres); const u32 gcm_format = helpers::get_sized_blit_format(src_is_argb8, dst_is_depth_surface, is_format_convert); - const auto rsx_range = address_range::start_length(image_base, src.pitch * image_height); + const auto rsx_range = address_range32::start_length(image_base, src.pitch * image_height); lock.upgrade(); @@ -3243,7 +3243,7 @@ namespace rsx dst_dimensions.height = align2(usable_section_length, dst.pitch) / dst.pitch; const u32 full_section_length = ((dst_dimensions.height - 1) * dst.pitch) + (dst_dimensions.width * dst_bpp); - const auto rsx_range = address_range::start_length(dst_base_address, full_section_length); + const auto rsx_range = address_range32::start_length(dst_base_address, full_section_length); lock.upgrade(); @@ -3502,7 +3502,7 @@ namespace rsx return m_predictor; } - bool is_protected(u32 section_base_address, const address_range& test_range, rsx::texture_upload_context context) + bool is_protected(u32 section_base_address, const address_range32& test_range, rsx::texture_upload_context context) { reader_lock lock(m_cache_mutex); diff --git a/rpcs3/Emu/RSX/Common/texture_cache_checker.h b/rpcs3/Emu/RSX/Common/texture_cache_checker.h index 094220ac33..cb283cc96a 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache_checker.h +++ b/rpcs3/Emu/RSX/Common/texture_cache_checker.h @@ -112,7 +112,7 @@ namespace rsx { } public: - void set_protection(const address_range& range, utils::protection prot) + void set_protection(const address_range32& range, utils::protection prot) { AUDIT(range.is_page_range()); AUDIT(prot == utils::protection::no || prot == utils::protection::ro || prot == utils::protection::rw); @@ -123,7 +123,7 @@ namespace rsx { } } - void discard(const address_range& range) + void discard(const address_range32& range) { set_protection(range, utils::protection::rw); } @@ -136,7 +136,7 @@ namespace rsx { } } - void add(const address_range& range, utils::protection prot) + void add(const address_range32& range, utils::protection prot) { AUDIT(range.is_page_range()); AUDIT(prot == utils::protection::no || prot == utils::protection::ro); @@ -147,7 +147,7 @@ namespace rsx { } } - void remove(const address_range& range, utils::protection prot) + void remove(const address_range32& range, utils::protection prot) { AUDIT(range.is_page_range()); AUDIT(prot == utils::protection::no || prot == utils::protection::ro); @@ -160,7 +160,7 @@ namespace rsx { // Returns the a lower bound as to how many locked sections are known to be within the given range with each protection {NA,RO} // The assumption here is that the page in the given range with the largest number of refcounted sections represents the lower bound to how many there must be - std::pair get_minimum_number_of_sections(const address_range& range) const + std::pair get_minimum_number_of_sections(const address_range32& range) const { AUDIT(range.is_page_range()); @@ -175,7 +175,7 @@ namespace rsx { return { no,ro }; } - void check_unprotected(const address_range& range, bool allow_ro = false, bool must_be_empty = true) const + void check_unprotected(const address_range32& range, bool allow_ro = false, bool must_be_empty = true) const { AUDIT(range.is_page_range()); for (const per_page_info_t* ptr = rsx_address_to_info_pointer(range.start); ptr <= rsx_address_to_info_pointer(range.end); ptr++) diff --git a/rpcs3/Emu/RSX/Common/texture_cache_helpers.h b/rpcs3/Emu/RSX/Common/texture_cache_helpers.h index 617f3b75db..dfe4cb5ee9 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache_helpers.h +++ b/rpcs3/Emu/RSX/Common/texture_cache_helpers.h @@ -69,9 +69,9 @@ namespace rsx blit_op_result(bool success) : succeeded(success) {} - inline address_range to_address_range() const + inline address_range32 to_address_range() const { - return address_range::start_length(real_dst_address, real_dst_size); + return address_range32::start_length(real_dst_address, real_dst_size); } }; @@ -182,7 +182,7 @@ namespace rsx static inline blit_target_properties get_optimal_blit_target_properties( bool src_is_render_target, - address_range dst_range, + address_range32 dst_range, u32 dst_pitch, const sizeu src_dimensions, const sizeu dst_dimensions) @@ -209,7 +209,7 @@ namespace rsx continue; } - const auto buffer_range = address_range::start_length(rsx::get_address(buffer.offset, CELL_GCM_LOCATION_LOCAL), pitch * (buffer.height - 1) + (buffer.width * bpp)); + const auto buffer_range = address_range32::start_length(rsx::get_address(buffer.offset, CELL_GCM_LOCATION_LOCAL), pitch * (buffer.height - 1) + (buffer.width * bpp)); if (dst_range.inside(buffer_range)) { // Match found diff --git a/rpcs3/Emu/RSX/Common/texture_cache_predictor.h b/rpcs3/Emu/RSX/Common/texture_cache_predictor.h index a18fc93c76..bfa500ef1a 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache_predictor.h +++ b/rpcs3/Emu/RSX/Common/texture_cache_predictor.h @@ -76,14 +76,14 @@ namespace rsx using texture_format = typename traits::texture_format; using section_storage_type = typename traits::section_storage_type; - address_range cpu_range; + address_range32 cpu_range; texture_format format; texture_upload_context context; // Constructors texture_cache_predictor_key() = default; - texture_cache_predictor_key(const address_range& _cpu_range, texture_format _format, texture_upload_context _context) + texture_cache_predictor_key(const address_range32& _cpu_range, texture_format _format, texture_upload_context _context) : cpu_range(_cpu_range) , format(_format) , context(_context) @@ -398,7 +398,7 @@ struct std::hash> { usz operator()(const rsx::texture_cache_predictor_key& k) const { - usz result = std::hash{}(k.cpu_range); + usz result = std::hash{}(k.cpu_range); result ^= static_cast(k.format); result ^= (static_cast(k.context) << 16); return result; diff --git a/rpcs3/Emu/RSX/Common/texture_cache_utils.h b/rpcs3/Emu/RSX/Common/texture_cache_utils.h index 3a87deceb7..97b02e8f9d 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache_utils.h +++ b/rpcs3/Emu/RSX/Common/texture_cache_utils.h @@ -27,7 +27,7 @@ namespace rsx hash }; - static inline void memory_protect(const address_range& range, utils::protection prot) + static inline void memory_protect(const address_range32& range, utils::protection prot) { ensure(range.is_page_range()); @@ -232,7 +232,7 @@ namespace rsx private: u32 index = 0; - address_range range = {}; + address_range32 range = {}; block_container_type sections = {}; unowned_container_type unowned; // pointers to sections from other blocks that overlap this block atomic_t exists_count = 0; @@ -269,7 +269,7 @@ namespace rsx m_storage = storage; index = _index; - range = address_range::start_length(index * block_size, block_size); + range = address_range32::start_length(index * block_size, block_size); AUDIT(range.is_page_range() && get_start() / block_size == index); } @@ -346,12 +346,12 @@ namespace rsx } // Address range - inline const address_range& get_range() const { return range; } + inline const address_range32& get_range() const { return range; } inline u32 get_start() const { return range.start; } inline u32 get_end() const { return range.end; } inline u32 get_index() const { return index; } inline bool overlaps(const section_storage_type& section, section_bounds bounds = full_range) const { return section.overlaps(range, bounds); } - inline bool overlaps(const address_range& _range) const { return range.overlaps(_range); } + inline bool overlaps(const address_range32& _range) const { return range.overlaps(_range); } /** * Section callbacks @@ -511,7 +511,7 @@ namespace rsx return blocks[address / block_size]; } - inline block_type& block_for(const address_range &range) + inline block_type& block_for(const address_range32 &range) { AUDIT(range.valid()); return block_for(range.start); @@ -689,7 +689,7 @@ namespace rsx // Constructors range_iterator_tmpl() = default; // end iterator - explicit range_iterator_tmpl(parent_type &storage, const address_range &_range, section_bounds _bounds, bool _locked_only) + explicit range_iterator_tmpl(parent_type &storage, const address_range32 &_range, section_bounds _bounds, bool _locked_only) : range(_range) , bounds(_bounds) , block(&storage.block_for(range.start)) @@ -704,7 +704,7 @@ namespace rsx private: // Members - address_range range; + address_range32 range; section_bounds bounds; block_type *block = nullptr; @@ -825,16 +825,16 @@ namespace rsx using range_iterator = range_iterator_tmpl; using range_const_iterator = range_iterator_tmpl; - inline range_iterator range_begin(const address_range &range, section_bounds bounds, bool locked_only = false) { + inline range_iterator range_begin(const address_range32 &range, section_bounds bounds, bool locked_only = false) { return range_iterator(*this, range, bounds, locked_only); } - inline range_const_iterator range_begin(const address_range &range, section_bounds bounds, bool locked_only = false) const { + inline range_const_iterator range_begin(const address_range32 &range, section_bounds bounds, bool locked_only = false) const { return range_const_iterator(*this, range, bounds, locked_only); } inline range_const_iterator range_begin(u32 address, section_bounds bounds, bool locked_only = false) const { - return range_const_iterator(*this, address_range::start_length(address, 1), bounds, locked_only); + return range_const_iterator(*this, address_range32::start_length(address, 1), bounds, locked_only); } constexpr range_iterator range_end() @@ -881,9 +881,9 @@ namespace rsx class buffered_section { private: - address_range locked_range; - address_range cpu_range = {}; - address_range confirmed_range; + address_range32 locked_range; + address_range32 cpu_range = {}; + address_range32 confirmed_range; utils::protection protection = utils::protection::rw; @@ -891,7 +891,7 @@ namespace rsx u64 mem_hash = 0; bool locked = false; - void init_lockable_range(const address_range& range); + void init_lockable_range(const address_range32& range); u64 fast_hash_internal() const; public: @@ -899,7 +899,7 @@ namespace rsx buffered_section() = default; ~buffered_section() = default; - void reset(const address_range& memory_range); + void reset(const address_range32& memory_range); protected: void invalidate_range(); @@ -911,7 +911,7 @@ namespace rsx bool sync() const; void discard(); - const address_range& get_bounds(section_bounds bounds) const; + const address_range32& get_bounds(section_bounds bounds) const; bool is_locked(bool actual_page_flags = false) const; @@ -923,7 +923,7 @@ namespace rsx return get_bounds(bounds).overlaps(address); } - inline bool overlaps(const address_range& other, section_bounds bounds) const + inline bool overlaps(const address_range32& other, section_bounds bounds) const { return get_bounds(bounds).overlaps(other); } @@ -938,7 +938,7 @@ namespace rsx return get_bounds(bounds).overlaps(other.get_bounds(bounds)); } - inline bool inside(const address_range& other, section_bounds bounds) const + inline bool inside(const address_range32& other, section_bounds bounds) const { return get_bounds(bounds).inside(other); } @@ -953,12 +953,12 @@ namespace rsx return get_bounds(bounds).inside(other.get_bounds(bounds)); } - inline s32 signed_distance(const address_range& other, section_bounds bounds) const + inline s32 signed_distance(const address_range32& other, section_bounds bounds) const { return get_bounds(bounds).signed_distance(other); } - inline u32 distance(const address_range& other, section_bounds bounds) const + inline u32 distance(const address_range32& other, section_bounds bounds) const { return get_bounds(bounds).distance(other); } @@ -981,18 +981,18 @@ namespace rsx return cpu_range.valid() ? cpu_range.length() : 0; } - inline const address_range& get_locked_range() const + inline const address_range32& get_locked_range() const { AUDIT(locked); return locked_range; } - inline const address_range& get_section_range() const + inline const address_range32& get_section_range() const { return cpu_range; } - const address_range& get_confirmed_range() const + const address_range32& get_confirmed_range() const { return confirmed_range.valid() ? confirmed_range : cpu_range; } @@ -1005,7 +1005,7 @@ namespace rsx return { confirmed_range.start - cpu_range.start, confirmed_range.length() }; } - inline bool matches(const address_range& range) const + inline bool matches(const address_range32& range) const { return cpu_range.valid() && cpu_range == range; } @@ -1015,7 +1015,7 @@ namespace rsx return protection; } - inline address_range get_min_max(const address_range& current_min_max, section_bounds bounds) const + inline address_range32 get_min_max(const address_range32& current_min_max, section_bounds bounds) const { return get_bounds(bounds).get_min_max(current_min_max); } @@ -1124,7 +1124,7 @@ namespace rsx /** * Reset */ - void reset(const address_range &memory_range) + void reset(const address_range32 &memory_range) { AUDIT(memory_range.valid()); AUDIT(!is_locked()); @@ -1537,7 +1537,7 @@ namespace rsx void imp_flush_memcpy(u32 vm_dst, u8* src, u32 len) const { u8 *dst = get_ptr(vm_dst); - address_range copy_range = address_range::start_length(vm_dst, len); + address_range32 copy_range = address_range32::start_length(vm_dst, len); if (flush_exclusions.empty() || !copy_range.overlaps(flush_exclusions)) { @@ -1673,7 +1673,7 @@ namespace rsx cleanup_flush(); } - void add_flush_exclusion(const address_range& rng) + void add_flush_exclusion(const address_range32& rng) { AUDIT(is_locked() && is_flushable()); const auto _rng = rng.get_intersect(get_section_range()); @@ -1804,7 +1804,7 @@ namespace rsx /** * Comparison */ - inline bool matches(const address_range &memory_range) const + inline bool matches(const address_range32 &memory_range) const { return valid_range() && rsx::buffered_section::matches(memory_range); } @@ -1846,7 +1846,7 @@ namespace rsx return matches(format, width, height, depth, mipmaps); } - bool matches(const address_range& memory_range, u32 format, u32 width, u32 height, u32 depth, u32 mipmaps) const + bool matches(const address_range32& memory_range, u32 format, u32 width, u32 height, u32 depth, u32 mipmaps) const { if (!valid_range()) return false; diff --git a/rpcs3/Emu/RSX/Core/RSXContext.cpp b/rpcs3/Emu/RSX/Core/RSXContext.cpp index 3d770b8ce2..aa5962c745 100644 --- a/rpcs3/Emu/RSX/Core/RSXContext.cpp +++ b/rpcs3/Emu/RSX/Core/RSXContext.cpp @@ -4,7 +4,7 @@ namespace rsx { - GCM_tile_reference GCM_context::get_tiled_memory_region(const utils::address_range& range) const + GCM_tile_reference GCM_context::get_tiled_memory_region(const utils::address_range32& range) const { if (rsx::get_location(range.start) != CELL_GCM_LOCATION_MAIN) { @@ -27,7 +27,7 @@ namespace rsx } const auto tile_base_address = iomap_table.get_addr(tile.offset); - const auto tile_range = utils::address_range::start_length(tile_base_address, tile.size); + const auto tile_range = utils::address_range32::start_length(tile_base_address, tile.size); if (range.inside(tile_range)) { @@ -39,12 +39,12 @@ namespace rsx return {}; } - utils::address_range GCM_tile_reference::tile_align(const utils::address_range& range) const + utils::address_range32 GCM_tile_reference::tile_align(const utils::address_range32& range) const { const auto alignment = 64 * tile->pitch; const u32 start_offset = rsx::align_down2(range.start - base_address, alignment); const u32 end_offset = rsx::align2(range.end - base_address + 1, alignment); - return utils::address_range::start_length(start_offset + base_address, end_offset - start_offset); + return utils::address_range32::start_length(start_offset + base_address, end_offset - start_offset); } } diff --git a/rpcs3/Emu/RSX/Core/RSXContext.h b/rpcs3/Emu/RSX/Core/RSXContext.h index 3b69d569aa..dd18747012 100644 --- a/rpcs3/Emu/RSX/Core/RSXContext.h +++ b/rpcs3/Emu/RSX/Core/RSXContext.h @@ -27,7 +27,7 @@ namespace rsx return !!tile; } - utils::address_range tile_align(const rsx::address_range& range) const; + utils::address_range32 tile_align(const rsx::address_range32& range) const; }; struct GCM_context @@ -53,6 +53,6 @@ namespace rsx atomic_t unsent_gcm_events = 0; // Unsent event bits when aborting RSX/VBLANK thread (will be sent on savestate load) - GCM_tile_reference get_tiled_memory_region(const utils::address_range& range) const; + GCM_tile_reference get_tiled_memory_region(const utils::address_range32& range) const; }; } diff --git a/rpcs3/Emu/RSX/Core/RSXReservationLock.hpp b/rpcs3/Emu/RSX/Core/RSXReservationLock.hpp index 06ae47796e..7a4ab76624 100644 --- a/rpcs3/Emu/RSX/Core/RSXReservationLock.hpp +++ b/rpcs3/Emu/RSX/Core/RSXReservationLock.hpp @@ -49,9 +49,9 @@ namespace rsx return; } - const auto range1 = utils::address_range::start_length(dst_addr, dst_length); - const auto range2 = utils::address_range::start_length(src_addr, src_length); - utils::address_range target_range; + const auto range1 = utils::address_range32::start_length(dst_addr, dst_length); + const auto range2 = utils::address_range32::start_length(src_addr, src_length); + utils::address_range32 target_range; if (!range1.overlaps(range2)) [[likely]] { diff --git a/rpcs3/Emu/RSX/GL/GLDMA.cpp b/rpcs3/Emu/RSX/GL/GLDMA.cpp index 758205214e..3c12009f67 100644 --- a/rpcs3/Emu/RSX/GL/GLDMA.cpp +++ b/rpcs3/Emu/RSX/GL/GLDMA.cpp @@ -29,7 +29,7 @@ namespace gl gl::check_state(); } - void* dma_block::map(const utils::address_range& range) const + void* dma_block::map(const utils::address_range32& range) const { ensure(range.inside(this->range())); return vm::get_super_ptr(range.start); @@ -58,7 +58,7 @@ namespace gl } } - bool dma_block::can_map(const utils::address_range& range) const + bool dma_block::can_map(const utils::address_range32& range) const { if (m_parent) { @@ -73,11 +73,11 @@ namespace gl g_dma_pool.clear(); } - utils::address_range to_dma_block_range(u32 start, u32 length) + utils::address_range32 to_dma_block_range(u32 start, u32 length) { const auto start_block_address = start & s_dma_block_mask; const auto end_block_address = (start + length + s_dma_block_size - 1) & s_dma_block_mask; - return utils::address_range::start_end(start_block_address, end_block_address); + return utils::address_range32::start_end(start_block_address, end_block_address); } const dma_block& get_block(u32 start, u32 length) @@ -91,7 +91,7 @@ namespace gl return *block; } - const auto range = utils::address_range::start_length(start, length); + const auto range = utils::address_range32::start_length(start, length); if (block->can_map(range)) [[ likely ]] { return *block; diff --git a/rpcs3/Emu/RSX/GL/GLDMA.h b/rpcs3/Emu/RSX/GL/GLDMA.h index 1e4b31bae0..c5862f5166 100644 --- a/rpcs3/Emu/RSX/GL/GLDMA.h +++ b/rpcs3/Emu/RSX/GL/GLDMA.h @@ -21,17 +21,17 @@ namespace gl void allocate(u32 base_address, u32 block_size); void resize(u32 new_length); - void* map(const utils::address_range& range) const; + void* map(const utils::address_range32& range) const; void set_parent(const dma_block* other); const dma_block* head() const { return m_parent ? m_parent : this; } - bool can_map(const utils::address_range& range) const; + bool can_map(const utils::address_range32& range) const; u32 base_addr() const { return m_base_address; } u32 length() const { return m_data ? static_cast(m_data->size()) : 0; } bool empty() const { return length() == 0; } buffer* get() const { return m_data.get(); } - utils::address_range range() const { return utils::address_range::start_length(m_base_address, length()); } + utils::address_range32 range() const { return utils::address_range32::start_length(m_base_address, length()); } protected: u32 m_base_address = 0; diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index b6c27c4dd8..1470f8fead 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -1240,7 +1240,7 @@ bool GLGSRender::on_access_violation(u32 address, bool is_writing) return true; } -void GLGSRender::on_invalidate_memory_range(const utils::address_range &range, rsx::invalidation_cause cause) +void GLGSRender::on_invalidate_memory_range(const utils::address_range32 &range, rsx::invalidation_cause cause) { gl::command_context cmd{ gl_state }; auto data = m_gl_texture_cache.invalidate_range(cmd, range, cause); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 59a7e075b9..51b126cc73 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -223,7 +223,7 @@ protected: void do_local_task(rsx::FIFO::state state) override; bool on_access_violation(u32 address, bool is_writing) override; - void on_invalidate_memory_range(const utils::address_range &range, rsx::invalidation_cause cause) override; + void on_invalidate_memory_range(const utils::address_range32 &range, rsx::invalidation_cause cause) override; void notify_tile_unbound(u32 tile) override; void on_semaphore_acquire_wait() override; }; diff --git a/rpcs3/Emu/RSX/GL/GLPresent.cpp b/rpcs3/Emu/RSX/GL/GLPresent.cpp index c73415edb2..ed71652063 100644 --- a/rpcs3/Emu/RSX/GL/GLPresent.cpp +++ b/rpcs3/Emu/RSX/GL/GLPresent.cpp @@ -129,7 +129,7 @@ gl::texture* GLGSRender::get_present_source(gl::present_surface_info* info, cons initialize_scratch_image(); gl::command_context cmd{ gl_state }; - const auto range = utils::address_range::start_length(info->address, info->pitch * info->height); + const auto range = utils::address_range32::start_length(info->address, info->pitch * info->height); m_gl_texture_cache.invalidate_range(cmd, range, rsx::invalidation_cause::read); flip_image->copy_from(vm::base(info->address), static_cast(expected_format), gl::texture::type::uint_8_8_8_8, unpack_settings); diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index 87e5ee5645..c222262699 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -153,7 +153,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /* { if (m_surface_info[i].pitch && g_cfg.video.write_color_buffers) { - const utils::address_range surface_range = m_surface_info[i].get_memory_range(); + const utils::address_range32 surface_range = m_surface_info[i].get_memory_range(); m_gl_texture_cache.set_memory_read_flags(surface_range, rsx::memory_read_flags::flush_once); m_gl_texture_cache.flush_if_cache_miss_likely(cmd, surface_range); } @@ -182,7 +182,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /* if (m_depth_surface_info.pitch && g_cfg.video.write_depth_buffer) { - const utils::address_range surface_range = m_depth_surface_info.get_memory_range(); + const utils::address_range32 surface_range = m_depth_surface_info.get_memory_range(); m_gl_texture_cache.set_memory_read_flags(surface_range, rsx::memory_read_flags::flush_once); m_gl_texture_cache.flush_if_cache_miss_likely(cmd, surface_range); } diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 45d787c184..f3b37e7f27 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -148,7 +148,7 @@ namespace gl } } - void dma_transfer(gl::command_context& cmd, gl::texture* src, const areai& /*src_area*/, const utils::address_range& /*valid_range*/, u32 pitch) + void dma_transfer(gl::command_context& cmd, gl::texture* src, const areai& /*src_area*/, const utils::address_range32& /*valid_range*/, u32 pitch) { init_buffer(src); glGetError(); @@ -600,7 +600,7 @@ namespace gl copy_transfer_regions_impl(cmd, dst->image(), region); } - cached_texture_section* create_new_texture(gl::command_context& cmd, const utils::address_range &rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, + cached_texture_section* create_new_texture(gl::command_context& cmd, const utils::address_range32 &rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, u32 gcm_format, rsx::texture_upload_context context, rsx::texture_dimension_extended type, bool swizzled, rsx::component_order swizzle_flags, rsx::flags32_t /*flags*/) override { const rsx::image_section_attributes_t search_desc = { .gcm_format = gcm_format, .width = width, .height = height, .depth = depth, .mipmaps = mipmaps }; @@ -708,7 +708,7 @@ namespace gl cached_texture_section* create_nul_section( gl::command_context& /*cmd*/, - const utils::address_range& rsx_range, + const utils::address_range32& rsx_range, const rsx::image_section_attributes_t& attrs, const rsx::GCM_tile_reference& /*tile*/, bool /*memory_load*/) override @@ -726,7 +726,7 @@ namespace gl return &cached; } - cached_texture_section* upload_image_from_cpu(gl::command_context& cmd, const utils::address_range& rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, u32 gcm_format, + cached_texture_section* upload_image_from_cpu(gl::command_context& cmd, const utils::address_range32& rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, u32 gcm_format, rsx::texture_upload_context context, const std::vector& subresource_layout, rsx::texture_dimension_extended type, bool input_swizzled) override { auto section = create_new_texture(cmd, rsx_range, width, height, depth, mipmaps, pitch, gcm_format, context, type, input_swizzled, diff --git a/rpcs3/Emu/RSX/GL/glutils/ring_buffer.cpp b/rpcs3/Emu/RSX/GL/glutils/ring_buffer.cpp index da77b50cbe..146136e4b4 100644 --- a/rpcs3/Emu/RSX/GL/glutils/ring_buffer.cpp +++ b/rpcs3/Emu/RSX/GL/glutils/ring_buffer.cpp @@ -280,7 +280,7 @@ namespace gl void scratch_ring_buffer::pop_barrier(u32 start, u32 length) { - const auto range = utils::address_range::start_length(start, length); + const auto range = utils::address_range32::start_length(start, length); m_barriers.erase(std::remove_if(m_barriers.begin(), m_barriers.end(), [&range](auto& barrier_) { if (barrier_.range.overlaps(range)) @@ -302,7 +302,7 @@ namespace gl } barrier barrier_; - barrier_.range = utils::address_range::start_length(start, length); + barrier_.range = utils::address_range32::start_length(start, length); barrier_.signal.create(); m_barriers.emplace_back(barrier_); } diff --git a/rpcs3/Emu/RSX/GL/glutils/ring_buffer.h b/rpcs3/Emu/RSX/GL/glutils/ring_buffer.h index 97f802ddf2..37ba0e4bdf 100644 --- a/rpcs3/Emu/RSX/GL/glutils/ring_buffer.h +++ b/rpcs3/Emu/RSX/GL/glutils/ring_buffer.h @@ -88,7 +88,7 @@ namespace gl struct barrier { fence signal; - utils::address_range range; + utils::address_range32 range; }; buffer m_storage; diff --git a/rpcs3/Emu/RSX/Host/MM.cpp b/rpcs3/Emu/RSX/Host/MM.cpp index 613f05e828..affb932fd1 100644 --- a/rpcs3/Emu/RSX/Host/MM.cpp +++ b/rpcs3/Emu/RSX/Host/MM.cpp @@ -90,7 +90,7 @@ namespace rsx } } - void mm_flush(const rsx::simple_array& ranges) + void mm_flush(const rsx::simple_array& ranges) { std::lock_guard lock(g_mprotect_queue_lock); if (g_deferred_mprotect_queue.empty()) diff --git a/rpcs3/Emu/RSX/Host/MM.h b/rpcs3/Emu/RSX/Host/MM.h index 0c70a81aa5..f71fbb69aa 100644 --- a/rpcs3/Emu/RSX/Host/MM.h +++ b/rpcs3/Emu/RSX/Host/MM.h @@ -39,6 +39,6 @@ namespace rsx void mm_protect(void* start, u64 length, utils::protection prot); void mm_flush_lazy(); void mm_flush(u32 vm_address); - void mm_flush(const rsx::simple_array& ranges); + void mm_flush(const rsx::simple_array& ranges); void mm_flush(); } diff --git a/rpcs3/Emu/RSX/NV47/HW/nv0039.cpp b/rpcs3/Emu/RSX/NV47/HW/nv0039.cpp index 831fa60adc..10ea3ff5db 100644 --- a/rpcs3/Emu/RSX/NV47/HW/nv0039.cpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv0039.cpp @@ -58,10 +58,10 @@ namespace rsx auto res = ::rsx::reservation_lock(write_address, write_length, read_address, read_length); - rsx::simple_array flush_mm_ranges = + rsx::simple_array flush_mm_ranges = { - utils::address_range::start_length(write_address, write_length).to_page_range(), - utils::address_range::start_length(read_address, read_length).to_page_range() + utils::address_range32::start_length(write_address, write_length).to_page_range(), + utils::address_range32::start_length(read_address, read_length).to_page_range() }; rsx::mm_flush(flush_mm_ranges); diff --git a/rpcs3/Emu/RSX/NV47/HW/nv3089.cpp b/rpcs3/Emu/RSX/NV47/HW/nv3089.cpp index 1082ae41b9..cbc2e54296 100644 --- a/rpcs3/Emu/RSX/NV47/HW/nv3089.cpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv3089.cpp @@ -328,8 +328,8 @@ namespace rsx { const bool is_overlapping = !src_is_modified && dst.dma == src.dma && [&]() -> bool { - const auto src_range = utils::address_range::start_length(src.rsx_address, src.pitch * (src.height - 1) + (src.bpp * src.width)); - const auto dst_range = utils::address_range::start_length(dst.rsx_address, dst.pitch * (dst.clip_height - 1) + (dst.bpp * dst.clip_width)); + const auto src_range = utils::address_range32::start_length(src.rsx_address, src.pitch * (src.height - 1) + (src.bpp * src.width)); + const auto dst_range = utils::address_range32::start_length(dst.rsx_address, dst.pitch * (dst.clip_height - 1) + (dst.bpp * dst.clip_width)); return src_range.overlaps(dst_range); }(); @@ -612,7 +612,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_range::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, dst.pitch * dst.clip_height)); std::vector tmp; if (tiled_region) diff --git a/rpcs3/Emu/RSX/RSXOffload.cpp b/rpcs3/Emu/RSX/RSXOffload.cpp index 5f8737543e..f306784d59 100644 --- a/rpcs3/Emu/RSX/RSXOffload.cpp +++ b/rpcs3/Emu/RSX/RSXOffload.cpp @@ -212,7 +212,7 @@ namespace rsx } // Fault recovery - utils::address_range dma_manager::get_fault_range(bool writing) const + utils::address_range32 dma_manager::get_fault_range(bool writing) const { const auto m_current_job = ensure(m_thread->m_current_job); @@ -237,6 +237,6 @@ namespace rsx fmt::throw_exception("Unreachable"); } - return utils::address_range::start_length(vm::get_addr(address), range); + return utils::address_range32::start_length(vm::get_addr(address), range); } } diff --git a/rpcs3/Emu/RSX/RSXOffload.h b/rpcs3/Emu/RSX/RSXOffload.h index 8622134962..6e1e5d7476 100644 --- a/rpcs3/Emu/RSX/RSXOffload.h +++ b/rpcs3/Emu/RSX/RSXOffload.h @@ -83,6 +83,6 @@ namespace rsx void clear_mem_fault_flag(); // Fault recovery - utils::address_range get_fault_range(bool writing) const; + utils::address_range32 get_fault_range(bool writing) const; }; } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index ffd09a742f..f0a72c05fc 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -1233,7 +1233,7 @@ namespace rsx { std::lock_guard lock(m_mtx_task); - m_invalidated_memory_range = utils::address_range::start_end(0x2 << 28, constants::local_mem_base + local_mem_size - 1); + m_invalidated_memory_range = utils::address_range32::start_end(0x2 << 28, constants::local_mem_base + local_mem_size - 1); handle_invalidated_memory_range(); } } @@ -2299,8 +2299,8 @@ namespace rsx return false; } - const auto current_fragment_shader_range = address_range::start_length(shader_offset, current_fragment_program.total_length); - if (!current_fragment_shader_range.overlaps(address_range::start_length(dst_offset, size))) + const auto current_fragment_shader_range = address_range32::start_length(shader_offset, current_fragment_program.total_length); + if (!current_fragment_shader_range.overlaps(address_range32::start_length(dst_offset, size))) { // No range overlap return false; @@ -2832,7 +2832,7 @@ namespace rsx reader_lock lock(m_mtx_task); - const auto map_range = address_range::start_length(address, size); + const auto map_range = address_range32::start_length(address, size); if (!m_invalidated_memory_range.valid()) return; @@ -2918,7 +2918,7 @@ namespace rsx // Queue up memory invalidation std::lock_guard lock(m_mtx_task); const bool existing_range_valid = m_invalidated_memory_range.valid(); - const auto unmap_range = address_range::start_length(address, size); + const auto unmap_range = address_range32::start_length(address, size); if (existing_range_valid && m_invalidated_memory_range.touches(unmap_range)) { diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 6b078a522b..73aacf360a 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -149,7 +149,7 @@ namespace rsx virtual f64 get_display_refresh_rate() const = 0; // Invalidated memory range - address_range m_invalidated_memory_range; + address_range32 m_invalidated_memory_range; // Profiler rsx::profiling_timer m_profiler; @@ -353,7 +353,7 @@ namespace rsx virtual void flip(const display_flip_info_t& info) = 0; virtual u64 timestamp(); virtual bool on_access_violation(u32 /*address*/, bool /*is_writing*/) { return false; } - virtual void on_invalidate_memory_range(const address_range & /*range*/, rsx::invalidation_cause) {} + virtual void on_invalidate_memory_range(const address_range32 & /*range*/, rsx::invalidation_cause) {} virtual void notify_tile_unbound(u32 /*tile*/) {} // control diff --git a/rpcs3/Emu/RSX/RSXZCULL.cpp b/rpcs3/Emu/RSX/RSXZCULL.cpp index 117caa7b4e..3dd9d1a776 100644 --- a/rpcs3/Emu/RSX/RSXZCULL.cpp +++ b/rpcs3/Emu/RSX/RSXZCULL.cpp @@ -788,7 +788,7 @@ namespace rsx u32 ZCULL_control::copy_reports_to(u32 start, u32 range, u32 dest) { u32 bytes_to_write = 0; - const auto memory_range = utils::address_range::start_length(start, range); + const auto memory_range = utils::address_range32::start_length(start, range); for (auto& writer : m_pending_writes) { if (!writer.sink) diff --git a/rpcs3/Emu/RSX/VK/VKDMA.cpp b/rpcs3/Emu/RSX/VK/VKDMA.cpp index 0aa7d864b7..09834d6f99 100644 --- a/rpcs3/Emu/RSX/VK/VKDMA.cpp +++ b/rpcs3/Emu/RSX/VK/VKDMA.cpp @@ -27,7 +27,7 @@ namespace vk free(); } - void* dma_block::map_range(const utils::address_range& range) + void* dma_block::map_range(const utils::address_range32& range) { if (inheritance_info.parent) { @@ -142,7 +142,7 @@ namespace vk inheritance_info.block_offset = (addr - parent->base_address); } - void dma_block::flush(const utils::address_range& range) + void dma_block::flush(const utils::address_range32& range) { if (inheritance_info.parent) { @@ -158,7 +158,7 @@ namespace vk // NOTE: Do not unmap. This can be extremely slow on some platforms. } - void dma_block::load(const utils::address_range& range) + void dma_block::load(const utils::address_range32& range) { if (inheritance_info.parent) { @@ -174,7 +174,7 @@ namespace vk // NOTE: Do not unmap. This can be extremely slow on some platforms. } - dma_mapping_handle dma_block::get(const utils::address_range& range) + dma_mapping_handle dma_block::get(const utils::address_range32& range) { if (inheritance_info.parent) { @@ -264,7 +264,7 @@ namespace vk s_allocated_dma_pool_size += allocated_memory->size(); } - void* dma_block_EXT::map_range(const utils::address_range& range) + void* dma_block_EXT::map_range(const utils::address_range32& range) { return vm::get_super_ptr(range.start); } @@ -274,12 +274,12 @@ namespace vk // NOP } - void dma_block_EXT::flush(const utils::address_range&) + void dma_block_EXT::flush(const utils::address_range32&) { // NOP } - void dma_block_EXT::load(const utils::address_range&) + void dma_block_EXT::load(const utils::address_range32&) { // NOP } @@ -336,7 +336,7 @@ namespace vk // Not much contention expected here, avoid searching twice std::lock_guard lock(g_dma_mutex); - const auto map_range = utils::address_range::start_length(local_address, length); + const auto map_range = utils::address_range32::start_length(local_address, length); auto first_block = (local_address & s_dma_block_mask); if (auto found = g_dma_pool.find(first_block); found != g_dma_pool.end()) @@ -454,7 +454,7 @@ namespace vk if (auto found = g_dma_pool.find(block); found != g_dma_pool.end()) { const auto sync_end = std::min(limit, found->second->end()); - const auto range = utils::address_range::start_end(local_address, sync_end); + const auto range = utils::address_range32::start_end(local_address, sync_end); if constexpr (load) { diff --git a/rpcs3/Emu/RSX/VK/VKDMA.h b/rpcs3/Emu/RSX/VK/VKDMA.h index e718733649..3cc0855f57 100644 --- a/rpcs3/Emu/RSX/VK/VKDMA.h +++ b/rpcs3/Emu/RSX/VK/VKDMA.h @@ -28,7 +28,7 @@ namespace vk virtual void allocate(const render_device& dev, usz size); virtual void free(); - virtual void* map_range(const utils::address_range& range); + virtual void* map_range(const utils::address_range32& range); virtual void unmap(); public: @@ -38,9 +38,9 @@ namespace vk virtual void init(const render_device& dev, u32 addr, usz size); virtual void init(dma_block* parent, u32 addr, usz size); - virtual void flush(const utils::address_range& range); - virtual void load(const utils::address_range& range); - std::pair get(const utils::address_range& range); + virtual void flush(const utils::address_range32& range); + virtual void load(const utils::address_range32& range); + std::pair get(const utils::address_range32& range); u32 start() const; u32 end() const; @@ -56,11 +56,11 @@ namespace vk { private: void allocate(const render_device& dev, usz size) override; - void* map_range(const utils::address_range& range) override; + void* map_range(const utils::address_range32& range) override; void unmap() override; public: - void flush(const utils::address_range& range) override; - void load(const utils::address_range& range) override; + void flush(const utils::address_range32& range) override; + void load(const utils::address_range32& range) override; }; } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 9ac52774ea..107cd7b399 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -976,7 +976,7 @@ bool VKGSRender::on_access_violation(u32 address, bool is_writing) return true; } -void VKGSRender::on_invalidate_memory_range(const utils::address_range &range, rsx::invalidation_cause cause) +void VKGSRender::on_invalidate_memory_range(const utils::address_range32 &range, rsx::invalidation_cause cause) { std::lock_guard lock(m_secondary_cb_guard); @@ -2438,7 +2438,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) // Flush old address if we keep missing it if (m_surface_info[i].pitch && g_cfg.video.write_color_buffers) { - const utils::address_range rsx_range = m_surface_info[i].get_memory_range(); + const utils::address_range32 rsx_range = m_surface_info[i].get_memory_range(); m_texture_cache.set_memory_read_flags(rsx_range, rsx::memory_read_flags::flush_once); m_texture_cache.flush_if_cache_miss_likely(*m_current_command_buffer, rsx_range); } @@ -2455,7 +2455,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) { if (m_depth_surface_info.pitch && g_cfg.video.write_depth_buffer) { - const utils::address_range surface_range = m_depth_surface_info.get_memory_range(); + const utils::address_range32 surface_range = m_depth_surface_info.get_memory_range(); m_texture_cache.set_memory_read_flags(surface_range, rsx::memory_read_flags::flush_once); m_texture_cache.flush_if_cache_miss_likely(*m_current_command_buffer, surface_range); } @@ -2572,7 +2572,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) { if (!m_surface_info[index].address || !m_surface_info[index].pitch) continue; - const utils::address_range surface_range = m_surface_info[index].get_memory_range(); + const utils::address_range32 surface_range = m_surface_info[index].get_memory_range(); if (g_cfg.video.write_color_buffers) { m_texture_cache.lock_memory_region( @@ -2588,7 +2588,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) if (m_depth_surface_info.address && m_depth_surface_info.pitch) { - const utils::address_range surface_range = m_depth_surface_info.get_memory_range(); + const utils::address_range32 surface_range = m_depth_surface_info.get_memory_range(); if (g_cfg.video.write_depth_buffer) { const u32 gcm_format = (m_depth_surface_info.depth_format == rsx::surface_depth_format::z16) ? CELL_GCM_TEXTURE_DEPTH16 : CELL_GCM_TEXTURE_DEPTH24_D8; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index f37c0d411b..e16d8d1afa 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -170,7 +170,7 @@ private: // Offloader thread deadlock recovery rsx::atomic_bitmask_t m_queue_status; - utils::address_range m_offloader_fault_range; + utils::address_range32 m_offloader_fault_range; rsx::invalidation_cause m_offloader_fault_cause; vk::draw_call_t m_current_draw {}; @@ -289,6 +289,6 @@ protected: void notify_tile_unbound(u32 tile) override; bool on_access_violation(u32 address, bool is_writing) override; - void on_invalidate_memory_range(const utils::address_range &range, rsx::invalidation_cause cause) override; + void on_invalidate_memory_range(const utils::address_range32 &range, rsx::invalidation_cause cause) override; void on_semaphore_acquire_wait() override; }; diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index 302abfb805..9d07a4581e 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -86,7 +86,7 @@ namespace vk VkImageAspectFlags flags, vk::data_heap &upload_heap, u32 heap_align, rsx::flags32_t image_setup_flags); std::pair detile_memory_block( - const vk::command_buffer& cmd, const rsx::GCM_tile_reference& tiled_region, const utils::address_range& range, + const vk::command_buffer& cmd, const rsx::GCM_tile_reference& tiled_region, const utils::address_range32& range, u16 width, u16 height, u8 bpp); // Other texture management helpers diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index 0d2912df89..a685dbabaa 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -325,7 +325,7 @@ vk::viewable_image* VKGSRender::get_present_source(/* inout */ vk::present_surfa if (!image_to_flip) [[ unlikely ]] { // Read from cell - const auto range = utils::address_range::start_length(info->address, info->pitch * info->height); + const auto range = utils::address_range32::start_length(info->address, info->pitch * info->height); const u32 lookup_mask = rsx::texture_upload_context::blit_engine_dst | rsx::texture_upload_context::framebuffer_storage; const auto overlap = m_texture_cache.find_texture_from_range(range, 0, lookup_mask); diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp b/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp index 11e7747f2f..0356a1c7d8 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp @@ -93,7 +93,7 @@ namespace vk // Drop MSAA resolve/unresolve caches. Only trigger when a hard sync is guaranteed to follow else it will cause even more problems! // 2-pass to ensure resources are available where they are most needed - auto relieve_memory_pressure = [&](auto& list, const utils::address_range& range) + auto relieve_memory_pressure = [&](auto& list, const utils::address_range32& range) { for (auto it = list.begin_range(range); it != list.end(); ++it) { @@ -254,7 +254,7 @@ namespace vk std::vector sorted_list; sorted_list.reserve(1024); - auto process_list_function = [&](auto& list, const utils::address_range& range) + auto process_list_function = [&](auto& list, const utils::address_range32& range) { for (auto it = list.begin_range(range); it != list.end(); ++it) { diff --git a/rpcs3/Emu/RSX/VK/VKTexture.cpp b/rpcs3/Emu/RSX/VK/VKTexture.cpp index d8d06420da..23b76df52b 100644 --- a/rpcs3/Emu/RSX/VK/VKTexture.cpp +++ b/rpcs3/Emu/RSX/VK/VKTexture.cpp @@ -1247,7 +1247,7 @@ namespace vk } std::pair detile_memory_block(const vk::command_buffer& cmd, const rsx::GCM_tile_reference& tiled_region, - const utils::address_range& range, u16 width, u16 height, u8 bpp) + const utils::address_range32& range, u16 width, u16 height, u8 bpp) { // Calculate the true length of the usable memory section const auto available_tile_size = tiled_region.tile->size - (range.start - tiled_region.base_address); diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.cpp b/rpcs3/Emu/RSX/VK/VKTextureCache.cpp index 7107e1f32b..fc1efb3533 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.cpp +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.cpp @@ -62,7 +62,7 @@ namespace vk } } - void cached_texture_section::dma_transfer(vk::command_buffer& cmd, vk::image* src, const areai& src_area, const utils::address_range& valid_range, u32 pitch) + void cached_texture_section::dma_transfer(vk::command_buffer& cmd, vk::image* src, const areai& src_area, const utils::address_range32& valid_range, u32 pitch) { ensure(src->samples() == 1); @@ -921,7 +921,7 @@ namespace vk dst->pop_layout(cmd); } - cached_texture_section* texture_cache::create_new_texture(vk::command_buffer& cmd, const utils::address_range& rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, + cached_texture_section* texture_cache::create_new_texture(vk::command_buffer& cmd, const utils::address_range32& rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, u32 gcm_format, rsx::texture_upload_context context, rsx::texture_dimension_extended type, bool swizzled, rsx::component_order swizzle_flags, rsx::flags32_t flags) { const auto section_depth = depth; @@ -1076,7 +1076,7 @@ namespace vk cached_texture_section* texture_cache::create_nul_section( vk::command_buffer& /*cmd*/, - const utils::address_range& rsx_range, + const utils::address_range32& rsx_range, const rsx::image_section_attributes_t& attrs, const rsx::GCM_tile_reference& tile, bool memory_load) @@ -1101,7 +1101,7 @@ namespace vk return ®ion; } - cached_texture_section* texture_cache::upload_image_from_cpu(vk::command_buffer& cmd, const utils::address_range& rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, u32 gcm_format, + cached_texture_section* texture_cache::upload_image_from_cpu(vk::command_buffer& cmd, const utils::address_range32& rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, u32 gcm_format, rsx::texture_upload_context context, const std::vector& subresource_layout, rsx::texture_dimension_extended type, bool swizzled) { if (context != rsx::texture_upload_context::shader_read) diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 0228bd538e..8bbd131fe5 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -186,7 +186,7 @@ namespace vk return flushed; } - void dma_transfer(vk::command_buffer& cmd, vk::image* src, const areai& src_area, const utils::address_range& valid_range, u32 pitch); + void dma_transfer(vk::command_buffer& cmd, vk::image* src, const areai& src_area, const utils::address_range32& valid_range, u32 pitch); void copy_texture(vk::command_buffer& cmd, bool miss) { @@ -477,13 +477,13 @@ namespace vk void update_image_contents(vk::command_buffer& cmd, vk::image_view* dst_view, vk::image* src, u16 width, u16 height) override; - cached_texture_section* create_new_texture(vk::command_buffer& cmd, const utils::address_range& rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, + cached_texture_section* create_new_texture(vk::command_buffer& cmd, const utils::address_range32& rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, u32 gcm_format, rsx::texture_upload_context context, rsx::texture_dimension_extended type, bool swizzled, rsx::component_order swizzle_flags, rsx::flags32_t flags) override; - cached_texture_section* create_nul_section(vk::command_buffer& cmd, const utils::address_range& rsx_range, const rsx::image_section_attributes_t& attrs, + cached_texture_section* create_nul_section(vk::command_buffer& cmd, const utils::address_range32& rsx_range, const rsx::image_section_attributes_t& attrs, const rsx::GCM_tile_reference& tile, bool memory_load) override; - cached_texture_section* upload_image_from_cpu(vk::command_buffer& cmd, const utils::address_range& rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, u32 gcm_format, + cached_texture_section* upload_image_from_cpu(vk::command_buffer& cmd, const utils::address_range32& rsx_range, u16 width, u16 height, u16 depth, u16 mipmaps, u32 pitch, u32 gcm_format, rsx::texture_upload_context context, const std::vector& subresource_layout, rsx::texture_dimension_extended type, bool swizzled) override; void set_component_order(cached_texture_section& section, u32 gcm_format, rsx::component_order expected_flags) override; diff --git a/rpcs3/Emu/RSX/rsx_utils.h b/rpcs3/Emu/RSX/rsx_utils.h index 37874933f4..5b7c09cf5d 100644 --- a/rpcs3/Emu/RSX/rsx_utils.h +++ b/rpcs3/Emu/RSX/rsx_utils.h @@ -14,8 +14,8 @@ extern "C" namespace rsx { - // Import address_range utilities - using utils::address_range; + // Import address_range32 utilities + using utils::address_range32; using utils::address_range_vector; using utils::page_for; using utils::page_start; @@ -120,7 +120,7 @@ namespace rsx u8 bpp = 0; u8 samples = 0; - address_range range{}; + address_range32 range{}; gcm_framebuffer_info() = default; @@ -131,16 +131,16 @@ namespace rsx // Account for the last line of the block not reaching the end const u32 block_size = pitch * (height - 1) * aa_factor_v; const u32 line_size = width * aa_factor_u * bpp; - range = address_range::start_length(address, block_size + line_size); + range = address_range32::start_length(address, block_size + line_size); } - address_range get_memory_range(const u32* aa_factors) + address_range32 get_memory_range(const u32* aa_factors) { calculate_memory_range(aa_factors[0], aa_factors[1]); return range; } - address_range get_memory_range() const + address_range32 get_memory_range() const { ensure(range.start == address); return range; @@ -260,7 +260,7 @@ namespace rsx static inline u32 get_location(u32 addr) { // We don't really care about the actual memory map, it shouldn't be possible to use the mmio bar region anyway - constexpr address_range local_mem_range = address_range::start_length(rsx::constants::local_mem_base, 0x1000'0000); + constexpr address_range32 local_mem_range = address_range32::start_length(rsx::constants::local_mem_base, 0x1000'0000); return local_mem_range.overlaps(addr) ? CELL_GCM_LOCATION_LOCAL : CELL_GCM_LOCATION_MAIN; diff --git a/rpcs3/tests/test_address_range.cpp b/rpcs3/tests/test_address_range.cpp index 292f8c11bf..c75483bcc5 100644 --- a/rpcs3/tests/test_address_range.cpp +++ b/rpcs3/tests/test_address_range.cpp @@ -11,29 +11,29 @@ namespace utils TEST(AddressRange, Constructors) { // Default constructor - address_range empty; + address_range32 empty; EXPECT_FALSE(empty.valid()); EXPECT_EQ(empty.start, umax); EXPECT_EQ(empty.end, 0); // Static factory methods - address_range r1 = address_range::start_length(0x1000, 0x1000); + address_range32 r1 = address_range32::start_length(0x1000, 0x1000); EXPECT_EQ(r1.start, 0x1000); EXPECT_EQ(r1.end, 0x1FFF); EXPECT_EQ(r1.length(), 0x1000); EXPECT_TRUE(r1.valid()); - address_range r2 = address_range::start_end(0x2000, 0x2FFF); + address_range32 r2 = address_range32::start_end(0x2000, 0x2FFF); EXPECT_EQ(r2.start, 0x2000); EXPECT_EQ(r2.end, 0x2FFF); EXPECT_EQ(r2.length(), 0x1000); EXPECT_TRUE(r2.valid()); // Edge cases - address_range zero_length = address_range::start_length(0x1000, 0); + address_range32 zero_length = address_range32::start_length(0x1000, 0); EXPECT_FALSE(zero_length.valid()); - address_range single_byte = address_range::start_length(0x1000, 1); + address_range32 single_byte = address_range32::start_length(0x1000, 1); EXPECT_TRUE(single_byte.valid()); EXPECT_EQ(single_byte.start, 0x1000); EXPECT_EQ(single_byte.end, 0x1000); @@ -42,7 +42,7 @@ namespace utils TEST(AddressRange, LengthAndBoundaries) { - address_range r = address_range::start_length(0x1000, 0x1000); + address_range32 r = address_range32::start_length(0x1000, 0x1000); // Test length EXPECT_EQ(r.length(), 0x1000); @@ -60,40 +60,40 @@ namespace utils TEST(AddressRange, Overlapping) { - address_range r1 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + address_range32 r1 = address_range32::start_length(0x1000, 0x1000); // 0x1000-0x1FFF // Complete overlap - address_range r2 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + address_range32 r2 = address_range32::start_length(0x1000, 0x1000); // 0x1000-0x1FFF EXPECT_TRUE(r1.overlaps(r2)); EXPECT_TRUE(r2.overlaps(r1)); // Partial overlap at start - address_range r3 = address_range::start_length(0x800, 0x1000); // 0x800-0x17FF + address_range32 r3 = address_range32::start_length(0x800, 0x1000); // 0x800-0x17FF EXPECT_TRUE(r1.overlaps(r3)); EXPECT_TRUE(r3.overlaps(r1)); // Partial overlap at end - address_range r4 = address_range::start_length(0x1800, 0x1000); // 0x1800-0x27FF + address_range32 r4 = address_range32::start_length(0x1800, 0x1000); // 0x1800-0x27FF EXPECT_TRUE(r1.overlaps(r4)); EXPECT_TRUE(r4.overlaps(r1)); // No overlap, before - address_range r5 = address_range::start_length(0x0, 0x1000); // 0x0-0xFFF + address_range32 r5 = address_range32::start_length(0x0, 0x1000); // 0x0-0xFFF EXPECT_FALSE(r1.overlaps(r5)); EXPECT_FALSE(r5.overlaps(r1)); // No overlap, after - address_range r6 = address_range::start_length(0x2000, 0x1000); // 0x2000-0x2FFF + address_range32 r6 = address_range32::start_length(0x2000, 0x1000); // 0x2000-0x2FFF EXPECT_FALSE(r1.overlaps(r6)); EXPECT_FALSE(r6.overlaps(r1)); // Single address overlap at start - address_range r7 = address_range::start_length(0x800, 0x801); // 0x800-0x1000 + address_range32 r7 = address_range32::start_length(0x800, 0x801); // 0x800-0x1000 EXPECT_TRUE(r1.overlaps(r7)); EXPECT_TRUE(r7.overlaps(r1)); // Single address overlap at end - address_range r8 = address_range::start_length(0x1FFF, 0x1000); // 0x1FFF-0x2FFE + address_range32 r8 = address_range32::start_length(0x1FFF, 0x1000); // 0x1FFF-0x2FFE EXPECT_TRUE(r1.overlaps(r8)); EXPECT_TRUE(r8.overlaps(r1)); @@ -107,89 +107,89 @@ namespace utils TEST(AddressRange, Inside) { - address_range r1 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + address_range32 r1 = address_range32::start_length(0x1000, 0x1000); // 0x1000-0x1FFF // Same range - address_range r2 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + address_range32 r2 = address_range32::start_length(0x1000, 0x1000); // 0x1000-0x1FFF EXPECT_TRUE(r1.inside(r2)); EXPECT_TRUE(r2.inside(r1)); // Smaller range inside - address_range r3 = address_range::start_length(0x1200, 0x800); // 0x1200-0x19FF + address_range32 r3 = address_range32::start_length(0x1200, 0x800); // 0x1200-0x19FF EXPECT_TRUE(r3.inside(r1)); EXPECT_FALSE(r1.inside(r3)); // Larger range outside - address_range r4 = address_range::start_length(0x800, 0x2000); // 0x800-0x27FF + address_range32 r4 = address_range32::start_length(0x800, 0x2000); // 0x800-0x27FF EXPECT_TRUE(r1.inside(r4)); EXPECT_FALSE(r4.inside(r1)); // Partially overlapping - address_range r5 = address_range::start_length(0x1800, 0x1000); // 0x1800-0x27FF + address_range32 r5 = address_range32::start_length(0x1800, 0x1000); // 0x1800-0x27FF EXPECT_FALSE(r1.inside(r5)); EXPECT_FALSE(r5.inside(r1)); // No overlap - address_range r6 = address_range::start_length(0x3000, 0x1000); // 0x3000-0x3FFF + address_range32 r6 = address_range32::start_length(0x3000, 0x1000); // 0x3000-0x3FFF EXPECT_FALSE(r1.inside(r6)); EXPECT_FALSE(r6.inside(r1)); } TEST(AddressRange, Touches) { - address_range r1 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + address_range32 r1 = address_range32::start_length(0x1000, 0x1000); // 0x1000-0x1FFF // Same range (overlaps) - address_range r2 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + address_range32 r2 = address_range32::start_length(0x1000, 0x1000); // 0x1000-0x1FFF EXPECT_TRUE(r1.touches(r2)); // Overlapping ranges - address_range r3 = address_range::start_length(0x1800, 0x1000); // 0x1800-0x27FF + address_range32 r3 = address_range32::start_length(0x1800, 0x1000); // 0x1800-0x27FF EXPECT_TRUE(r1.touches(r3)); // Adjacent at end of r1 - address_range r4 = address_range::start_length(0x2000, 0x1000); // 0x2000-0x2FFF + address_range32 r4 = address_range32::start_length(0x2000, 0x1000); // 0x2000-0x2FFF EXPECT_TRUE(r1.touches(r4)); EXPECT_TRUE(r4.touches(r1)); // Adjacent at start of r1 - address_range r5 = address_range::start_length(0x0, 0x1000); // 0x0-0xFFF + address_range32 r5 = address_range32::start_length(0x0, 0x1000); // 0x0-0xFFF EXPECT_TRUE(r1.touches(r5)); EXPECT_TRUE(r5.touches(r1)); // Not touching - address_range r6 = address_range::start_length(0x3000, 0x1000); // 0x3000-0x3FFF + address_range32 r6 = address_range32::start_length(0x3000, 0x1000); // 0x3000-0x3FFF EXPECT_FALSE(r1.touches(r6)); EXPECT_FALSE(r6.touches(r1)); } TEST(AddressRange, Distance) { - address_range r1 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + address_range32 r1 = address_range32::start_length(0x1000, 0x1000); // 0x1000-0x1FFF // Touching ranges - address_range r2 = address_range::start_length(0x2000, 0x1000); // 0x2000-0x2FFF + address_range32 r2 = address_range32::start_length(0x2000, 0x1000); // 0x2000-0x2FFF EXPECT_EQ(r1.distance(r2), 0); EXPECT_EQ(r2.distance(r1), 0); EXPECT_EQ(r1.signed_distance(r2), 0); EXPECT_EQ(r2.signed_distance(r1), 0); // Gap of 0x1000 (r3 after r1) - address_range r3 = address_range::start_length(0x3000, 0x1000); // 0x3000-0x3FFF + address_range32 r3 = address_range32::start_length(0x3000, 0x1000); // 0x3000-0x3FFF EXPECT_EQ(r1.distance(r3), 0x1000); EXPECT_EQ(r3.distance(r1), 0x1000); EXPECT_EQ(r1.signed_distance(r3), 0x1000); EXPECT_EQ(r3.signed_distance(r1), -0x1000); // Gap of 0x1000 (r4 before r1) - address_range r4 = address_range::start_end(0, 0xEFF); // 0x0-0xEFF + address_range32 r4 = address_range32::start_end(0, 0xEFF); // 0x0-0xEFF EXPECT_EQ(r1.distance(r4), 0x100); EXPECT_EQ(r4.distance(r1), 0x100); EXPECT_EQ(r1.signed_distance(r4), -0x100); EXPECT_EQ(r4.signed_distance(r1), 0x100); // Overlapping ranges - address_range r5 = address_range::start_length(0x1800, 0x1000); // 0x1800-0x27FF + address_range32 r5 = address_range32::start_length(0x1800, 0x1000); // 0x1800-0x27FF EXPECT_EQ(r1.distance(r5), 0); EXPECT_EQ(r5.distance(r1), 0); EXPECT_EQ(r1.signed_distance(r5), 0); @@ -198,64 +198,64 @@ namespace utils TEST(AddressRange, MinMax) { - address_range r1 = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF - address_range r2 = address_range::start_length(0x1800, 0x1000); // 0x1800-0x27FF + address_range32 r1 = address_range32::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + address_range32 r2 = address_range32::start_length(0x1800, 0x1000); // 0x1800-0x27FF // Get min-max - address_range min_max = r1.get_min_max(r2); + address_range32 min_max = r1.get_min_max(r2); EXPECT_EQ(min_max.start, 0x1000); EXPECT_EQ(min_max.end, 0x27FF); // Set min-max - address_range r3 = address_range::start_length(0x2000, 0x1000); // 0x2000-0x2FFF + address_range32 r3 = address_range32::start_length(0x2000, 0x1000); // 0x2000-0x2FFF r3.set_min_max(r1); EXPECT_EQ(r3.start, 0x1000); EXPECT_EQ(r3.end, 0x2FFF); // Test with invalid ranges - address_range empty; - address_range min_max2 = r1.get_min_max(empty); + address_range32 empty; + address_range32 min_max2 = r1.get_min_max(empty); EXPECT_EQ(min_max2.start, r1.start); EXPECT_EQ(min_max2.end, r1.end); - address_range min_max3 = empty.get_min_max(r1); + address_range32 min_max3 = empty.get_min_max(r1); EXPECT_EQ(min_max3.start, r1.start); EXPECT_EQ(min_max3.end, r1.end); - address_range min_max4 = empty.get_min_max(empty); + address_range32 min_max4 = empty.get_min_max(empty); EXPECT_EQ(min_max4.start, umax); EXPECT_EQ(min_max4.end, 0); } TEST(AddressRange, Intersect) { - address_range r1 = address_range::start_length(0x1000, 0x2000); // 0x1000-0x2FFF + address_range32 r1 = address_range32::start_length(0x1000, 0x2000); // 0x1000-0x2FFF // Complete overlap - address_range r2 = address_range::start_length(0x0, 0x4000); // 0x0-0x3FFF - address_range i1 = r1.get_intersect(r2); + address_range32 r2 = address_range32::start_length(0x0, 0x4000); // 0x0-0x3FFF + address_range32 i1 = r1.get_intersect(r2); EXPECT_EQ(i1.start, 0x1000); EXPECT_EQ(i1.end, 0x2FFF); // Partial overlap at start - address_range r3 = address_range::start_length(0x0, 0x2000); // 0x0-0x1FFF - address_range i2 = r1.get_intersect(r3); + address_range32 r3 = address_range32::start_length(0x0, 0x2000); // 0x0-0x1FFF + address_range32 i2 = r1.get_intersect(r3); EXPECT_EQ(i2.start, 0x1000); EXPECT_EQ(i2.end, 0x1FFF); // Partial overlap at end - address_range r4 = address_range::start_length(0x2000, 0x2000); // 0x2000-0x3FFF - address_range i3 = r1.get_intersect(r4); + address_range32 r4 = address_range32::start_length(0x2000, 0x2000); // 0x2000-0x3FFF + address_range32 i3 = r1.get_intersect(r4); EXPECT_EQ(i3.start, 0x2000); EXPECT_EQ(i3.end, 0x2FFF); // No overlap - address_range r5 = address_range::start_length(0x4000, 0x1000); // 0x4000-0x4FFF - address_range i4 = r1.get_intersect(r5); + address_range32 r5 = address_range32::start_length(0x4000, 0x1000); // 0x4000-0x4FFF + address_range32 i4 = r1.get_intersect(r5); EXPECT_FALSE(i4.valid()); // Test intersect method - address_range r6 = address_range::start_length(0x1000, 0x2000); // 0x1000-0x2FFF + address_range32 r6 = address_range32::start_length(0x1000, 0x2000); // 0x1000-0x2FFF r6.intersect(r3); EXPECT_EQ(r6.start, 0x1000); EXPECT_EQ(r6.end, 0x1FFF); @@ -264,15 +264,15 @@ namespace utils TEST(AddressRange, Validity) { // Valid range - address_range r1 = address_range::start_length(0x1000, 0x1000); + address_range32 r1 = address_range32::start_length(0x1000, 0x1000); EXPECT_TRUE(r1.valid()); // Invalid range (default constructor) - address_range r2; + address_range32 r2; EXPECT_FALSE(r2.valid()); // Invalid range (start > end) - address_range r3 = address_range::start_end(0x2000, 0x1000); + address_range32 r3 = address_range32::start_end(0x2000, 0x1000); EXPECT_FALSE(r3.valid()); // Invalidate @@ -284,9 +284,9 @@ namespace utils TEST(AddressRange, Comparison) { - address_range r1 = address_range::start_length(0x1000, 0x1000); - address_range r2 = address_range::start_length(0x1000, 0x1000); - address_range r3 = address_range::start_length(0x2000, 0x1000); + address_range32 r1 = address_range32::start_length(0x1000, 0x1000); + address_range32 r2 = address_range32::start_length(0x1000, 0x1000); + address_range32 r3 = address_range32::start_length(0x2000, 0x1000); EXPECT_TRUE(r1 == r2); EXPECT_FALSE(r1 == r3); @@ -294,7 +294,7 @@ namespace utils TEST(AddressRange, StringRepresentation) { - address_range r1 = address_range::start_length(0x1000, 0x1000); + address_range32 r1 = address_range32::start_length(0x1000, 0x1000); std::string str = r1.str(); // The exact format may vary, but it should contain the start and end addresses @@ -310,7 +310,7 @@ namespace utils EXPECT_EQ(vec.size(), 0); // Add a range - vec.merge(address_range::start_length(0x1000, 0x1000)); + vec.merge(address_range32::start_length(0x1000, 0x1000)); EXPECT_FALSE(vec.empty()); EXPECT_EQ(vec.size(), 1); @@ -325,33 +325,33 @@ namespace utils address_range_vector vec; // Add non-touching ranges - vec.merge(address_range::start_length(0x1000, 0x1000)); // 0x1000-0x1FFF - vec.merge(address_range::start_length(0x3000, 0x1000)); // 0x3000-0x3FFF + vec.merge(address_range32::start_length(0x1000, 0x1000)); // 0x1000-0x1FFF + vec.merge(address_range32::start_length(0x3000, 0x1000)); // 0x3000-0x3FFF EXPECT_EQ(vec.valid_count(), 2); // Add a range that touches the first range - vec.merge(address_range::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF + vec.merge(address_range32::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF // Should merge all three ranges EXPECT_EQ(vec.valid_count(), 1); - EXPECT_TRUE(vec.contains(address_range::start_end(0x1000, 0x3FFF))); + EXPECT_TRUE(vec.contains(address_range32::start_end(0x1000, 0x3FFF))); // Add a non-touching range - vec.merge(address_range::start_length(0x5000, 0x1000)); // 0x5000-0x5FFF + vec.merge(address_range32::start_length(0x5000, 0x1000)); // 0x5000-0x5FFF EXPECT_EQ(vec.valid_count(), 2); // Add an overlapping range - vec.merge(address_range::start_length(0x4000, 0x2000)); // 0x4000-0x5FFF + vec.merge(address_range32::start_length(0x4000, 0x2000)); // 0x4000-0x5FFF EXPECT_EQ(vec.valid_count(), 1); - EXPECT_TRUE(vec.contains(address_range::start_end(0x1000, 0x5FFF))); + EXPECT_TRUE(vec.contains(address_range32::start_end(0x1000, 0x5FFF))); } TEST(AddressRangeVector, ExcludeOperations) { address_range_vector vec; - vec.merge(address_range::start_length(0x1000, 0x4000)); // 0x1000-0x4FFF + vec.merge(address_range32::start_length(0x1000, 0x4000)); // 0x1000-0x4FFF // Exclude from the middle - vec.exclude(address_range::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF + vec.exclude(address_range32::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF EXPECT_EQ(vec.valid_count(), 2); auto it = vec.begin(); @@ -362,43 +362,43 @@ namespace utils EXPECT_EQ(it->end, 0x4FFF); // Exclude from the start - vec.exclude(address_range::start_length(0x1000, 0x1000)); // 0x1000-0x1FFF + vec.exclude(address_range32::start_length(0x1000, 0x1000)); // 0x1000-0x1FFF EXPECT_EQ(vec.valid_count(), 1); - EXPECT_TRUE(vec.contains(address_range::start_end(0x3000, 0x4FFF))); + EXPECT_TRUE(vec.contains(address_range32::start_end(0x3000, 0x4FFF))); // Exclude from the end - vec.exclude(address_range::start_length(0x4000, 0x1000)); // 0x4000-0x4FFF + vec.exclude(address_range32::start_length(0x4000, 0x1000)); // 0x4000-0x4FFF EXPECT_EQ(vec.valid_count(), 1); - EXPECT_TRUE(vec.contains(address_range::start_end(0x3000, 0x3FFF))); + EXPECT_TRUE(vec.contains(address_range32::start_end(0x3000, 0x3FFF))); // Exclude entire range - vec.exclude(address_range::start_length(0x3000, 0x1000)); // 0x3000-0x3FFF + vec.exclude(address_range32::start_length(0x3000, 0x1000)); // 0x3000-0x3FFF EXPECT_EQ(vec.valid_count(), 0); // Test excluding with another vector - vec.merge(address_range::start_length(0x1000, 0x4000)); // 0x1000-0x4FFF + vec.merge(address_range32::start_length(0x1000, 0x4000)); // 0x1000-0x4FFF address_range_vector vec2; - vec2.merge(address_range::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF - vec2.merge(address_range::start_length(0x4000, 0x1000)); // 0x4000-0x4FFF + vec2.merge(address_range32::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF + vec2.merge(address_range32::start_length(0x4000, 0x1000)); // 0x4000-0x4FFF vec.exclude(vec2); EXPECT_EQ(vec.valid_count(), 2); - EXPECT_TRUE(vec.contains(address_range::start_end(0x1000, 0x1FFF))); - EXPECT_TRUE(vec.contains(address_range::start_end(0x3000, 0x3FFF))); + EXPECT_TRUE(vec.contains(address_range32::start_end(0x1000, 0x1FFF))); + EXPECT_TRUE(vec.contains(address_range32::start_end(0x3000, 0x3FFF))); } TEST(AddressRangeVector, ConsistencyCheck) { address_range_vector vec; - vec.merge(address_range::start_length(0x1000, 0x1000)); // 0x1000-0x1FFF - vec.merge(address_range::start_length(0x3000, 0x1000)); // 0x3000-0x3FFF + vec.merge(address_range32::start_length(0x1000, 0x1000)); // 0x1000-0x1FFF + vec.merge(address_range32::start_length(0x3000, 0x1000)); // 0x3000-0x3FFF EXPECT_TRUE(vec.check_consistency()); // This would cause inconsistency, but merge should handle it - vec.merge(address_range::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF + vec.merge(address_range32::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF EXPECT_TRUE(vec.check_consistency()); EXPECT_EQ(vec.valid_count(), 1); } @@ -406,44 +406,44 @@ namespace utils TEST(AddressRangeVector, OverlapsAndContains) { address_range_vector vec; - vec.merge(address_range::start_length(0x1000, 0x1000)); // 0x1000-0x1FFF - vec.merge(address_range::start_length(0x3000, 0x1000)); // 0x3000-0x3FFF + vec.merge(address_range32::start_length(0x1000, 0x1000)); // 0x1000-0x1FFF + vec.merge(address_range32::start_length(0x3000, 0x1000)); // 0x3000-0x3FFF // Test overlaps with range - EXPECT_TRUE(vec.overlaps(address_range::start_length(0x1500, 0x1000))); // 0x1500-0x24FF - EXPECT_TRUE(vec.overlaps(address_range::start_length(0x3500, 0x1000))); // 0x3500-0x44FF - EXPECT_FALSE(vec.overlaps(address_range::start_length(0x2000, 0x1000))); // 0x2000-0x2FFF + EXPECT_TRUE(vec.overlaps(address_range32::start_length(0x1500, 0x1000))); // 0x1500-0x24FF + EXPECT_TRUE(vec.overlaps(address_range32::start_length(0x3500, 0x1000))); // 0x3500-0x44FF + EXPECT_FALSE(vec.overlaps(address_range32::start_length(0x2000, 0x1000))); // 0x2000-0x2FFF // Test contains - EXPECT_TRUE(vec.contains(address_range::start_length(0x1000, 0x1000))); // 0x1000-0x1FFF - EXPECT_TRUE(vec.contains(address_range::start_length(0x3000, 0x1000))); // 0x3000-0x3FFF - EXPECT_FALSE(vec.contains(address_range::start_length(0x1500, 0x1000))); // 0x1500-0x24FF + EXPECT_TRUE(vec.contains(address_range32::start_length(0x1000, 0x1000))); // 0x1000-0x1FFF + EXPECT_TRUE(vec.contains(address_range32::start_length(0x3000, 0x1000))); // 0x3000-0x3FFF + EXPECT_FALSE(vec.contains(address_range32::start_length(0x1500, 0x1000))); // 0x1500-0x24FF // Test overlaps with another vector address_range_vector vec2; - vec2.merge(address_range::start_length(0x1500, 0x1000)); // 0x1500-0x24FF + vec2.merge(address_range32::start_length(0x1500, 0x1000)); // 0x1500-0x24FF EXPECT_TRUE(vec.overlaps(vec2)); address_range_vector vec3; - vec3.merge(address_range::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF + vec3.merge(address_range32::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF EXPECT_FALSE(vec.overlaps(vec3)); // Test inside - address_range big_range = address_range::start_length(0x0, 0x5000); // 0x0-0x4FFF + address_range32 big_range = address_range32::start_length(0x0, 0x5000); // 0x0-0x4FFF EXPECT_TRUE(vec.inside(big_range)); - address_range small_range = address_range::start_length(0x1000, 0x1000); // 0x1000-0x1FFF + address_range32 small_range = address_range32::start_length(0x1000, 0x1000); // 0x1000-0x1FFF EXPECT_FALSE(vec.inside(small_range)); } - // Test the std::hash implementation for address_range + // Test the std::hash implementation for address_range32 TEST(AddressRange, Hash) { - address_range r1 = address_range::start_length(0x1000, 0x1000); - address_range r2 = address_range::start_length(0x1000, 0x1000); - address_range r3 = address_range::start_length(0x2000, 0x1000); + address_range32 r1 = address_range32::start_length(0x1000, 0x1000); + address_range32 r2 = address_range32::start_length(0x1000, 0x1000); + address_range32 r3 = address_range32::start_length(0x2000, 0x1000); - std::hash hasher; + std::hash hasher; EXPECT_EQ(hasher(r1), hasher(r2)); EXPECT_NE(hasher(r1), hasher(r3)); } From 2ea7ff6b1480483c9e8161715de6f0c5188e91c5 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 26 May 2025 03:11:08 +0300 Subject: [PATCH 009/384] rsx/util: Split address_range into a sized address_range template --- Utilities/address_range.h | 154 ++++++++++++--------- rpcs3/Emu/Memory/vm.h | 4 +- rpcs3/Emu/RSX/Common/texture_cache.h | 8 +- rpcs3/Emu/RSX/Common/texture_cache_utils.h | 8 +- rpcs3/Emu/RSX/rsx_utils.h | 2 +- rpcs3/tests/test_address_range.cpp | 18 +-- 6 files changed, 108 insertions(+), 86 deletions(-) diff --git a/Utilities/address_range.h b/Utilities/address_range.h index 1ac39c26a1..ba07651b4e 100644 --- a/Utilities/address_range.h +++ b/Utilities/address_range.h @@ -8,65 +8,73 @@ namespace utils { + template class address_range_vector; /** * Helpers */ - static inline u32 page_start(u32 addr) + template + T page_start(T addr) { - return addr & ~(get_page_size() - 1); + return addr & ~static_cast(get_page_size() - 1); } - static inline u32 next_page(u32 addr) + template + static inline T next_page(T addr) { - return page_start(addr) + get_page_size(); + return page_start(addr) + static_cast(get_page_size()); } - static inline u32 page_end(u32 addr) + template + static inline T page_end(T addr) { return next_page(addr) - 1; } - static inline u32 is_page_aligned(u32 val) + template + static inline T is_page_aligned(T val) { - return (val & (get_page_size() - 1)) == 0; + return (val & static_cast(get_page_size() - 1)) == 0; } /** * Address Range utility class */ - class address_range32 + template + class address_range { public: - u32 start = umax; // First address in range - u32 end = 0; // Last address + T start = umax; // First address in range + T end = 0; // Last address + + using signed_type_t = std::make_signed::type; private: // Helper constexprs - static constexpr inline bool range_overlaps(u32 start1, u32 end1, u32 start2, u32 end2) + static constexpr inline bool range_overlaps(T start1, T end1, T start2, T end2) { return (start1 <= end2 && start2 <= end1); } - static constexpr inline bool address_overlaps(u32 address, u32 start, u32 end) + static constexpr inline bool address_overlaps(T address, T start, T end) { return (start <= address && address <= end); } - static constexpr inline bool range_inside_range(u32 start1, u32 end1, u32 start2, u32 end2) + static constexpr inline bool range_inside_range(T start1, T end1, T start2, T end2) { return (start1 >= start2 && end1 <= end2); } - constexpr address_range32(u32 _start, u32 _end) : start(_start), end(_end) {} + constexpr address_range(T _start, T _end) : start(_start), end(_end) {} public: // Constructors - constexpr address_range32() = default; + constexpr address_range() = default; - static constexpr address_range32 start_length(u32 _start, u32 _length) + static constexpr address_range start_length(T _start, T _length) { if (!_length) { @@ -76,57 +84,57 @@ namespace utils return {_start, _start + (_length - 1)}; } - static constexpr address_range32 start_end(u32 _start, u32 _end) + static constexpr address_range start_end(T _start, T _end) { return {_start, _end}; } // Length - u32 length() const + T length() const { AUDIT(valid()); return end - start + 1; } - void set_length(const u32 new_length) + void set_length(const T new_length) { end = start + new_length - 1; ensure(valid()); } - u32 next_address() const + T next_address() const { return end + 1; } - u32 prev_address() const + T prev_address() const { return start - 1; } // Overlapping checks - bool overlaps(const address_range32 &other) const + bool overlaps(const address_range& other) const { AUDIT(valid() && other.valid()); return range_overlaps(start, end, other.start, other.end); } - bool overlaps(const u32 addr) const + bool overlaps(const T addr) const { AUDIT(valid()); return address_overlaps(addr, start, end); } - bool inside(const address_range32 &other) const + bool inside(const address_range& other) const { AUDIT(valid() && other.valid()); return range_inside_range(start, end, other.start, other.end); } - inline bool inside(const address_range_vector &vec) const; - inline bool overlaps(const address_range_vector &vec) const; + inline bool inside(const address_range_vector& vec) const; + inline bool overlaps(const address_range_vector& vec) const; - bool touches(const address_range32 &other) const + bool touches(const address_range& other) const { AUDIT(valid() && other.valid()); // returns true if there is overlap, or if sections are side-by-side @@ -134,7 +142,7 @@ namespace utils } // Utilities - s32 signed_distance(const address_range32 &other) const + signed_type_t signed_distance(const address_range& other) const { if (touches(other)) { @@ -144,15 +152,15 @@ namespace utils // other after this if (other.start > end) { - return static_cast(other.start - end - 1); + return static_cast(other.start - end - 1); } // this after other AUDIT(start > other.end); - return -static_cast(start - other.end - 1); + return -static_cast(start - other.end - 1); } - u32 distance(const address_range32 &other) const + T distance(const address_range& other) const { if (touches(other)) { @@ -170,7 +178,7 @@ namespace utils return (start - other.end - 1); } - address_range32 get_min_max(const address_range32 &other) const + address_range get_min_max(const address_range& other) const { return { std::min(valid() ? start : umax, other.valid() ? other.start : umax), @@ -178,7 +186,7 @@ namespace utils }; } - void set_min_max(const address_range32 &other) + void set_min_max(const address_range& other) { *this = get_min_max(other); } @@ -188,7 +196,7 @@ namespace utils return (valid() && is_page_aligned(start) && is_page_aligned(length())); } - address_range32 to_page_range() const + address_range to_page_range() const { AUDIT(valid()); return { page_start(start), page_end(end) }; @@ -202,7 +210,7 @@ namespace utils AUDIT(is_page_range()); } - address_range32 get_intersect(const address_range32 &clamp) const + address_range get_intersect(const address_range& clamp) const { if (!valid() || !clamp.valid()) { @@ -212,7 +220,7 @@ namespace utils return { std::max(start, clamp.start), std::min(end, clamp.end) }; } - void intersect(const address_range32 &clamp) + void intersect(const address_range& clamp) { if (!clamp.valid()) { @@ -238,7 +246,7 @@ namespace utils } // Comparison Operators - bool operator ==(const address_range32& other) const + bool operator ==(const address_range& other) const { return (start == other.start && end == other.end); } @@ -252,21 +260,27 @@ namespace utils } }; - static inline address_range32 page_for(u32 addr) + using address_range16 = address_range; + using address_range32 = address_range; + using address_range64 = address_range; + + template + static inline address_range page_for(T addr) { - return address_range32::start_end(page_start(addr), page_end(addr)); + return address_range::start_end(page_start(addr), page_end(addr)); } /** * Address Range Vector utility class * - * Collection of address_range32 objects. Allows for merging and removing ranges from the set. + * Collection of address_range objects. Allows for merging and removing ranges from the set. */ + template class address_range_vector { public: - using vector_type = std::vector; + using vector_type = std::vector>; using iterator = vector_type::iterator; using const_iterator = vector_type::const_iterator; using size_type = vector_type::size_type; @@ -280,8 +294,8 @@ namespace utils inline void clear() { data.clear(); } inline size_type size() const { return data.size(); } inline bool empty() const { return data.empty(); } - inline address_range32& operator[](size_type n) { return data[n]; } - inline const address_range32& operator[](size_type n) const { return data[n]; } + inline address_range& operator[](size_type n) { return data[n]; } + inline const address_range& operator[](size_type n) const { return data[n]; } inline iterator begin() { return data.begin(); } inline const_iterator begin() const { return data.begin(); } inline iterator end() { return data.end(); } @@ -289,7 +303,7 @@ namespace utils // Search for ranges that touch new_range. If found, merge instead of adding new_range. // When adding a new range, re-use invalid ranges whenever possible - void merge(const address_range32 &new_range) + void merge(const address_range& new_range) { // Note the case where we have // AAAA BBBB @@ -301,8 +315,8 @@ namespace utils return; } - address_range32 *found = nullptr; - address_range32 *invalid = nullptr; + address_range *found = nullptr; + address_range *invalid = nullptr; for (auto &existing : data) { @@ -347,22 +361,22 @@ namespace utils AUDIT(check_consistency()); } - void merge(const address_range_vector &other) + void merge(const address_range_vector& other) { - for (const address_range32 &new_range : other) + for (const address_range& new_range : other) { merge(new_range); } } // Exclude a given range from data - void exclude(const address_range32 &exclusion) + void exclude(const address_range& exclusion) { // Note the case where we have // AAAAAAA // EEE // where data={A} and exclusion=E. - // In this case, we need to reduce A to the head (before E starts), and then create a new address_range32 B for the tail (after E ends), i.e. + // In this case, we need to reduce A to the head (before E starts), and then create a new address_range B for the tail (after E ends), i.e. // AA BB // EEE @@ -371,13 +385,13 @@ namespace utils return; } - address_range32 *invalid = nullptr; // try to re-use an invalid range instead of calling push_back + address_range *invalid = nullptr; // try to re-use an invalid range instead of calling push_back // We use index access because we might have to push_back within the loop, which could invalidate the iterators size_type _size = data.size(); for (size_type n = 0; n < _size; ++n) { - address_range32 &existing = data[n]; + address_range& existing = data[n]; if (!existing.valid()) { @@ -430,7 +444,7 @@ namespace utils else { // IMPORTANT: adding to data invalidates "existing". This must be done last! - data.push_back(address_range32::start_end(exclusion.next_address(), tail_end)); + data.push_back(address_range::start_end(exclusion.next_address(), tail_end)); } } } @@ -438,9 +452,9 @@ namespace utils AUDIT(!overlaps(exclusion)); } - void exclude(const address_range_vector &other) + void exclude(const address_range_vector& other) { - for (const address_range32 &exclusion : other) + for (const address_range& exclusion : other) { exclude(exclusion); } @@ -478,25 +492,25 @@ namespace utils } // Test for overlap with a given range - bool overlaps(const address_range32 &range) const + bool overlaps(const address_range& range) const { - return std::any_of(data.cbegin(), data.cend(), [&range](const address_range32& cur) + return std::any_of(data.cbegin(), data.cend(), [&range](const address_range& cur) { return cur.valid() && cur.overlaps(range); }); } - // Test for overlap with a given address_range32 vector - bool overlaps(const address_range_vector &other) const + // Test for overlap with a given address_range vector + bool overlaps(const address_range_vector& other) const { - for (const address_range32 &rng1 : data) + for (const address_range& rng1 : data) { if (!rng1.valid()) { continue; } - for (const address_range32 &rng2 : other.data) + for (const address_range& rng2 : other.data) { if (!rng2.valid()) { @@ -513,18 +527,18 @@ namespace utils } // Test if a given range is fully contained inside this vector - bool contains(const address_range32 &range) const + bool contains(const address_range& range) const { - return std::any_of(this->begin(), this->end(), [&range](const address_range32& cur) + return std::any_of(this->begin(), this->end(), [&range](const address_range& cur) { return cur.valid() && cur.inside(range); }); } // Test if all ranges in this vector are full contained inside a specific range - bool inside(const address_range32 &range) const + bool inside(const address_range& range) const { - return std::all_of(this->begin(), this->end(), [&range](const address_range32& cur) + return std::all_of(this->begin(), this->end(), [&range](const address_range& cur) { return !cur.valid() || cur.inside(range); }); @@ -547,16 +561,22 @@ namespace utils // These declarations must be done after address_range_vector has been defined - bool address_range32::inside(const address_range_vector &vec) const + template + bool address_range::inside(const address_range_vector& vec) const { return vec.contains(*this); } - bool address_range32::overlaps(const address_range_vector &vec) const + template + bool address_range::overlaps(const address_range_vector& vec) const { return vec.overlaps(*this); } + using address_range_vector16 = address_range_vector; + using address_range_vector32 = address_range_vector; + using address_range_vector64 = address_range_vector; + } // namespace utils diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 98800055a5..3c39d0aa4a 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -22,7 +22,9 @@ void ppubreak(ppu_thread& ppu); namespace utils { class shm; - class address_range32; + + template class address_range; + using address_range32 = address_range; } namespace vm diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 2eeab39ecb..91e41e6179 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -685,7 +685,7 @@ namespace rsx // Merges the protected ranges of the sections in "sections" into "result" - void merge_protected_ranges(address_range_vector &result, const std::vector §ions) + void merge_protected_ranges(address_range_vector32 &result, const std::vector §ions) { result.reserve(result.size() + sections.size()); @@ -704,7 +704,7 @@ namespace rsx // Otherwise the page protections will end up incorrect and things will break! void unprotect_set(thrashed_set& data) { - auto protect_ranges = [](address_range_vector& _set, utils::protection _prot) + auto protect_ranges = [](address_range_vector32& _set, utils::protection _prot) { //u32 count = 0; for (auto &range : _set) @@ -734,8 +734,8 @@ namespace rsx AUDIT(data.is_flushed()); // Merge ranges to unprotect - address_range_vector ranges_to_unprotect; - address_range_vector ranges_to_protect_ro; + address_range_vector32 ranges_to_unprotect; + address_range_vector32 ranges_to_protect_ro; ranges_to_unprotect.reserve(data.sections_to_unprotect.size() + data.sections_to_flush.size() + data.sections_to_exclude.size()); merge_protected_ranges(ranges_to_unprotect, data.sections_to_unprotect); diff --git a/rpcs3/Emu/RSX/Common/texture_cache_utils.h b/rpcs3/Emu/RSX/Common/texture_cache_utils.h index 97b02e8f9d..8c5defdd0b 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache_utils.h +++ b/rpcs3/Emu/RSX/Common/texture_cache_utils.h @@ -928,7 +928,7 @@ namespace rsx return get_bounds(bounds).overlaps(other); } - inline bool overlaps(const address_range_vector& other, section_bounds bounds) const + inline bool overlaps(const address_range_vector32& other, section_bounds bounds) const { return get_bounds(bounds).overlaps(other); } @@ -943,7 +943,7 @@ namespace rsx return get_bounds(bounds).inside(other); } - inline bool inside(const address_range_vector& other, section_bounds bounds) const + inline bool inside(const address_range_vector32& other, section_bounds bounds) const { return get_bounds(bounds).inside(other); } @@ -1088,7 +1088,7 @@ namespace rsx rsx::texture_upload_context context = rsx::texture_upload_context::shader_read; rsx::texture_dimension_extended image_type = rsx::texture_dimension_extended::texture_dimension_2d; - address_range_vector flush_exclusions; // Address ranges that will be skipped during flush + address_range_vector32 flush_exclusions; // Address ranges that will be skipped during flush predictor_type *m_predictor = nullptr; usz m_predictor_key_hash = 0; @@ -1553,7 +1553,7 @@ namespace rsx // Otherwise, we need to filter the memcpy with our flush exclusions // Should be relatively rare - address_range_vector vec; + address_range_vector32 vec; vec.merge(copy_range); vec.exclude(flush_exclusions); diff --git a/rpcs3/Emu/RSX/rsx_utils.h b/rpcs3/Emu/RSX/rsx_utils.h index 5b7c09cf5d..7a0aa3c14f 100644 --- a/rpcs3/Emu/RSX/rsx_utils.h +++ b/rpcs3/Emu/RSX/rsx_utils.h @@ -16,7 +16,7 @@ namespace rsx { // Import address_range32 utilities using utils::address_range32; - using utils::address_range_vector; + using utils::address_range_vector32; using utils::page_for; using utils::page_start; using utils::page_end; diff --git a/rpcs3/tests/test_address_range.cpp b/rpcs3/tests/test_address_range.cpp index c75483bcc5..44ad134646 100644 --- a/rpcs3/tests/test_address_range.cpp +++ b/rpcs3/tests/test_address_range.cpp @@ -302,10 +302,10 @@ namespace utils EXPECT_NE(str.find("1fff"), std::string::npos); } - // Tests for address_range_vector + // Tests for address_range_vector32 TEST(AddressRangeVector, BasicOperations) { - address_range_vector vec; + address_range_vector32 vec; EXPECT_TRUE(vec.empty()); EXPECT_EQ(vec.size(), 0); @@ -322,7 +322,7 @@ namespace utils TEST(AddressRangeVector, MergeOperations) { - address_range_vector vec; + address_range_vector32 vec; // Add non-touching ranges vec.merge(address_range32::start_length(0x1000, 0x1000)); // 0x1000-0x1FFF @@ -347,7 +347,7 @@ namespace utils TEST(AddressRangeVector, ExcludeOperations) { - address_range_vector vec; + address_range_vector32 vec; vec.merge(address_range32::start_length(0x1000, 0x4000)); // 0x1000-0x4FFF // Exclude from the middle @@ -378,7 +378,7 @@ namespace utils // Test excluding with another vector vec.merge(address_range32::start_length(0x1000, 0x4000)); // 0x1000-0x4FFF - address_range_vector vec2; + address_range_vector32 vec2; vec2.merge(address_range32::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF vec2.merge(address_range32::start_length(0x4000, 0x1000)); // 0x4000-0x4FFF @@ -391,7 +391,7 @@ namespace utils TEST(AddressRangeVector, ConsistencyCheck) { - address_range_vector vec; + address_range_vector32 vec; vec.merge(address_range32::start_length(0x1000, 0x1000)); // 0x1000-0x1FFF vec.merge(address_range32::start_length(0x3000, 0x1000)); // 0x3000-0x3FFF @@ -405,7 +405,7 @@ namespace utils TEST(AddressRangeVector, OverlapsAndContains) { - address_range_vector vec; + address_range_vector32 vec; vec.merge(address_range32::start_length(0x1000, 0x1000)); // 0x1000-0x1FFF vec.merge(address_range32::start_length(0x3000, 0x1000)); // 0x3000-0x3FFF @@ -420,11 +420,11 @@ namespace utils EXPECT_FALSE(vec.contains(address_range32::start_length(0x1500, 0x1000))); // 0x1500-0x24FF // Test overlaps with another vector - address_range_vector vec2; + address_range_vector32 vec2; vec2.merge(address_range32::start_length(0x1500, 0x1000)); // 0x1500-0x24FF EXPECT_TRUE(vec.overlaps(vec2)); - address_range_vector vec3; + address_range_vector32 vec3; vec3.merge(address_range32::start_length(0x2000, 0x1000)); // 0x2000-0x2FFF EXPECT_FALSE(vec.overlaps(vec3)); From 45718d7679b028d4a2924b056f617f0785519018 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 26 May 2025 03:42:56 +0300 Subject: [PATCH 010/384] rsx: Use address_range64 to simplify MM intersection tests --- rpcs3/Emu/RSX/Host/MM.cpp | 19 ++++++------------- rpcs3/Emu/RSX/Host/MM.h | 17 +++++------------ rpcs3/Emu/RSX/NV47/HW/nv0039.cpp | 12 ++++++------ 3 files changed, 17 insertions(+), 31 deletions(-) diff --git a/rpcs3/Emu/RSX/Host/MM.cpp b/rpcs3/Emu/RSX/Host/MM.cpp index affb932fd1..e1313cc13a 100644 --- a/rpcs3/Emu/RSX/Host/MM.cpp +++ b/rpcs3/Emu/RSX/Host/MM.cpp @@ -18,7 +18,7 @@ namespace rsx { for (const auto& block : g_deferred_mprotect_queue) { - utils::memory_protect(reinterpret_cast(block.start), block.length, block.prot); + utils::memory_protect(reinterpret_cast(block.range.start), block.range.length(), block.prot); } g_deferred_mprotect_queue.clear(); @@ -28,7 +28,7 @@ namespace rsx { // We could stack and merge requests here, but that is more trouble than it is truly worth. // A fresh call to memory_protect only takes a few nanoseconds of setup overhead, it is not worth the risk of hanging because of conflicts. - g_deferred_mprotect_queue.push_back({ start, length, prot }); + g_deferred_mprotect_queue.push_back({ utils::address_range64::start_length(start, length), prot }); } void mm_protect(void* ptr, u64 length, utils::protection prot) @@ -41,7 +41,7 @@ namespace rsx // Naive merge. Eventually it makes more sense to do conflict resolution, but it's not as important. const auto start = reinterpret_cast(ptr); - const auto end = start + length; + const auto range = utils::address_range64::start_length(start, length); std::lock_guard lock(g_mprotect_queue_lock); @@ -50,7 +50,7 @@ namespace rsx // Basically an unlock op. Flush if any overlap is detected for (const auto& block : g_deferred_mprotect_queue) { - if (block.overlaps(start, end)) + if (block.overlaps(range)) { mm_flush_mprotect_queue_internal(); break; @@ -90,7 +90,7 @@ namespace rsx } } - void mm_flush(const rsx::simple_array& ranges) + void mm_flush(const rsx::simple_array& ranges) { std::lock_guard lock(g_mprotect_queue_lock); if (g_deferred_mprotect_queue.empty()) @@ -98,16 +98,9 @@ namespace rsx return; } - const auto ranges64 = ranges.map([](const auto& r) - { - const u64 start = reinterpret_cast(vm::base(r.start)); - const u64 end = start + r.length(); - return std::make_pair(start, end); - }); - for (const auto& block : g_deferred_mprotect_queue) { - if (ranges64.any(FN(block.overlaps(x.first, x.second)))) + if (ranges.any(FN(block.overlaps(x)))) { mm_flush_mprotect_queue_internal(); return; diff --git a/rpcs3/Emu/RSX/Host/MM.h b/rpcs3/Emu/RSX/Host/MM.h index f71fbb69aa..43053cdd17 100644 --- a/rpcs3/Emu/RSX/Host/MM.h +++ b/rpcs3/Emu/RSX/Host/MM.h @@ -10,24 +10,17 @@ namespace rsx { struct MM_block { - u64 start; - u64 length; + utils::address_range64 range; utils::protection prot; - inline bool overlaps(u64 start, u64 end) const + inline bool overlaps(const utils::address_range64& test) const { - // [Start, End] is not a proper closed range, there is an off-by-one by design. - // FIXME: Use address_range64 - const u64 this_end = this->start + this->length; - return (this->start < end && start < this_end); + return range.overlaps(test); } inline bool overlaps(u64 addr) const { - // [Start, End] is not a proper closed range, there is an off-by-one by design. - // FIXME: Use address_range64 - const u64 this_end = this->start + this->length; - return (addr >= start && addr < this_end); + return range.overlaps(addr); } }; @@ -39,6 +32,6 @@ namespace rsx void mm_protect(void* start, u64 length, utils::protection prot); void mm_flush_lazy(); void mm_flush(u32 vm_address); - void mm_flush(const rsx::simple_array& ranges); + void mm_flush(const rsx::simple_array& ranges); void mm_flush(); } diff --git a/rpcs3/Emu/RSX/NV47/HW/nv0039.cpp b/rpcs3/Emu/RSX/NV47/HW/nv0039.cpp index 10ea3ff5db..a41fae11dc 100644 --- a/rpcs3/Emu/RSX/NV47/HW/nv0039.cpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv0039.cpp @@ -58,16 +58,16 @@ namespace rsx auto res = ::rsx::reservation_lock(write_address, write_length, read_address, read_length); - rsx::simple_array flush_mm_ranges = + u8* dst = vm::_ptr(write_address); + const u8* src = vm::_ptr(read_address); + + rsx::simple_array flush_mm_ranges = { - utils::address_range32::start_length(write_address, write_length).to_page_range(), - utils::address_range32::start_length(read_address, read_length).to_page_range() + utils::address_range64::start_length(reinterpret_cast(dst), write_length), + utils::address_range64::start_length(reinterpret_cast(src), read_length) }; rsx::mm_flush(flush_mm_ranges); - u8 *dst = vm::_ptr(write_address); - const u8 *src = vm::_ptr(read_address); - const bool is_overlapping = dst_dma == src_dma && [&]() -> bool { const u32 src_max = src_offset + read_length; From 2d9a24d1d6ef0682cfed9ee04d411a8caac9f15a Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 27 May 2025 00:14:39 +0300 Subject: [PATCH 011/384] rsx/util/test: Cover edge cases in address_range test suite --- Utilities/address_range.h | 3 +- rpcs3/CMakeLists.txt | 1 + rpcs3/tests/test_address_range.cpp | 47 ++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/Utilities/address_range.h b/Utilities/address_range.h index ba07651b4e..8da0279ef1 100644 --- a/Utilities/address_range.h +++ b/Utilities/address_range.h @@ -81,7 +81,8 @@ namespace utils return {}; } - return {_start, _start + (_length - 1)}; + const T _end = static_cast(_start + _length - 1); + return {_start, _end}; } static constexpr address_range start_end(T _start, T _end) diff --git a/rpcs3/CMakeLists.txt b/rpcs3/CMakeLists.txt index 727bee8cae..395ea52e87 100644 --- a/rpcs3/CMakeLists.txt +++ b/rpcs3/CMakeLists.txt @@ -200,6 +200,7 @@ if(BUILD_RPCS3_TESTS) tests/test.cpp tests/test_fmt.cpp tests/test_simple_array.cpp + tests/test_address_range.cpp ) target_link_libraries(rpcs3_test diff --git a/rpcs3/tests/test_address_range.cpp b/rpcs3/tests/test_address_range.cpp index 44ad134646..5a7e8b2faf 100644 --- a/rpcs3/tests/test_address_range.cpp +++ b/rpcs3/tests/test_address_range.cpp @@ -447,4 +447,51 @@ namespace utils EXPECT_EQ(hasher(r1), hasher(r2)); EXPECT_NE(hasher(r1), hasher(r3)); } + + // Test invalidation rules around umax + TEST(AddressRange, Invalidate32) + { + address_range32 r1 = address_range32::start_length(0x0, 0x1000); + r1.invalidate(); + + EXPECT_FALSE(r1.valid()); + EXPECT_EQ(r1.start, 0xffff'ffffu); + EXPECT_EQ(r1.end, 0u); + } + + TEST(AddressRange, Invalidate64) + { + address_range64 r1 = address_range64::start_length(0x0, 0x1000); + r1.invalidate(); + + EXPECT_FALSE(r1.valid()); + EXPECT_EQ(r1.start, 0xffff'ffff'ffff'ffffull); + EXPECT_EQ(r1.end, 0ull); + } + + TEST(AddressRange, Invalidate16) + { + const u16 start = 0x1000, length = 0x1000; + address_range16 r1 = address_range16::start_length(start, length); + r1.invalidate(); + + EXPECT_FALSE(r1.valid()); + EXPECT_EQ(r1.start, 0xffff); + EXPECT_EQ(r1.end, 0); + } + + TEST(AddressRange, InvalidConstruction) + { + address_range32 r1 = address_range32::start_length(umax, u32{umax} / 2); + EXPECT_FALSE(r1.valid()); + } + + TEST(AddressRange, LargeValues64) + { + const u32 start = umax, length = u32{umax} / 2; + address_range64 r1 = address_range64::start_length(start, length); + + EXPECT_EQ(r1.start, 0xffff'ffffull); + EXPECT_EQ(r1.end, 0x1'7fff'fffd); + } } From a9df046f21d11b4e7758401bed47d2cad402c294 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Thu, 29 May 2025 00:26:03 +0200 Subject: [PATCH 012/384] Update curl to 8.14.0 --- 3rdparty/curl/curl | 2 +- 3rdparty/curl/libcurl.vcxproj | 61 +++++---- 3rdparty/curl/libcurl.vcxproj.filters | 183 +++++++++++++++----------- 3 files changed, 141 insertions(+), 105 deletions(-) diff --git a/3rdparty/curl/curl b/3rdparty/curl/curl index 1c31498817..4dacb79fcd 160000 --- a/3rdparty/curl/curl +++ b/3rdparty/curl/curl @@ -1 +1 @@ -Subproject commit 1c3149881769e7bd79b072e48374e4c2b3678b2f +Subproject commit 4dacb79fcdd9364c1083e06f6a011d797a344f47 diff --git a/3rdparty/curl/libcurl.vcxproj b/3rdparty/curl/libcurl.vcxproj index 6c8cd23ffb..c4a96abdc4 100644 --- a/3rdparty/curl/libcurl.vcxproj +++ b/3rdparty/curl/libcurl.vcxproj @@ -62,8 +62,8 @@ - - + + @@ -77,6 +77,17 @@ + + + + + + + + + + + @@ -85,7 +96,6 @@ - @@ -99,12 +109,12 @@ - + @@ -115,14 +125,11 @@ - - - @@ -138,7 +145,6 @@ - @@ -152,7 +158,6 @@ - @@ -182,18 +187,18 @@ - - - + + + + - @@ -203,7 +208,6 @@ - @@ -266,9 +270,19 @@ - + + + + + + + + + + + + - @@ -283,7 +297,6 @@ - @@ -300,12 +313,12 @@ - + @@ -316,7 +329,6 @@ - @@ -334,7 +346,6 @@ - @@ -344,7 +355,6 @@ - @@ -374,19 +384,19 @@ - - - + + + + - @@ -399,7 +409,6 @@ - diff --git a/3rdparty/curl/libcurl.vcxproj.filters b/3rdparty/curl/libcurl.vcxproj.filters index 15fe93ce39..32eb05f40e 100644 --- a/3rdparty/curl/libcurl.vcxproj.filters +++ b/3rdparty/curl/libcurl.vcxproj.filters @@ -24,12 +24,6 @@ Source Files - - Source Files - - - Source Files - Source Files @@ -69,9 +63,6 @@ Source Files - - Source Files - Source Files @@ -132,9 +123,6 @@ Source Files - - Source Files - Source Files @@ -144,9 +132,6 @@ Source Files - - Source Files - Source Files @@ -177,9 +162,6 @@ Source Files - - Source Files - Source Files @@ -210,9 +192,6 @@ Source Files - - Source Files - Source Files @@ -300,9 +279,6 @@ Source Files - - Source Files - Source Files @@ -315,9 +291,6 @@ Source Files - - Source Files - Source Files @@ -396,15 +369,9 @@ Source Files - - Source Files - Source Files - - Source Files - Source Files @@ -438,9 +405,6 @@ Source Files - - Source Files - Source Files @@ -504,9 +468,6 @@ Source Files - - Source Files - Source Files @@ -525,9 +486,6 @@ Source Files - - Source Files - Source Files @@ -537,6 +495,60 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + @@ -608,15 +620,9 @@ Header Files - - Header Files - Header Files - - Header Files - Header Files @@ -656,9 +662,6 @@ Header Files - - Header Files - Header Files @@ -758,9 +761,6 @@ Header Files - - Header Files - Header Files @@ -779,9 +779,6 @@ Header Files - - Header Files - Header Files @@ -875,9 +872,6 @@ Header Files - - Header Files - Header Files @@ -890,9 +884,6 @@ Header Files - - Header Files - Header Files @@ -935,18 +926,12 @@ Header Files - - Header Files - Header Files Header Files - - Header Files - Header Files @@ -977,9 +962,6 @@ Header Files - - Header Files - Header Files @@ -1052,9 +1034,6 @@ Header Files - - Header Files - Header Files @@ -1076,15 +1055,63 @@ Header Files - - Header Files - Header Files Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + From 3d0a68c9e8b464776ba8b425cbe53a270bd75bcc Mon Sep 17 00:00:00 2001 From: oltolm Date: Tue, 8 Apr 2025 11:40:01 +0200 Subject: [PATCH 013/384] stdafx.h: fix clang warnings --- rpcs3/stdafx.h | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/rpcs3/stdafx.h b/rpcs3/stdafx.h index 362cafd75d..b1e768dc52 100644 --- a/rpcs3/stdafx.h +++ b/rpcs3/stdafx.h @@ -1,24 +1,24 @@ #pragma once // No BOM and only basic ASCII in this header, or a neko will die -#include "util/types.hpp" -#include "util/atomic.hpp" -#include "util/endian.hpp" -#include "Utilities/Config.h" -#include "Utilities/StrFmt.h" -#include "Utilities/File.h" -#include "util/logs.hpp" -#include "util/shared_ptr.hpp" -#include "util/typeindices.hpp" -#include "util/fixed_typemap.hpp" -#include "util/auto_typemap.hpp" +#include "util/types.hpp" // IWYU pragma: export +#include "util/atomic.hpp" // IWYU pragma: export +#include "util/endian.hpp" // IWYU pragma: export +#include "Utilities/Config.h" // IWYU pragma: export +#include "Utilities/StrFmt.h" // IWYU pragma: export +#include "Utilities/File.h" // IWYU pragma: export +#include "util/logs.hpp" // IWYU pragma: export +#include "util/shared_ptr.hpp" // IWYU pragma: export +#include "util/typeindices.hpp" // IWYU pragma: export +#include "util/fixed_typemap.hpp" // IWYU pragma: export +#include "util/auto_typemap.hpp" // IWYU pragma: export -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export From 38289f3bc1d711aa8b9d801668f8c9b8059d35df Mon Sep 17 00:00:00 2001 From: oltolm Date: Wed, 30 Apr 2025 17:14:05 +0200 Subject: [PATCH 014/384] fix Windows build with GCC/Clang --- 3rdparty/curl/CMakeLists.txt | 4 ++-- 3rdparty/qt6.cmake | 3 +-- CMakeLists.txt | 3 +++ buildfiles/cmake/FindFFMPEG.cmake | 26 ++++++++------------------ buildfiles/cmake/FindWayland.cmake | 10 +++++----- rpcs3/CMakeLists.txt | 12 ++++++------ rpcs3/Input/hid_pad_handler.h | 2 +- 7 files changed, 26 insertions(+), 34 deletions(-) diff --git a/3rdparty/curl/CMakeLists.txt b/3rdparty/curl/CMakeLists.txt index d8fc5790fc..b20763af65 100644 --- a/3rdparty/curl/CMakeLists.txt +++ b/3rdparty/curl/CMakeLists.txt @@ -26,8 +26,8 @@ else() endif() set(CURL_USE_LIBSSH2 OFF CACHE BOOL "Use libSSH2") set(CURL_USE_LIBPSL OFF CACHE BOOL "Use libPSL") - - set(CURL_DISABLE_TESTS ON) + option(BUILD_TESTING "Build tests" OFF) + option(BUILD_EXAMPLES "Build libcurl examples" OFF) add_subdirectory(curl EXCLUDE_FROM_ALL) diff --git a/3rdparty/qt6.cmake b/3rdparty/qt6.cmake index 259727879e..ef89bdab05 100644 --- a/3rdparty/qt6.cmake +++ b/3rdparty/qt6.cmake @@ -32,8 +32,7 @@ Find the correct ppa at https://launchpad.net/~beineri and follow the instructio else() message("CMake was unable to find Qt6!") if(WIN32) - message(FATAL_ERROR "Make sure the QTDIR env variable has been set properly. (for example C:\\Qt\\${QT_MIN_VER}\\msvc2019_64\\) -You can also try setting the Qt6_DIR preprocessor definiton.") + message(FATAL_ERROR "Make sure the Qt6_ROOT environment variable has been set properly. (for example C:\\Qt\\${QT_MIN_VER}\\msvc2022_64\\)") elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") message(FATAL_ERROR "Make sure to install your distro's qt6 package!") else() diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d2edd8365..a0867ab67f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,6 +147,9 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${PROJECT_BINARY_DIR}/bin") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${PROJECT_BINARY_DIR}/bin") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${PROJECT_BINARY_DIR}/bin") +if(BUILD_RPCS3_TESTS) + enable_testing() +endif() add_subdirectory(rpcs3) set_directory_properties(PROPERTIES VS_STARTUP_PROJECT rpcs3) diff --git a/buildfiles/cmake/FindFFMPEG.cmake b/buildfiles/cmake/FindFFMPEG.cmake index 79144eb94c..f4f62034a8 100644 --- a/buildfiles/cmake/FindFFMPEG.cmake +++ b/buildfiles/cmake/FindFFMPEG.cmake @@ -21,7 +21,7 @@ if (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) # in cache already set(FFMPEG_FOUND TRUE) -else (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) +else () # use pkg-config to get the directories and then use these values # in the FIND_PATH() and FIND_LIBRARY() calls find_package(PkgConfig) @@ -31,7 +31,7 @@ else (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) pkg_check_modules(_FFMPEG_AVUTIL libavutil) pkg_check_modules(_FFMPEG_SWSCALE libswscale) pkg_check_modules(_FFMPEG_SWRESAMPLE libswresample) - endif (PKG_CONFIG_FOUND) + endif () find_path(FFMPEG_AVCODEC_INCLUDE_DIR NAMES libavcodec/avcodec.h @@ -64,9 +64,10 @@ else (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) PATHS ${_FFMPEG_SWRESAMPLE_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) - if (FFMPEG_LIBAVCODEC AND FFMPEG_LIBAVFORMAT AND FFMPEG_LIBSWSCALE AND FFMPEG_LIBSWRESAMPLE) - set(FFMPEG_FOUND TRUE) - endif() + find_package_handle_standard_args(FFMPEG + DEFAULT_MSG + FFMPEG_LIBAVCODEC FFMPEG_LIBAVFORMAT FFMPEG_LIBSWSCALE FFMPEG_LIBSWRESAMPLE + ) if (FFMPEG_FOUND) set(FFMPEG_INCLUDE_DIR ${FFMPEG_AVCODEC_INCLUDE_DIR}) @@ -79,17 +80,6 @@ else (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) ${FFMPEG_LIBSWRESAMPLE} ) - endif (FFMPEG_FOUND) - - if (FFMPEG_FOUND) - if (NOT FFMPEG_FIND_QUIETLY) - message(STATUS "Found FFMPEG or Libav: ${FFMPEG_LIBRARIES}, ${FFMPEG_INCLUDE_DIR}") - endif (NOT FFMPEG_FIND_QUIETLY) - else (FFMPEG_FOUND) - if (FFMPEG_FIND_REQUIRED) - message(FATAL_ERROR "Could not find libavcodec or libavformat or libavutil or libswscale or libswresample") - endif (FFMPEG_FIND_REQUIRED) - endif (FFMPEG_FOUND) - -endif (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) + endif () +endif () diff --git a/buildfiles/cmake/FindWayland.cmake b/buildfiles/cmake/FindWayland.cmake index f93218b873..6ace12a523 100644 --- a/buildfiles/cmake/FindWayland.cmake +++ b/buildfiles/cmake/FindWayland.cmake @@ -49,11 +49,11 @@ IF (NOT WIN32) include(FindPackageHandleStandardArgs) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CLIENT DEFAULT_MSG WAYLAND_CLIENT_LIBRARIES WAYLAND_CLIENT_INCLUDE_DIR) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_SERVER DEFAULT_MSG WAYLAND_SERVER_LIBRARIES WAYLAND_SERVER_INCLUDE_DIR) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_EGL DEFAULT_MSG WAYLAND_EGL_LIBRARIES WAYLAND_EGL_INCLUDE_DIR) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CURSOR DEFAULT_MSG WAYLAND_CURSOR_LIBRARIES WAYLAND_CURSOR_INCLUDE_DIR) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_LIBRARIES WAYLAND_INCLUDE_DIR) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CLIENT REQUIRED_VARS WAYLAND_CLIENT_LIBRARIES WAYLAND_CLIENT_INCLUDE_DIR NAME_MISMATCHED) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_SERVER REQUIRED_VARS WAYLAND_SERVER_LIBRARIES WAYLAND_SERVER_INCLUDE_DIR NAME_MISMATCHED) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_EGL REQUIRED_VARS WAYLAND_EGL_LIBRARIES WAYLAND_EGL_INCLUDE_DIR NAME_MISMATCHED) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CURSOR REQUIRED_VARS WAYLAND_CURSOR_LIBRARIES WAYLAND_CURSOR_INCLUDE_DIR NAME_MISMATCHED) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND REQUIRED_VARS WAYLAND_LIBRARIES WAYLAND_INCLUDE_DIR NAME_MISMATCHED) MARK_AS_ADVANCED( WAYLAND_INCLUDE_DIR WAYLAND_LIBRARIES diff --git a/rpcs3/CMakeLists.txt b/rpcs3/CMakeLists.txt index 395ea52e87..150d667af1 100644 --- a/rpcs3/CMakeLists.txt +++ b/rpcs3/CMakeLists.txt @@ -13,23 +13,23 @@ set(CMAKE_CXX_STANDARD 20) set(ADDITIONAL_LIBS "") if(CMAKE_SYSTEM_NAME STREQUAL "Linux") #on some Linux distros shm_unlink and similar functions are in librt only - set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} "rt") + list(APPEND ADDITIONAL_LIBS "rt") elseif(NOT WIN32 AND NOT CMAKE_CXX_FLAGS MATCHES "LIBICONV_PLUG") #it seems like glibc includes the iconv functions we use but other libc #implementations like the one on OSX don't seem implement them - set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} "iconv") + list(APPEND ADDITIONAL_LIBS "iconv") endif() if(UNIX AND NOT APPLE AND NOT ANDROID) - add_definitions(-DDATADIR="${CMAKE_INSTALL_FULL_DATADIR}/rpcs3") + add_compile_definitions(DATADIR="${CMAKE_INSTALL_FULL_DATADIR}/rpcs3") # Optionally enable X11 for window management find_package(X11) if(X11_FOUND) - add_definitions(-DHAVE_X11) + add_compile_definitions(HAVE_X11) endif() find_package(Wayland) if(WAYLAND_FOUND) - add_definitions(-DHAVE_WAYLAND) + add_compile_definitions(HAVE_WAYLAND) endif() endif() @@ -188,7 +188,6 @@ endif() # Unit tests if(BUILD_RPCS3_TESTS) - enable_testing() find_package(GTest REQUIRED) message(STATUS "Building unit tests...") @@ -206,6 +205,7 @@ if(BUILD_RPCS3_TESTS) target_link_libraries(rpcs3_test PRIVATE rpcs3_lib + rpcs3_emu GTest::gtest ) diff --git a/rpcs3/Input/hid_pad_handler.h b/rpcs3/Input/hid_pad_handler.h index 36e7358211..d6f93ce857 100644 --- a/rpcs3/Input/hid_pad_handler.h +++ b/rpcs3/Input/hid_pad_handler.h @@ -4,7 +4,7 @@ #include "Utilities/CRC.h" #include "Utilities/Thread.h" -#include "hidapi.h" +#include #ifdef ANDROID #include "hidapi_libusb.h" From bda335a50596935f6fb0dbdc22698bb1377f66ac Mon Sep 17 00:00:00 2001 From: Marcin Serwin Date: Sat, 24 May 2025 18:51:09 +0200 Subject: [PATCH 015/384] cmake: add option to use system cubeb Signed-off-by: Marcin Serwin --- 3rdparty/CMakeLists.txt | 9 ++++++++- CMakeLists.txt | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index 044fd464eb..6c49a889ba 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -131,7 +131,14 @@ add_subdirectory(stblib) add_subdirectory(discord-rpc) # Cubeb -add_subdirectory(cubeb EXCLUDE_FROM_ALL) +if(USE_SYSTEM_CUBEB) + find_package(cubeb REQUIRED GLOBAL) + message(STATUS "Using system cubeb version '${cubeb_VERSION}'") + add_library(3rdparty::cubeb ALIAS cubeb::cubeb) +else() + message(STATUS "Using static cubeb from 3rdparty") + add_subdirectory(cubeb EXCLUDE_FROM_ALL) +endif() # SoundTouch add_subdirectory(SoundTouch EXCLUDE_FROM_ALL) diff --git a/CMakeLists.txt b/CMakeLists.txt index a0867ab67f..09c1c47e63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ option(USE_SYSTEM_FFMPEG "Prefer system ffmpeg instead of the prebuild one" OFF) option(USE_SYSTEM_OPENAL "Prefer system OpenAL instead of the prebuild one" ON) option(USE_SYSTEM_CURL "Prefer system Curl instead of the prebuild one" ON) option(USE_SYSTEM_OPENCV "Prefer system OpenCV instead of the builtin one" ON) +option(USE_SYSTEM_CUBEB "Prefer system cubeb instead of the builtin one" OFF) option(HAS_MEMORY_BREAKPOINTS "Add support for memory breakpoints to the interpreter" OFF) option(USE_LTO "Use LTO for building" ON) option(BUILD_RPCS3_TESTS "Build RPCS3 unit tests." OFF) From c0bfc34a75ac3bdae7a1baf57e79c8e225287bfe Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sun, 25 May 2025 18:38:53 +0200 Subject: [PATCH 016/384] Fix codestyle --- rpcs3/Emu/RSX/RSXFIFO.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXFIFO.h b/rpcs3/Emu/RSX/RSXFIFO.h index d62d32a134..91f7ffb050 100644 --- a/rpcs3/Emu/RSX/RSXFIFO.h +++ b/rpcs3/Emu/RSX/RSXFIFO.h @@ -93,7 +93,7 @@ namespace rsx std::array register_properties{}; - for (const auto &method : ignorable_ranges) + for (const auto& method : ignorable_ranges) { for (u32 i = 0; i < method.second; ++i) { @@ -175,4 +175,4 @@ namespace rsx bool skip_methods(u32 count); }; } -} \ No newline at end of file +} From ae35430c9686ba2af762be793f0fe02934390b2b Mon Sep 17 00:00:00 2001 From: Megamouse Date: Wed, 28 May 2025 23:37:53 +0200 Subject: [PATCH 017/384] multithreaded version_check --- 3rdparty/version_check.sh | 82 ++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 31 deletions(-) diff --git a/3rdparty/version_check.sh b/3rdparty/version_check.sh index 2b721fe28f..0e195b553e 100644 --- a/3rdparty/version_check.sh +++ b/3rdparty/version_check.sh @@ -1,7 +1,11 @@ -#!/bin/sh -ex +#!/bin/bash -ex verbose=0 git_verbose=0 +max_jobs=16 + +lockfile="$(pwd)/version_check.lock" +resultfile="$(pwd)/version_check_results.txt" if [ "$1" = "-v" ]; then verbose=1 @@ -10,9 +14,13 @@ elif [ "$1" = "-vv" ]; then git_verbose=1 fi -max_dir_length=0 -result_dirs=() -result_msgs=() +# Limit concurrent jobs +job_control() +{ + while [ "$(jobs | wc -l)" -ge "$max_jobs" ]; do + sleep 0.1 + done +} git_call() { @@ -27,20 +35,20 @@ git_call() check_tags() { - path=$(echo "$1" | sed 's:/*$::') + local path=$(echo "$1" | sed 's:/*$::') echo "Checking $path" - git_call fetch --prune --all + # git_call fetch --prune --all # Get the latest tag (by commit date, not tag name) - tag_list=$(git_call rev-list --tags --max-count=1) - latest_tag=$(git_call describe --tags "$tag_list") + local tag_list=$(git_call rev-list --tags --max-count=1) + local latest_tag=$(git_call describe --tags "$tag_list") if [ -n "$latest_tag" ]; then # Get the current tag - current_tag=$(git_call describe --tags --abbrev=0) + local current_tag=$(git_call describe --tags --abbrev=0) if [ -n "$current_tag" ]; then @@ -48,8 +56,8 @@ check_tags() echo "$path -> latest: $latest_tag, current: $current_tag" fi - ts1=$(git_call log -1 --format=%ct $latest_tag) - ts2=$(git_call log -1 --format=%ct $current_tag) + local ts1=$(git_call log -1 --format=%ct $latest_tag) + local ts2=$(git_call log -1 --format=%ct $current_tag) if (( ts1 > ts2 )); then if [ "$verbose" -eq 1 ]; then @@ -58,12 +66,11 @@ check_tags() echo "$path -> latest: $latest_tag, current: $current_tag" fi - path_length=${#path} - if (( $path_length > $max_dir_length )); then - max_dir_length=$path_length - fi - result_dirs+=("$path") - result_msgs+=("latest: $latest_tag, current: $current_tag") + # Critical section guarded by flock + ( + flock 200 + echo "$path -> latest: $latest_tag, current: $current_tag" >> "$resultfile" + ) 200>"$lockfile" fi elif [ "$verbose" -eq 1 ]; then @@ -79,19 +86,21 @@ check_tags() fi } +# Fetch and check repositories multi threaded for submoduledir in */ ; do cd "$submoduledir" || continue if [ -e ".git" ]; then - check_tags "$submoduledir" + job_control + check_tags "$submoduledir" & else - # find */ -mindepth 1 -maxdepth 1 -type d | while read -r sub; for sub in */ ; do if [ -e "$sub/.git" ]; then cd "$sub" || continue - check_tags "$submoduledir$sub" + job_control + check_tags "$submoduledir$sub" & cd .. || exit fi done @@ -100,16 +109,27 @@ do cd .. || exit done +# Wait for all background jobs to finish +wait + +# Print results echo -e "\n\nResult:\n" -i=0 -for result_dir in "${result_dirs[@]}"; do - msg="" - diff=$(($max_dir_length - ${#result_dir})) - if (( $diff > 0 )); then - msg+=$(printf "%${diff}s" "") + +# Find the max length of the paths (before '->') +max_len=0 +while IFS='->' read -r left _; do + len=$(echo -n "$left" | wc -c) + if (( len > max_len )); then + max_len=$len fi - msg+="$result_dir" - echo "$msg -> ${result_msgs[$i]}" - ((i++)) -done -echo "" +done < "$resultfile" + +# Print with padding so '->' lines up +while IFS='->' read -r left right; do + right=$(echo "$right" | sed 's/^[[:space:]]*>*[[:space:]]*//') + printf "%-${max_len}s -> %s\n" "$left" "$right" +done < "$resultfile" + +# Remove tmp files +rm -f "$resultfile" +rm -f "$lockfile" From 382e62c7d8755fbd1bbeb1b70c44e211f2d5cdfa Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sun, 25 May 2025 22:42:53 +0200 Subject: [PATCH 018/384] input: implement basic copiloting --- rpcs3/Emu/Cell/Modules/cellGem.cpp | 20 ++-- rpcs3/Emu/Cell/Modules/cellPad.cpp | 147 +++++++++++++++++++------- rpcs3/Emu/Cell/Modules/cellPad.h | 14 +-- rpcs3/Emu/Io/Buzz.cpp | 2 +- rpcs3/Emu/Io/GHLtar.cpp | 2 +- rpcs3/Emu/Io/GameTablet.cpp | 2 +- rpcs3/Emu/Io/GunCon3.cpp | 2 +- rpcs3/Emu/Io/TopShotElite.cpp | 2 +- rpcs3/Emu/Io/TopShotFearmaster.cpp | 2 +- rpcs3/Emu/Io/Turntable.cpp | 2 +- rpcs3/Emu/Io/pad_types.h | 24 +++++ rpcs3/Emu/Io/usio.cpp | 4 +- rpcs3/Emu/RSX/Overlays/overlays.cpp | 2 +- rpcs3/Input/gui_pad_thread.cpp | 2 +- rpcs3/Input/pad_thread.cpp | 53 +++++++--- rpcs3/Input/pad_thread.h | 2 +- rpcs3/Input/product_info.cpp | 5 + rpcs3/rpcs3qt/pad_settings_dialog.cpp | 7 ++ 18 files changed, 212 insertions(+), 82 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellGem.cpp b/rpcs3/Emu/Cell/Modules/cellGem.cpp index ddb582c5d8..bfbeb416df 100644 --- a/rpcs3/Emu/Cell/Modules/cellGem.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGem.cpp @@ -351,7 +351,7 @@ public: for (u32 i = 0; i < CELL_GEM_MAX_NUM; i++) { const auto& pad = ::at32(handler->GetPads(), pad_num(i)); - const bool connected = pad && (pad->m_port_status & CELL_PAD_STATUS_CONNECTED) && i < attribute.max_connect; + const bool connected = pad && pad->is_connected() && i < attribute.max_connect; const bool is_real_move = g_cfg.io.move != move_handler::real || pad->m_pad_handler == pad_handler::move; update_connection(i, connected && is_real_move); @@ -469,7 +469,7 @@ public: for (u32 i = 0; i < std::min(attribute.max_connect, CELL_GEM_MAX_NUM); i++) { const auto& pad = ::at32(handler->GetPads(), pad_num(i)); - if (pad && pad->m_pad_handler == pad_handler::move && (pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (pad && pad->m_pad_handler == pad_handler::move && pad->is_connected()) { connected_controllers++; @@ -490,7 +490,7 @@ public: for (u32 i = 0; i < std::min(attribute.max_connect, CELL_GEM_MAX_NUM); i++) { const auto& pad = ::at32(handler->GetPads(), pad_num(i)); - if (pad && (pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (pad && pad->is_connected()) { connected_controllers++; @@ -1776,7 +1776,7 @@ static void ds3_input_to_pad(const u32 gem_num, be_t& digital_buttons, be_t const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (!pad->is_connected()) { return; } @@ -1864,7 +1864,7 @@ static void ds3_pos_to_gem_state(u32 gem_num, gem_config::gem_controller& contro const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (!pad->is_connected()) { return; } @@ -1895,7 +1895,7 @@ static void ps_move_pos_to_gem_state(u32 gem_num, gem_config::gem_controller& co const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad->m_pad_handler != pad_handler::move || !(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (pad->m_pad_handler != pad_handler::move || !pad->is_connected()) { return; } @@ -1940,7 +1940,7 @@ static void ds3_input_to_ext(u32 gem_num, gem_config::gem_controller& controller const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (!pad->is_connected()) { return; } @@ -2777,7 +2777,7 @@ error_code cellGemGetInertialState(u32 gem_num, u32 state_flag, u64 timestamp, v const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad && (pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (pad && pad->is_connected()) { inertial_state->temperature = pad->move_data.temperature; inertial_state->accelerometer[0] = pad->move_data.accelerometer_x; @@ -3392,7 +3392,7 @@ error_code cellGemReadExternalPortDeviceInfo(u32 gem_num, vm::ptr ext_id, v const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad->m_pad_handler != pad_handler::move || !(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (pad->m_pad_handler != pad_handler::move || !pad->is_connected()) { return CELL_GEM_NOT_CONNECTED; } @@ -3706,7 +3706,7 @@ error_code cellGemWriteExternalPort(u32 gem_num, vm::ptrGetPads(), pad_num(gem_num)); - if (pad->m_pad_handler != pad_handler::move || !(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (pad->m_pad_handler != pad_handler::move || !pad->is_connected()) { return CELL_GEM_NOT_CONNECTED; } diff --git a/rpcs3/Emu/Cell/Modules/cellPad.cpp b/rpcs3/Emu/Cell/Modules/cellPad.cpp index f28d96d1ce..61e29805aa 100644 --- a/rpcs3/Emu/Cell/Modules/cellPad.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPad.cpp @@ -272,7 +272,7 @@ error_code cellPadInit(ppu_thread& ppu, u32 max_connect) for (usz i = 0; i < config.get_max_connect(); ++i) { - if (!pads[i]->is_fake_pad && (pads[i]->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (!pads[i]->is_fake_pad && pads[i]->is_connected()) { send_sys_io_connect_event(i, CELL_PAD_STATUS_CONNECTED); } @@ -339,7 +339,7 @@ error_code cellPadClearBuf(u32 port_no) const auto& pads = handler->GetPads(); const auto& pad = pads[port_no]; - if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !pad->is_connected()) return not_an_error(CELL_PAD_ERROR_NO_DEVICE); clear_pad_buffer(pad); @@ -411,26 +411,59 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false) } }; - for (Button& button : pad->m_buttons) + for (const Button& button : pad->m_buttons) { // here we check btns, and set pad accordingly, // if something changed, set btnChanged + bool pressed = button.m_pressed; + u16 value = button.m_value; + + // Merge copilots + if (!pad->copilots.empty()) + { + for (const auto& copilot : pad->copilots) + { + if (!copilot || !copilot->is_connected()) + { + continue; + } + + for (const Button& other : copilot->m_buttons) + { + if (button.m_offset == other.m_offset && button.m_outKeyCode == other.m_outKeyCode) + { + if (other.m_pressed) + { + pressed = true; + + if (value < other.m_value) + { + value = other.m_value; + } + } + + break; + } + } + } + } + switch (button.m_offset) { case CELL_PAD_BTN_OFFSET_DIGITAL1: { - if (button.m_pressed) + if (pressed) pad->m_digital_1 |= button.m_outKeyCode; else pad->m_digital_1 &= ~button.m_outKeyCode; switch (button.m_outKeyCode) { - case CELL_PAD_CTRL_LEFT: set_value(pad->m_press_left, button.m_value); break; - case CELL_PAD_CTRL_DOWN: set_value(pad->m_press_down, button.m_value); break; - case CELL_PAD_CTRL_RIGHT: set_value(pad->m_press_right, button.m_value); break; - case CELL_PAD_CTRL_UP: set_value(pad->m_press_up, button.m_value); break; + case CELL_PAD_CTRL_LEFT: set_value(pad->m_press_left, value); break; + case CELL_PAD_CTRL_DOWN: set_value(pad->m_press_down, value); break; + case CELL_PAD_CTRL_RIGHT: set_value(pad->m_press_right, value); break; + case CELL_PAD_CTRL_UP: set_value(pad->m_press_up, value); break; // These arent pressure btns case CELL_PAD_CTRL_R3: case CELL_PAD_CTRL_L3: @@ -442,21 +475,21 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false) } case CELL_PAD_BTN_OFFSET_DIGITAL2: { - if (button.m_pressed) + if (pressed) pad->m_digital_2 |= button.m_outKeyCode; else pad->m_digital_2 &= ~button.m_outKeyCode; switch (button.m_outKeyCode) { - case CELL_PAD_CTRL_SQUARE: set_value(pad->m_press_square, button.m_value); break; - case CELL_PAD_CTRL_CROSS: set_value(pad->m_press_cross, button.m_value); break; - case CELL_PAD_CTRL_CIRCLE: set_value(pad->m_press_circle, button.m_value); break; - case CELL_PAD_CTRL_TRIANGLE: set_value(pad->m_press_triangle, button.m_value); break; - case CELL_PAD_CTRL_R1: set_value(pad->m_press_R1, button.m_value); break; - case CELL_PAD_CTRL_L1: set_value(pad->m_press_L1, button.m_value); break; - case CELL_PAD_CTRL_R2: set_value(pad->m_press_R2, button.m_value); break; - case CELL_PAD_CTRL_L2: set_value(pad->m_press_L2, button.m_value); break; + case CELL_PAD_CTRL_SQUARE: set_value(pad->m_press_square, value); break; + case CELL_PAD_CTRL_CROSS: set_value(pad->m_press_cross, value); break; + case CELL_PAD_CTRL_CIRCLE: set_value(pad->m_press_circle, value); break; + case CELL_PAD_CTRL_TRIANGLE: set_value(pad->m_press_triangle, value); break; + case CELL_PAD_CTRL_R1: set_value(pad->m_press_R1, value); break; + case CELL_PAD_CTRL_L1: set_value(pad->m_press_L1, value); break; + case CELL_PAD_CTRL_R2: set_value(pad->m_press_R2, value); break; + case CELL_PAD_CTRL_L2: set_value(pad->m_press_L2, value); break; default: break; } break; @@ -465,18 +498,18 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false) { switch (button.m_outKeyCode) { - case CELL_PAD_CTRL_PRESS_RIGHT: set_value(pad->m_press_right, button.m_value, true); break; - case CELL_PAD_CTRL_PRESS_LEFT: set_value(pad->m_press_left, button.m_value, true); break; - case CELL_PAD_CTRL_PRESS_UP: set_value(pad->m_press_up, button.m_value, true); break; - case CELL_PAD_CTRL_PRESS_DOWN: set_value(pad->m_press_down, button.m_value, true); break; - case CELL_PAD_CTRL_PRESS_TRIANGLE: set_value(pad->m_press_triangle, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard - case CELL_PAD_CTRL_PRESS_CIRCLE: set_value(pad->m_press_circle, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard - case CELL_PAD_CTRL_PRESS_CROSS: set_value(pad->m_press_cross, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard - case CELL_PAD_CTRL_PRESS_SQUARE: set_value(pad->m_press_square, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard - case CELL_PAD_CTRL_PRESS_L1: set_value(pad->m_press_L1, button.m_value, true); break; - case CELL_PAD_CTRL_PRESS_R1: set_value(pad->m_press_R1, button.m_value, true); break; - case CELL_PAD_CTRL_PRESS_L2: set_value(pad->m_press_L2, button.m_value, true); break; - case CELL_PAD_CTRL_PRESS_R2: set_value(pad->m_press_R2, button.m_value, true); break; + case CELL_PAD_CTRL_PRESS_RIGHT: set_value(pad->m_press_right, value, true); break; + case CELL_PAD_CTRL_PRESS_LEFT: set_value(pad->m_press_left, value, true); break; + case CELL_PAD_CTRL_PRESS_UP: set_value(pad->m_press_up, value, true); break; + case CELL_PAD_CTRL_PRESS_DOWN: set_value(pad->m_press_down, value, true); break; + case CELL_PAD_CTRL_PRESS_TRIANGLE: set_value(pad->m_press_triangle, value, true, 255, 63); break; // Infrared on RIDE Skateboard + case CELL_PAD_CTRL_PRESS_CIRCLE: set_value(pad->m_press_circle, value, true, 255, 63); break; // Infrared on RIDE Skateboard + case CELL_PAD_CTRL_PRESS_CROSS: set_value(pad->m_press_cross, value, true, 255, 63); break; // Infrared on RIDE Skateboard + case CELL_PAD_CTRL_PRESS_SQUARE: set_value(pad->m_press_square, value, true, 255, 63); break; // Infrared on RIDE Skateboard + case CELL_PAD_CTRL_PRESS_L1: set_value(pad->m_press_L1, value, true); break; + case CELL_PAD_CTRL_PRESS_R1: set_value(pad->m_press_R1, value, true); break; + case CELL_PAD_CTRL_PRESS_L2: set_value(pad->m_press_L2, value, true); break; + case CELL_PAD_CTRL_PRESS_R2: set_value(pad->m_press_R2, value, true); break; default: break; } break; @@ -488,12 +521,44 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false) for (const AnalogStick& stick : pad->m_sticks) { + u16 value = stick.m_value; + + // Merge copilots + if (!pad->copilots.empty()) + { + const auto normalize = [](s32 value) + { + return (value - 128) / 127.0f; + }; + + f32 accumulated_value = normalize(value); + + for (const auto& copilot : pad->copilots) + { + if (!copilot || !copilot->is_connected()) + { + continue; + } + + for (const AnalogStick& other : copilot->m_sticks) + { + if (stick.m_offset == other.m_offset) + { + accumulated_value += normalize(other.m_value); + break; + } + } + } + + value = static_cast(std::round(std::clamp(accumulated_value * 127.0f + 128.0f, 0.0f, 255.0f))); + } + switch (stick.m_offset) { - case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: set_value(pad->m_analog_left_x, stick.m_value); break; - case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: set_value(pad->m_analog_left_y, stick.m_value); break; - case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: set_value(pad->m_analog_right_x, stick.m_value); break; - case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: set_value(pad->m_analog_right_y, stick.m_value); break; + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: set_value(pad->m_analog_left_x, value); break; + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: set_value(pad->m_analog_left_y, value); break; + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: set_value(pad->m_analog_right_x, value); break; + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: set_value(pad->m_analog_right_y, value); break; default: break; } } @@ -712,7 +777,7 @@ error_code cellPadGetData(u32 port_no, vm::ptr data) const auto& pads = handler->GetPads(); const auto& pad = pads[port_no]; - if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !pad->is_connected()) return not_an_error(CELL_PAD_ERROR_NO_DEVICE); pad_get_data(port_no, data.get_ptr()); @@ -798,7 +863,7 @@ error_code cellPadPeriphGetData(u32 port_no, vm::ptr data) const auto& pads = handler->GetPads(); const auto& pad = pads[port_no]; - if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !pad->is_connected()) return not_an_error(CELL_PAD_ERROR_NO_DEVICE); pad_get_data(port_no, &data->cellpad_data, true); @@ -830,7 +895,7 @@ error_code cellPadGetRawData(u32 port_no, vm::ptr data) const auto& pads = handler->GetPads(); const auto& pad = pads[port_no]; - if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !pad->is_connected()) return not_an_error(CELL_PAD_ERROR_NO_DEVICE); // ? @@ -843,7 +908,7 @@ error_code cellPadGetDataExtra(u32 port_no, vm::ptr device_type, vm::ptr param) const auto& pads = handler->GetPads(); const auto& pad = pads[port_no]; - if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !pad->is_connected()) return not_an_error(CELL_PAD_ERROR_NO_DEVICE); // TODO: find out if this is checked here or later or at all @@ -1021,7 +1086,7 @@ error_code cellPadGetCapabilityInfo(u32 port_no, vm::ptr const auto& pads = handler->GetPads(); const auto& pad = pads[port_no]; - if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !pad->is_connected()) return not_an_error(CELL_PAD_ERROR_NO_DEVICE); // Should return the same as device capability mask, psl1ght has it backwards in pad->h @@ -1077,7 +1142,7 @@ error_code cellPadInfoPressMode(u32 port_no) const auto& pads = handler->GetPads(); const auto& pad = pads[port_no]; - if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !pad->is_connected()) return not_an_error(CELL_PAD_ERROR_NO_DEVICE); return not_an_error((pad->m_device_capability & CELL_PAD_CAPABILITY_PRESS_MODE) ? 1 : 0); @@ -1104,7 +1169,7 @@ error_code cellPadInfoSensorMode(u32 port_no) const auto& pads = handler->GetPads(); const auto& pad = pads[port_no]; - if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (pad->is_fake_pad || !config.is_reportedly_connected(port_no) || !pad->is_connected()) return not_an_error(CELL_PAD_ERROR_NO_DEVICE); return not_an_error((pad->m_device_capability & CELL_PAD_CAPABILITY_SENSOR_MODE) ? 1 : 0); diff --git a/rpcs3/Emu/Cell/Modules/cellPad.h b/rpcs3/Emu/Cell/Modules/cellPad.h index 0fdd4b23a7..3394fe6b2b 100644 --- a/rpcs3/Emu/Cell/Modules/cellPad.h +++ b/rpcs3/Emu/Cell/Modules/cellPad.h @@ -42,13 +42,13 @@ enum struct pad_data_internal { - u16 vendor_id; - u16 product_id; - u32 port_status; - u32 device_capability; - u32 device_type; - u32 pclass_type; - u32 pclass_profile; + u16 vendor_id = 0; + u16 product_id = 0; + u32 port_status = 0; + u32 device_capability = 0; + u32 device_type = 0; + u32 pclass_type = 0; + u32 pclass_profile = 0; ENABLE_BITWISE_SERIALIZATION; }; diff --git a/rpcs3/Emu/Io/Buzz.cpp b/rpcs3/Emu/Io/Buzz.cpp index 7c7890d41e..d5b7fe4f23 100644 --- a/rpcs3/Emu/Io/Buzz.cpp +++ b/rpcs3/Emu/Io/Buzz.cpp @@ -173,7 +173,7 @@ void usb_device_buzz::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint*/ { const auto& pad = pads[i]; - if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (!pad->is_connected()) { continue; } diff --git a/rpcs3/Emu/Io/GHLtar.cpp b/rpcs3/Emu/Io/GHLtar.cpp index e520e53c7f..9a2b9d0ce6 100644 --- a/rpcs3/Emu/Io/GHLtar.cpp +++ b/rpcs3/Emu/Io/GHLtar.cpp @@ -152,7 +152,7 @@ void usb_device_ghltar::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), m_controller_index); - if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (!pad->is_connected()) { return; } diff --git a/rpcs3/Emu/Io/GameTablet.cpp b/rpcs3/Emu/Io/GameTablet.cpp index 31ed81f3af..0b87a709bf 100644 --- a/rpcs3/Emu/Io/GameTablet.cpp +++ b/rpcs3/Emu/Io/GameTablet.cpp @@ -198,7 +198,7 @@ void usb_device_gametablet::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endp const auto gamepad_handler = pad::get_pad_thread(); const auto& pads = gamepad_handler->GetPads(); const auto& pad = ::at32(pads, m_controller_index); - if (pad->m_port_status & CELL_PAD_STATUS_CONNECTED) + if (pad->is_connected()) { for (Button& button : pad->m_buttons) { diff --git a/rpcs3/Emu/Io/GunCon3.cpp b/rpcs3/Emu/Io/GunCon3.cpp index d229693907..8dc5688f73 100644 --- a/rpcs3/Emu/Io/GunCon3.cpp +++ b/rpcs3/Emu/Io/GunCon3.cpp @@ -258,7 +258,7 @@ void usb_device_guncon3::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint, const auto gamepad_handler = pad::get_pad_thread(); const auto& pads = gamepad_handler->GetPads(); const auto& pad = ::at32(pads, m_controller_index); - if (pad->m_port_status & CELL_PAD_STATUS_CONNECTED) + if (pad->is_connected()) { cfg->handle_input(pad, true, input_callback); } diff --git a/rpcs3/Emu/Io/TopShotElite.cpp b/rpcs3/Emu/Io/TopShotElite.cpp index 06cddab9f0..b7e2b64b98 100644 --- a/rpcs3/Emu/Io/TopShotElite.cpp +++ b/rpcs3/Emu/Io/TopShotElite.cpp @@ -318,7 +318,7 @@ void usb_device_topshotelite::interrupt_transfer(u32 buf_size, u8* buf, u32 /*en const auto gamepad_handler = pad::get_pad_thread(); const auto& pads = gamepad_handler->GetPads(); const auto& pad = ::at32(pads, m_controller_index); - if (pad->m_port_status & CELL_PAD_STATUS_CONNECTED) + if (pad->is_connected()) { cfg->handle_input(pad, true, input_callback); } diff --git a/rpcs3/Emu/Io/TopShotFearmaster.cpp b/rpcs3/Emu/Io/TopShotFearmaster.cpp index 98b54700d9..03c634d839 100644 --- a/rpcs3/Emu/Io/TopShotFearmaster.cpp +++ b/rpcs3/Emu/Io/TopShotFearmaster.cpp @@ -342,7 +342,7 @@ void usb_device_topshotfearmaster::interrupt_transfer(u32 buf_size, u8* buf, u32 const auto gamepad_handler = pad::get_pad_thread(); const auto& pads = gamepad_handler->GetPads(); const auto& pad = ::at32(pads, m_controller_index); - if (pad->m_port_status & CELL_PAD_STATUS_CONNECTED) + if (pad->is_connected()) { cfg->handle_input(pad, true, input_callback); } diff --git a/rpcs3/Emu/Io/Turntable.cpp b/rpcs3/Emu/Io/Turntable.cpp index eca1926825..ec67fabc22 100644 --- a/rpcs3/Emu/Io/Turntable.cpp +++ b/rpcs3/Emu/Io/Turntable.cpp @@ -166,7 +166,7 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo const auto& pads = handler->GetPads(); const auto& pad = ::at32(pads, m_controller_index); - if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (!pad->is_connected()) return; const auto& cfg = ::at32(g_cfg_turntable.players, m_controller_index); diff --git a/rpcs3/Emu/Io/pad_types.h b/rpcs3/Emu/Io/pad_types.h index e6761a295f..57634a66b4 100644 --- a/rpcs3/Emu/Io/pad_types.h +++ b/rpcs3/Emu/Io/pad_types.h @@ -151,6 +151,13 @@ enum CELL_PAD_FAKE_TYPE_TOP_SHOT_ELITE = 0xa001, CELL_PAD_FAKE_TYPE_TOP_SHOT_FEARMASTER = 0xa002, CELL_PAD_FAKE_TYPE_GAMETABLET = 0xa003, + CELL_PAD_FAKE_TYPE_COPILOT_1 = 0xa004, + CELL_PAD_FAKE_TYPE_COPILOT_2 = 0xa005, + CELL_PAD_FAKE_TYPE_COPILOT_3 = 0xa006, + CELL_PAD_FAKE_TYPE_COPILOT_4 = 0xa007, + CELL_PAD_FAKE_TYPE_COPILOT_5 = 0xa008, + CELL_PAD_FAKE_TYPE_COPILOT_6 = 0xa009, + CELL_PAD_FAKE_TYPE_COPILOT_7 = 0xa00a, CELL_PAD_FAKE_TYPE_LAST, CELL_PAD_PCLASS_TYPE_MAX // last item @@ -536,6 +543,8 @@ struct Pad std::array m_sensors{}; std::array m_vibrateMotors{}; + std::vector> copilots; + // These hold bits for their respective buttons u16 m_digital_1{0}; u16 m_digital_2{0}; @@ -592,4 +601,19 @@ struct Pad m_product_id = product_id; m_pressure_intensity = (255 * pressure_intensity_percent) / 100; } + + u32 copilot_player() const + { + if (m_class_type >= CELL_PAD_FAKE_TYPE_COPILOT_1 && m_class_type <= CELL_PAD_FAKE_TYPE_COPILOT_7) + { + return m_class_type - CELL_PAD_FAKE_TYPE_COPILOT_1; + } + + return umax; + } + + bool is_connected() const + { + return !!(m_port_status & CELL_PAD_STATUS_CONNECTED); + } }; diff --git a/rpcs3/Emu/Io/usio.cpp b/rpcs3/Emu/Io/usio.cpp index e01deccf8a..0bfc5bcd59 100644 --- a/rpcs3/Emu/Io/usio.cpp +++ b/rpcs3/Emu/Io/usio.cpp @@ -210,7 +210,7 @@ void usb_device_usio::translate_input_taiko() const usz offset = player * 8ULL; auto& status = m_io_status[0]; - if (const auto& pad = ::at32(handler->GetPads(), pad_number); (pad->m_port_status & CELL_PAD_STATUS_CONNECTED) && is_input_allowed()) + if (const auto& pad = ::at32(handler->GetPads(), pad_number); pad->is_connected() && is_input_allowed()) { const auto& cfg = ::at32(g_cfg_usio.players, pad_number); cfg->handle_input(pad, false, [&](usio_btn btn, pad_button /*pad_btn*/, u16 /*value*/, bool pressed, bool& /*abort*/) @@ -295,7 +295,7 @@ void usb_device_usio::translate_input_tekken() auto& status = m_io_status[player / 2]; auto& input = digital_input[player / 2]; - if (const auto& pad = ::at32(handler->GetPads(), pad_number); (pad->m_port_status & CELL_PAD_STATUS_CONNECTED) && is_input_allowed()) + if (const auto& pad = ::at32(handler->GetPads(), pad_number); pad->is_connected() && is_input_allowed()) { const auto& cfg = ::at32(g_cfg_usio.players, pad_number); cfg->handle_input(pad, false, [&](usio_btn btn, pad_button /*pad_btn*/, u16 /*value*/, bool pressed, bool& /*abort*/) diff --git a/rpcs3/Emu/RSX/Overlays/overlays.cpp b/rpcs3/Emu/RSX/Overlays/overlays.cpp index 47e7ee3f87..aadf03e44a 100644 --- a/rpcs3/Emu/RSX/Overlays/overlays.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlays.cpp @@ -225,7 +225,7 @@ namespace rsx continue; } - if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (!pad->is_connected()) { continue; } diff --git a/rpcs3/Input/gui_pad_thread.cpp b/rpcs3/Input/gui_pad_thread.cpp index f0bf833a46..3aa81efb29 100644 --- a/rpcs3/Input/gui_pad_thread.cpp +++ b/rpcs3/Input/gui_pad_thread.cpp @@ -283,7 +283,7 @@ void gui_pad_thread::run() void gui_pad_thread::process_input() { - if (!m_pad || !(m_pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (!m_pad || !m_pad->is_connected()) { return; } diff --git a/rpcs3/Input/pad_thread.cpp b/rpcs3/Input/pad_thread.cpp index 2f4bea7b34..58c9da78a6 100644 --- a/rpcs3/Input/pad_thread.cpp +++ b/rpcs3/Input/pad_thread.cpp @@ -227,18 +227,47 @@ void pad_thread::Init() connect_usb_controller(i, input::get_product_by_vid_pid(pad->m_vendor_id, pad->m_product_id)); } + // Set copilots + for (usz i = 0; i < m_pads.size(); i++) + { + if (!m_pads[i]) continue; + + m_pads[i]->copilots.clear(); + + for (usz j = 0; j < m_pads.size(); j++) + { + if (i == j || !m_pads[j] || m_pads[j]->copilot_player() != i) + continue; + + m_pads[i]->copilots.push_back(m_pads[j]); + } + } + // Initialize active mouse and keyboard. Activate pad handler if one exists. input::set_mouse_and_keyboard(m_handlers.contains(pad_handler::keyboard) ? input::active_mouse_and_keyboard::pad : input::active_mouse_and_keyboard::emulated); } -void pad_thread::SetRumble(const u32 pad, u8 large_motor, bool small_motor) +void pad_thread::SetRumble(u32 pad, u8 large_motor, bool small_motor) { - if (pad >= m_pads.size()) + if (pad >= m_pads.size() || !m_pads[pad]) return; - m_pads[pad]->m_last_rumble_time_us = get_system_time(); + const u64 now_us = get_system_time(); + + m_pads[pad]->m_last_rumble_time_us = now_us; m_pads[pad]->m_vibrateMotors[0].m_value = large_motor; m_pads[pad]->m_vibrateMotors[1].m_value = small_motor ? 255 : 0; + + // Rumble copilots as well + for (const auto& copilot : m_pads[pad]->copilots) + { + if (copilot && copilot->is_connected()) + { + copilot->m_last_rumble_time_us = now_us; + copilot->m_vibrateMotors[0].m_value = large_motor; + copilot->m_vibrateMotors[1].m_value = small_motor ? 255 : 0; + } + } } void pad_thread::SetIntercepted(bool intercepted) @@ -263,7 +292,7 @@ void pad_thread::update_pad_states() // Simulate unplugging and plugging in a new controller if (pad && pad->m_disconnection_timer > 0) { - const bool is_connected = pad->m_port_status & CELL_PAD_STATUS_CONNECTED; + const bool is_connected = pad->is_connected(); const u64 now = get_system_time(); if (is_connected && now < pad->m_disconnection_timer) @@ -278,7 +307,7 @@ void pad_thread::update_pad_states() } } - const bool connected = pad && !pad->is_fake_pad && !!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED); + const bool connected = pad && !pad->is_fake_pad && pad->is_connected(); if (m_pads_connected[i] == connected) continue; @@ -431,7 +460,7 @@ void pad_thread::operator()() { const auto& pad = m_pads[i]; - if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (!pad->is_connected()) continue; for (const auto& button : pad->m_buttons) @@ -468,7 +497,7 @@ void pad_thread::operator()() const auto& pad = m_pads[i]; - if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (!pad->is_connected()) continue; // Check if an LDD pad pressed the PS button (bit 0 of the first button) @@ -535,7 +564,7 @@ void pad_thread::operator()() { const auto& pad = m_pads[i]; - if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) + if (!pad->is_connected()) continue; for (const auto& button : pad->m_buttons) @@ -640,11 +669,11 @@ s32 pad_thread::AddLddPad() void pad_thread::UnregisterLddPad(u32 handle) { - ensure(handle < m_pads.size()); + auto& pad = ::at32(m_pads, handle); - m_pads[handle]->ldd = false; - m_pads[handle]->m_port_status &= ~CELL_PAD_STATUS_CONNECTED; - m_pads[handle]->m_port_status |= CELL_PAD_STATUS_ASSIGN_CHANGES; + pad->ldd = false; + pad->m_port_status &= ~CELL_PAD_STATUS_CONNECTED; + pad->m_port_status |= CELL_PAD_STATUS_ASSIGN_CHANGES; num_ldd_pad--; } diff --git a/rpcs3/Input/pad_thread.h b/rpcs3/Input/pad_thread.h index 1939ce0104..70fb0f9de3 100644 --- a/rpcs3/Input/pad_thread.h +++ b/rpcs3/Input/pad_thread.h @@ -26,7 +26,7 @@ public: PadInfo& GetInfo() { return m_info; } std::array, CELL_PAD_MAX_PORT_NUM>& GetPads() { return m_pads; } - void SetRumble(const u32 pad, u8 large_motor, bool small_motor); + void SetRumble(u32 pad, u8 large_motor, bool small_motor); void SetIntercepted(bool intercepted); s32 AddLddPad(); diff --git a/rpcs3/Input/product_info.cpp b/rpcs3/Input/product_info.cpp index 825b50d0c1..120354014d 100644 --- a/rpcs3/Input/product_info.cpp +++ b/rpcs3/Input/product_info.cpp @@ -261,6 +261,11 @@ namespace input std::vector get_products_by_class(int class_id) { + if (class_id >= CELL_PAD_FAKE_TYPE_COPILOT_1 && class_id <= CELL_PAD_FAKE_TYPE_COPILOT_7) + { + class_id = CELL_PAD_PCLASS_TYPE_STANDARD; + } + std::vector ret; for (const auto& [type, product] : input_products) { diff --git a/rpcs3/rpcs3qt/pad_settings_dialog.cpp b/rpcs3/rpcs3qt/pad_settings_dialog.cpp index fdad85e08e..4710ad4ec4 100644 --- a/rpcs3/rpcs3qt/pad_settings_dialog.cpp +++ b/rpcs3/rpcs3qt/pad_settings_dialog.cpp @@ -183,6 +183,13 @@ pad_settings_dialog::pad_settings_dialog(std::shared_ptr gui_setti ui->chooseClass->addItem(tr("Top Shot Elite"), u32{CELL_PAD_FAKE_TYPE_TOP_SHOT_ELITE}); ui->chooseClass->addItem(tr("Top Shot Fearmaster"),u32{CELL_PAD_FAKE_TYPE_TOP_SHOT_FEARMASTER}); ui->chooseClass->addItem(tr("uDraw GameTablet"), u32{CELL_PAD_FAKE_TYPE_GAMETABLET}); + ui->chooseClass->addItem(tr("Copilot for Player 1"), u32{CELL_PAD_FAKE_TYPE_COPILOT_1}); + ui->chooseClass->addItem(tr("Copilot for Player 2"), u32{CELL_PAD_FAKE_TYPE_COPILOT_2}); + ui->chooseClass->addItem(tr("Copilot for Player 3"), u32{CELL_PAD_FAKE_TYPE_COPILOT_3}); + ui->chooseClass->addItem(tr("Copilot for Player 4"), u32{CELL_PAD_FAKE_TYPE_COPILOT_4}); + ui->chooseClass->addItem(tr("Copilot for Player 5"), u32{CELL_PAD_FAKE_TYPE_COPILOT_5}); + ui->chooseClass->addItem(tr("Copilot for Player 6"), u32{CELL_PAD_FAKE_TYPE_COPILOT_6}); + ui->chooseClass->addItem(tr("Copilot for Player 7"), u32{CELL_PAD_FAKE_TYPE_COPILOT_7}); connect(ui->chooseClass, QOverload::of(&QComboBox::currentIndexChanged), this, [this](int index) { From cd7c9a8da4029c4142680165ae49137e4d3f00c4 Mon Sep 17 00:00:00 2001 From: schm1dtmac Date: Thu, 29 May 2025 14:12:38 +0100 Subject: [PATCH 019/384] Move Mac builds to GH Actions --- .ci/build-mac-arm64.sh | 92 +++------- .ci/build-mac.sh | 28 +-- .ci/deploy-mac-arm64.sh | 12 +- .ci/deploy-mac.sh | 0 .ci/export-cirrus-vars.sh | 0 .ci/get_keys-windows.sh | 0 .ci/optimize-mac.sh | 0 .github/workflows/rpcs3.yml | 77 ++++++++ README.md | 1 - azure-pipelines.yml | 260 --------------------------- buildfiles/cmake/TCDarwinARM64.cmake | 2 - rpcs3/rpcs3.vcxproj | 2 - rpcs3/rpcs3.vcxproj.filters | 6 - 13 files changed, 122 insertions(+), 358 deletions(-) mode change 100644 => 100755 .ci/build-mac-arm64.sh mode change 100644 => 100755 .ci/build-mac.sh mode change 100644 => 100755 .ci/deploy-mac-arm64.sh mode change 100644 => 100755 .ci/deploy-mac.sh mode change 100644 => 100755 .ci/export-cirrus-vars.sh mode change 100644 => 100755 .ci/get_keys-windows.sh mode change 100644 => 100755 .ci/optimize-mac.sh delete mode 100644 azure-pipelines.yml delete mode 100644 buildfiles/cmake/TCDarwinARM64.cmake diff --git a/.ci/build-mac-arm64.sh b/.ci/build-mac-arm64.sh old mode 100644 new mode 100755 index 0b7d554504..e30b5487bf --- a/.ci/build-mac-arm64.sh +++ b/.ci/build-mac-arm64.sh @@ -1,66 +1,25 @@ #!/bin/sh -ex # shellcheck disable=SC2086 -brew_arm64_install_packages() { - for pkg in "$@"; do - echo "Fetching bottle for $pkg (arm64)..." - bottle_path="$("$BREW_ARM64_PATH/bin/brew" --cache --bottle-tag=arm64_sonoma "$pkg")" - if [ ! -f "$bottle_path" ]; then - if ! "$BREW_ARM64_PATH/bin/brew" fetch --force --verbose --debug --bottle-tag=arm64_sonoma "$pkg"; then - echo "Failed to fetch bottle for $pkg" - return 1 - fi - bottle_path="$("$BREW_ARM64_PATH/bin/brew" --cache --bottle-tag=arm64_sonoma "$pkg")" - fi - - echo "Installing $pkg (arm64)..." - "$BREW_ARM64_PATH/bin/brew" install --force --force-bottle --ignore-dependencies "$bottle_path" || true - done -} - export HOMEBREW_NO_AUTO_UPDATE=1 export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 export HOMEBREW_NO_INSTALL_CLEANUP=1 -/usr/local/bin/brew update -sudo rm -rf /usr/local/Cellar/curl /usr/local/opt/curl -/usr/local/bin/brew install -f --overwrite curl -/usr/local/bin/brew uninstall -f --ignore-dependencies ffmpeg -/usr/local/bin/brew install -f --build-from-source ffmpeg@5 || true -/usr/local/bin/brew install -f --overwrite python || true -/usr/local/bin/brew link --overwrite python || true -/usr/local/bin/brew install -f --overwrite nasm ninja p7zip ccache pipenv #create-dmg -/usr/local/bin/brew link -f curl || true -/usr/local/bin/brew install llvm@$LLVM_COMPILER_VER glew cmake sdl3 vulkan-headers coreutils -/usr/local/bin/brew link -f llvm@$LLVM_COMPILER_VER ffmpeg@5 || true - -export BREW_ARM64_PATH="/opt/homebrew1" -sudo mkdir -p "$BREW_ARM64_PATH" -sudo chmod 777 "$BREW_ARM64_PATH" -curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C "$BREW_ARM64_PATH" - -#"$BREW_ARM64_PATH/bin/brew" update -# libvorbis requires Homebrew-installed curl, but we can't run it on x64, and we also need the aarch64 libs, so we swap the binary -brew_arm64_install_packages curl -mv /opt/homebrew1/opt/curl/bin/curl /opt/homebrew1/opt/curl/bin/curl.bak -ln -s /usr/local/opt/curl/bin/curl /opt/homebrew1/opt/curl/bin/curl - -brew_arm64_install_packages 0mq aom aribb24 ca-certificates cjson dav1d ffmpeg@5 fontconfig freetype freetype2 gettext glew gmp gnutls lame libbluray libidn2 libnettle libogg libpng librist libsodium libsoxr libtasn libtasn1 libunistring libvmaf libvorbis libvpx libx11 libxau libxcb libxdmcp llvm@$LLVM_COMPILER_VER mbedtls molten-vk nettle opencore-amr openjpeg openssl opus p11-kit pkg-config pkgconfig pzstd rav1e sdl3 snappy speex srt svt-av1 theora vulkan-headers webp x264 x265 xz z3 zeromq zmq zstd -"$BREW_ARM64_PATH/bin/brew" link -f ffmpeg@5 -ln -s "/opt/homebrew1/opt/llvm@$LLVM_COMPILER_VER/lib/unwind/libunwind.1.dylib" "/opt/homebrew1/opt/llvm@$LLVM_COMPILER_VER/lib/libunwind.1.dylib" +/opt/homebrew/bin/brew install -f --overwrite nasm ninja p7zip ccache pipenv gnutls freetype #create-dmg +/opt/homebrew/bin/brew install -f ffmpeg@5 +/opt/homebrew/bin/brew install "llvm@$LLVM_COMPILER_VER" glew cmake sdl3 vulkan-headers coreutils +/opt/homebrew/bin/brew link -f "llvm@$LLVM_COMPILER_VER" ffmpeg@5 # moltenvk based on commit for 1.3.0 release wget https://raw.githubusercontent.com/Homebrew/homebrew-core/7255441cbcafabaa8950f67c7ec55ff499dbb2d3/Formula/m/molten-vk.rb -/usr/local/bin/brew install -f --overwrite ./molten-vk.rb +/opt/homebrew/bin/brew install -f --overwrite ./molten-vk.rb export CXX=clang++ export CC=clang export BREW_PATH; BREW_PATH="$(brew --prefix)" -export BREW_X64_PATH; -BREW_X64_PATH="$("/usr/local/bin/brew" --prefix)" -export BREW_BIN="/usr/local/bin" -export BREW_SBIN="/usr/local/sbin" +export BREW_BIN="/opt/homebrew/bin" +export BREW_SBIN="/opt/homebrew/sbin" export CMAKE_EXTRA_OPTS='-DLLVM_TARGETS_TO_BUILD=arm64' export WORKDIR; @@ -75,36 +34,39 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then # nested Qt 6.9.0 URL workaround # sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader # sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader + # archived Qt 6.7.3 URL workaround + sed -i '' "s/official_releases/archive/g" qt-downloader cd "/tmp/Qt" - "$BREW_X64_PATH/bin/pipenv" run pip3 install py7zr requests semantic_version lxml + arch -arm64 "$BREW_PATH/bin/pipenv" run pip3 uninstall py7zr requests semantic_version lxml + arch -arm64 "$BREW_PATH/bin/pipenv" run pip3 install py7zr requests semantic_version lxml --no-cache mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64" # sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.9.0 workaround - "$BREW_X64_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64" + arch -arm64 "$BREW_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64" fi cd "$WORKDIR" ditto "/tmp/Qt/$QT_VER" "qt-downloader/$QT_VER" export Qt6_DIR="$WORKDIR/qt-downloader/$QT_VER/clang_64/lib/cmake/Qt$QT_VER_MAIN" -export SDL3_DIR="$BREW_ARM64_PATH/opt/sdl3/lib/cmake/SDL3" +export SDL3_DIR="$BREW_PATH/opt/sdl3/lib/cmake/SDL3" -export PATH="$BREW_X64_PATH/opt/llvm@$LLVM_COMPILER_VER/bin:$WORKDIR/qt-downloader/$QT_VER/clang_64/bin:$BREW_BIN:$BREW_SBIN:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Library/Apple/usr/bin:$PATH" -export LDFLAGS="-L$BREW_ARM64_PATH/lib $BREW_ARM64_PATH/opt/ffmpeg@5/lib/libavcodec.dylib $BREW_ARM64_PATH/opt/ffmpeg@5/lib/libavformat.dylib $BREW_ARM64_PATH/opt/ffmpeg@5/lib/libavutil.dylib $BREW_ARM64_PATH/opt/ffmpeg@5/lib/libswscale.dylib $BREW_ARM64_PATH/opt/ffmpeg@5/lib/libswresample.dylib $BREW_ARM64_PATH/opt/llvm@$LLVM_COMPILER_VER/lib/c++/libc++.1.dylib $BREW_ARM64_PATH/lib/libSDL3.dylib $BREW_ARM64_PATH/lib/libGLEW.dylib $BREW_ARM64_PATH/opt/llvm@$LLVM_COMPILER_VER/lib/libunwind.1.dylib -Wl,-rpath,$BREW_ARM64_PATH/lib" -export CPPFLAGS="-I$BREW_ARM64_PATH/include -I$BREW_X64_PATH/include -no-pie -D__MAC_OS_X_VERSION_MIN_REQUIRED=140000" +export PATH="$BREW_PATH/opt/llvm@$LLVM_COMPILER_VER/bin:$WORKDIR/qt-downloader/$QT_VER/clang_64/bin:$BREW_BIN:$BREW_SBIN:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Library/Apple/usr/bin:$PATH" +export LDFLAGS="-L$BREW_PATH/lib $BREW_PATH/opt/ffmpeg@5/lib/libavcodec.dylib $BREW_PATH/opt/ffmpeg@5/lib/libavformat.dylib $BREW_PATH/opt/ffmpeg@5/lib/libavutil.dylib $BREW_PATH/opt/ffmpeg@5/lib/libswscale.dylib $BREW_PATH/opt/ffmpeg@5/lib/libswresample.dylib $BREW_PATH/opt/llvm@$LLVM_COMPILER_VER/lib/c++/libc++.1.dylib $BREW_PATH/lib/libSDL3.dylib $BREW_PATH/lib/libGLEW.dylib $BREW_PATH/opt/llvm@$LLVM_COMPILER_VER/lib/unwind/libunwind.1.dylib -Wl,-rpath,$BREW_PATH/lib" +export CPPFLAGS="-I$BREW_PATH/include -I$BREW_PATH/include -no-pie -D__MAC_OS_X_VERSION_MIN_REQUIRED=140000" export CFLAGS="-D__MAC_OS_X_VERSION_MIN_REQUIRED=140000" -export LIBRARY_PATH="$BREW_ARM64_PATH/lib" -export LD_LIBRARY_PATH="$BREW_ARM64_PATH/lib" +export LIBRARY_PATH="$BREW_PATH/lib" +export LD_LIBRARY_PATH="$BREW_PATH/lib" export VULKAN_SDK -VULKAN_SDK="$BREW_ARM64_PATH/opt/molten-vk" +VULKAN_SDK="$BREW_PATH/opt/molten-vk" ln -s "$VULKAN_SDK/lib/libMoltenVK.dylib" "$VULKAN_SDK/lib/libvulkan.dylib" || true export VK_ICD_FILENAMES="$VULKAN_SDK/share/vulkan/icd.d/MoltenVK_icd.json" export LLVM_DIR -LLVM_DIR="$BREW_ARM64_PATH/opt/llvm@$LLVM_COMPILER_VER" -# exclude ffmpeg, LLVM, and sdl from submodule update +LLVM_DIR="$BREW_PATH/opt/llvm@$LLVM_COMPILER_VER" +# exclude ffmpeg, LLVM, opencv, and sdl from submodule update # shellcheck disable=SC2046 -git submodule -q update --init --depth=1 --jobs=8 $(awk '/path/ && !/ffmpeg/ && !/llvm/ && !/SDL/ { print $3 }' .gitmodules) +git submodule -q update --init --depth=1 --jobs=8 $(awk '/path/ && !/ffmpeg/ && !/llvm/ && !/opencv/ && !/SDL/ { print $3 }' .gitmodules) # 3rdparty fixes sed -i '' "s/extern const double NSAppKitVersionNumber;/const double NSAppKitVersionNumber = 1343;/g" 3rdparty/hidapi/hidapi/mac/hid.c @@ -114,7 +76,7 @@ mkdir build && cd build || exit 1 export MACOSX_DEPLOYMENT_TARGET=14.0 -"$BREW_X64_PATH/bin/cmake" .. \ +"$BREW_PATH/bin/cmake" .. \ -DBUILD_RPCS3_TESTS=OFF \ -DRUN_RPCS3_TESTS=OFF \ -DUSE_SDL=ON \ @@ -139,13 +101,11 @@ export MACOSX_DEPLOYMENT_TARGET=14.0 -DUSE_SYSTEM_FAUDIO=OFF \ -DUSE_SYSTEM_SDL=ON \ -DUSE_SYSTEM_OPENCV=ON \ - $CMAKE_EXTRA_OPTS \ + "$CMAKE_EXTRA_OPTS" \ -DLLVM_TARGET_ARCH=arm64 \ -DCMAKE_OSX_ARCHITECTURES=arm64 \ - -DCMAKE_IGNORE_PATH="$BREW_X64_PATH/lib" \ - -DCMAKE_IGNORE_PREFIX_PATH=/usr/local/opt \ - -DCMAKE_SYSTEM_PROCESSOR=arm64 \ - -DCMAKE_TOOLCHAIN_FILE=buildfiles/cmake/TCDarwinARM64.cmake \ + -DCMAKE_IGNORE_PATH="$BREW_PATH/lib" \ + -DCMAKE_IGNORE_PREFIX_PATH=/opt/homebrew/opt \ -DCMAKE_CXX_FLAGS="-D__MAC_OS_X_VERSION_MIN_REQUIRED=140000" \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -DCMAKE_OSX_SYSROOT="$(xcrun --sdk macosx --show-sdk-path)" \ diff --git a/.ci/build-mac.sh b/.ci/build-mac.sh old mode 100644 new mode 100755 index 83ab07c1d9..5691512d69 --- a/.ci/build-mac.sh +++ b/.ci/build-mac.sh @@ -3,18 +3,16 @@ # shellcheck disable=SC2086 export HOMEBREW_NO_AUTO_UPDATE=1 export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 -brew unlink certifi -brew install -f --overwrite nasm ninja p7zip ccache pipenv #create-dmg +export HOMEBREW_NO_INSTALL_CLEANUP=1 #/usr/sbin/softwareupdate --install-rosetta --agree-to-license arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" arch -x86_64 /usr/local/bin/brew update arch -x86_64 /usr/local/bin/brew install -f --overwrite python || arch -x86_64 /usr/local/bin/brew link --overwrite python -arch -x86_64 /usr/local/bin/brew uninstall -f --ignore-dependencies ffmpeg -arch -x86_64 /usr/local/bin/brew install -f --build-from-source ffmpeg@5 -arch -x86_64 /usr/local/bin/brew reinstall -f --build-from-source gnutls freetype -arch -x86_64 /usr/local/bin/brew install llvm@$LLVM_COMPILER_VER glew cmake sdl3 vulkan-headers coreutils -arch -x86_64 /usr/local/bin/brew link -f llvm@$LLVM_COMPILER_VER ffmpeg@5 +arch -x86_64 /usr/local/bin/brew install -f --overwrite nasm ninja p7zip ccache pipenv gnutls freetype #create-dmg +arch -x86_64 /usr/local/bin/brew install -f ffmpeg@5 +arch -x86_64 /usr/local/bin/brew install "llvm@$LLVM_COMPILER_VER" glew cmake sdl3 vulkan-headers coreutils +arch -x86_64 /usr/local/bin/brew link -f "llvm@$LLVM_COMPILER_VER" ffmpeg@5 # moltenvk based on commit for 1.3.0 release wget https://raw.githubusercontent.com/Homebrew/homebrew-core/7255441cbcafabaa8950f67c7ec55ff499dbb2d3/Formula/m/molten-vk.rb @@ -22,8 +20,6 @@ arch -x86_64 /usr/local/bin/brew install -f --overwrite ./molten-vk.rb export CXX=clang++ export CC=clang -export BREW_PATH; -BREW_PATH="$(brew --prefix)" export BREW_X64_PATH; BREW_X64_PATH="$("/usr/local/bin/brew" --prefix)" export BREW_BIN="/usr/local/bin" @@ -42,11 +38,13 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then # nested Qt 6.9.0 URL workaround # sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader # sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader + # archived Qt 6.7.3 URL workaround + sed -i '' "s/official_releases/archive/g" qt-downloader cd "/tmp/Qt" - "$BREW_X64_PATH/bin/pipenv" run pip3 install py7zr requests semantic_version lxml + arch -x86_64 "$BREW_X64_PATH/bin/pipenv" --python "$BREW_X64_PATH/bin/python3" run pip3 install py7zr requests semantic_version lxml mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64" # sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.9.0 workaround - "$BREW_X64_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64" + arch -x86_64 "$BREW_X64_PATH/bin/pipenv" --python "$BREW_X64_PATH/bin/python3" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64" fi cd "$WORKDIR" @@ -76,6 +74,7 @@ git submodule -q update --init --depth=1 --jobs=8 $(awk '/path/ && !/ffmpeg/ && # 3rdparty fixes sed -i '' "s/extern const double NSAppKitVersionNumber;/const double NSAppKitVersionNumber = 1343;/g" 3rdparty/hidapi/hidapi/mac/hid.c +rm -rf build mkdir build && cd build || exit 1 export MACOSX_DEPLOYMENT_TARGET=14.0 @@ -105,16 +104,17 @@ export MACOSX_DEPLOYMENT_TARGET=14.0 -DUSE_SYSTEM_FAUDIO=OFF \ -DUSE_SYSTEM_SDL=ON \ -DUSE_SYSTEM_OPENCV=ON \ - $CMAKE_EXTRA_OPTS \ + "$CMAKE_EXTRA_OPTS" \ -DLLVM_TARGET_ARCH=X86_64 \ -DCMAKE_OSX_ARCHITECTURES=x86_64 \ - -DCMAKE_IGNORE_PATH="$BREW_PATH/lib" \ + -DCMAKE_IGNORE_PATH="$BREW_X64_PATH/lib" \ + -DCMAKE_IGNORE_PREFIX_PATH=/usr/local/opt \ -DCMAKE_CXX_FLAGS="-D__MAC_OS_X_VERSION_MIN_REQUIRED=140000" \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -DCMAKE_OSX_SYSROOT="$(xcrun --sdk macosx --show-sdk-path)" \ -G Ninja -"$BREW_PATH/bin/ninja"; build_status=$?; +"$BREW_X64_PATH/bin/ninja"; build_status=$?; cd .. diff --git a/.ci/deploy-mac-arm64.sh b/.ci/deploy-mac-arm64.sh old mode 100644 new mode 100755 index da1fbe9165..e7de472378 --- a/.ci/deploy-mac-arm64.sh +++ b/.ci/deploy-mac-arm64.sh @@ -16,9 +16,9 @@ echo "AVVER=$AVVER" >> ../.ci/ci-vars.env cd bin mkdir "rpcs3.app/Contents/lib/" || true -cp "$(realpath /opt/homebrew1/opt/llvm@$LLVM_COMPILER_VER/lib/c++/libc++abi.1.0.dylib)" "rpcs3.app/Contents/Frameworks/libc++abi.1.dylib" -cp "$(realpath /opt/homebrew1/lib/libsharpyuv.0.dylib)" "rpcs3.app/Contents/lib/libsharpyuv.0.dylib" -cp "$(realpath /opt/homebrew1/lib/libintl.8.dylib)" "rpcs3.app/Contents/lib/libintl.8.dylib" +cp "$(realpath /opt/homebrew/opt/llvm@$LLVM_COMPILER_VER/lib/c++/libc++abi.1.0.dylib)" "rpcs3.app/Contents/Frameworks/libc++abi.1.dylib" +cp "$(realpath /opt/homebrew/lib/libsharpyuv.0.dylib)" "rpcs3.app/Contents/lib/libsharpyuv.0.dylib" +cp "$(realpath /opt/homebrew/lib/libintl.8.dylib)" "rpcs3.app/Contents/lib/libintl.8.dylib" rm -rf "rpcs3.app/Contents/Frameworks/QtPdf.framework" \ "rpcs3.app/Contents/Frameworks/QtQml.framework" \ @@ -33,10 +33,8 @@ rm -rf "rpcs3.app/Contents/Frameworks/QtPdf.framework" \ # Hack install_name_tool \ --delete_rpath /opt/homebrew1/lib \ -delete_rpath /opt/homebrew/lib \ --delete_rpath /opt/homebrew1/opt/llvm@$LLVM_COMPILER_VER/lib \ --delete_rpath /usr/local/lib RPCS3.app/Contents/MacOS/rpcs3 +-delete_rpath /opt/homebrew/opt/llvm@$LLVM_COMPILER_VER/lib RPCS3.app/Contents/MacOS/rpcs3 #-delete_rpath /opt/homebrew1/Cellar/sdl3/3.2.8/lib # Need to do this rename hack due to case insensitive filesystem @@ -67,7 +65,7 @@ echo "IconIndex=0" >> Quickstart.url #SHA256SUM=$(shasum -a 256 "$DMG_FILEPATH" | awk '{ print $1 }') ARCHIVE_FILEPATH="$BUILD_ARTIFACTSTAGINGDIRECTORY/rpcs3-v${COMM_TAG}-${COMM_COUNT}-${COMM_HASH}_macos_arm64.7z" -"$BREW_X64_PATH/bin/7z" a -mx9 "$ARCHIVE_FILEPATH" RPCS3.app Quickstart.url +"$BREW_PATH/bin/7z" a -mx9 "$ARCHIVE_FILEPATH" RPCS3.app Quickstart.url FILESIZE=$(stat -f %z "$ARCHIVE_FILEPATH") SHA256SUM=$(shasum -a 256 "$ARCHIVE_FILEPATH" | awk '{ print $1 }') diff --git a/.ci/deploy-mac.sh b/.ci/deploy-mac.sh old mode 100644 new mode 100755 diff --git a/.ci/export-cirrus-vars.sh b/.ci/export-cirrus-vars.sh old mode 100644 new mode 100755 diff --git a/.ci/get_keys-windows.sh b/.ci/get_keys-windows.sh old mode 100644 new mode 100755 diff --git a/.ci/optimize-mac.sh b/.ci/optimize-mac.sh old mode 100644 new mode 100755 diff --git a/.github/workflows/rpcs3.yml b/.github/workflows/rpcs3.yml index f09655cb76..55b8c09aa6 100644 --- a/.github/workflows/rpcs3.yml +++ b/.github/workflows/rpcs3.yml @@ -104,6 +104,83 @@ jobs: export AVVER="${COMM_TAG}-${COMM_COUNT}" .ci/github-upload.sh + Mac_Build: + # Only run push event on master branch of main repo, but run all PRs + if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master') + strategy: + fail-fast: false + matrix: + include: + - name: Intel + build_sh: "arch -X86_64 .ci/build-mac.sh" + UPLOAD_COMMIT_HASH: 8e21bdbc40711a3fccd18fbf17b742348b0f4281 + UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-mac" + - name: Apple Silicon + build_sh: ".ci/build-mac-arm64.sh" + UPLOAD_COMMIT_HASH: 51ae32f468089a8169aaf1567de355ff4a3e0842 + UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-mac-arm64" + name: RPCS3 Mac ${{ matrix.name }} + runs-on: macos-14 + env: + CCACHE_DIR: "/tmp/ccache_dir" + CI_HAS_ARTIFACTS: true + QT_VER: '6.7.3' + QT_VER_MAIN: '6' + LLVM_COMPILER_VER: '19' + RELEASE_MESSAGE: "../GitHubReleaseMessage.txt" + UPLOAD_COMMIT_HASH: ${{ matrix.UPLOAD_COMMIT_HASH }} + UPLOAD_REPO_FULL_NAME: ${{ matrix.UPLOAD_REPO_FULL_NAME }} + steps: + - name: Checkout repository + uses: actions/checkout@main + with: + fetch-depth: 0 + + - name: Setup Cache + uses: actions/cache@main + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ runner.os }}-ccache-${{ matrix.name }}-${{github.run_id}} + restore-keys: | + ${{ runner.os }}-ccache-${{ matrix.name }}- + + - name: Setup Qt Cache + uses: actions/cache@main + with: + path: "/tmp/Qt" + key: ${{ runner.os }}-qt-${{ matrix.name }}-${{ env.QT_VER }} + restore-keys: | + ${{ runner.os }}-qt-${{ matrix.name }}-${{ env.QT_VER }} + + - name: Build + run: | + ${{ matrix.build_sh }} + + - name: Upload artifacts + uses: actions/upload-artifact@main + with: + name: RPCS3 for Mac (${{ matrix.name }}) + path: ${{ env.BUILD_ARTIFACTSTAGINGDIRECTORY }} + compression-level: 0 + + - name: Export Variables + run: | + while IFS='=' read -r key val; do + # Skip lines that are empty or start with '#' + [[ -z "$key" || "$key" =~ ^# ]] && continue + echo "$key=$val" >> "${{ github.env }}" + done < .ci/ci-vars.env + + - name: Deploy master build to GitHub Releases + if: | + github.event_name != 'pull_request' && + github.repository == 'RPCS3/rpcs3' && + github.ref == 'refs/heads/master' + env: + RPCS3_TOKEN: ${{ secrets.RPCS3_TOKEN }} + run: | + .ci/github-upload.sh + Windows_Build: # Only run push event on master branch of main repo, but run all PRs if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master') diff --git a/README.md b/README.md index c47af8d204..fb49b2dc01 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ RPCS3 ===== -[![Azure Build Status](https://dev.azure.com/nekotekina/nekotekina/_apis/build/status/RPCS3.rpcs3?branchName=master)](https://dev.azure.com/nekotekina/nekotekina/_build?definitionId=8&_a=summary&repositoryFilter=4) [![Cirrus CI - Base Branch Build Status](https://img.shields.io/cirrus/github/RPCS3/rpcs3/master?label=Cirrus%20CI&logo=cirrus-ci)](https://cirrus-ci.com/github/RPCS3/rpcs3) [![GitHub Actions](https://img.shields.io/github/actions/workflow/status/RPCS3/rpcs3/rpcs3.yml?branch=master&logo=github&label=Actions)](https://github.com/RPCS3/rpcs3/actions/workflows/rpcs3.yml) [![RPCS3 Discord Server](https://img.shields.io/discord/272035812277878785?color=5865F2&label=RPCS3%20Discord&logo=discord&logoColor=white)](https://discord.gg/rpcs3) diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 97970a521d..0000000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,260 +0,0 @@ -trigger: - branches: - include: - - master - tags: - exclude: - - '*' -pr: - branches: - include: - - master -jobs: -# - job: Linux_Build -# strategy: -# matrix: -# Clang: -# COMPILER: clang -# GCC: -# COMPILER: gcc -# variables: -# CCACHE_DIR: $(Pipeline.Workspace)/ccache -# CI_HAS_ARTIFACTS: true -# UPLOAD_COMMIT_HASH: d812f1254a1157c80fd402f94446310560f54e5f -# UPLOAD_REPO_FULL_NAME: "RPCS3/rpcs3-binaries-linux" -# DEPLOY_APPIMAGE: true -# APPDIR: "/rpcs3/build/appdir" -# ARTDIR: "/root/artifacts" -# RELEASE_MESSAGE: "/rpcs3/GitHubReleaseMessage.txt" - -# pool: -# vmImage: 'ubuntu-latest' - -# steps: -# - task: Cache@2 -# inputs: -# key: ccache | $(Agent.OS) | $(COMPILER) | $(Build.SourceVersion) -# restoreKeys: | -# ccache | $(Agent.OS) | $(COMPILER) -# path: $(CCACHE_DIR) -# displayName: ccache - -# - bash: | -# docker pull --quiet rpcs3/rpcs3-ci-jammy:1.6 -# docker run \ -# -v $(pwd):/rpcs3 \ -# --env-file .ci/docker.env \ -# -v $CCACHE_DIR:/root/.ccache \ -# -v $BUILD_ARTIFACTSTAGINGDIRECTORY:/root/artifacts \ -# rpcs3/rpcs3-ci-jammy:1.6 \ -# /rpcs3/.ci/build-linux.sh -# displayName: Docker setup and build - -# - publish: $(Build.ArtifactStagingDirectory) -# condition: succeeded() -# artifact: RPCS3 for Linux ($(COMPILER)) - -# - bash: | -# COMM_TAG=$(awk '/version{.*}/ { printf("%d.%d.%d", $5, $6, $7) }' ./rpcs3/rpcs3_version.cpp) -# COMM_COUNT=$(git rev-list --count HEAD) -# COMM_HASH=$(git rev-parse --short=8 HEAD) - -# export AVVER="${COMM_TAG}-${COMM_COUNT}" - -# .ci/github-upload.sh -# condition: and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.Repository.Name'], 'RPCS3/rpcs3'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq(variables['COMPILER'], 'clang')) -# displayName: Push build to GitHub -# env: -# RPCS3_TOKEN: $(RPCS3-Token) - -# - job: Windows_Build -# variables: -# COMPILER: msvc -# QT_VER_MAIN: '6' -# QT_VER: '6.9.0' -# QT_VER_MSVC: 'msvc2022' -# QT_DATE: '202503301022' -# QTDIR: C:\Qt\$(QT_VER)\$(QT_VER_MSVC)_64 -# LLVM_VER: '19.1.7' -# VULKAN_VER: '1.3.268.0' -# VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5' -# VULKAN_SDK: C:\VulkanSDK\$(VULKAN_VER) -# CCACHE_SHA: '6252f081876a9a9f700fae13a5aec5d0d486b28261d7f1f72ac11c7ad9df4da9' -# CCACHE_BIN_DIR: 'C:\ccache_bin' -# CCACHE_DIR: 'C:\ccache' -# CCACHE_INODECACHE: 'true' -# CCACHE_SLOPPINESS: 'time_macros' -# DEPS_CACHE_DIR: ./dependency_cache -# UPLOAD_COMMIT_HASH: 7d09e3be30805911226241afbb14f8cdc2eb054e -# UPLOAD_REPO_FULL_NAME: "RPCS3/rpcs3-binaries-win" - -# pool: -# vmImage: "windows-latest" - -# steps: -# - bash: .ci/get_keys-windows.sh -# displayName: Get Cache Keys - -# - task: Cache@2 -# inputs: -# key: ccache | $(Agent.OS) | $(COMPILER) | "$(Build.SourceVersion)" -# path: $(CCACHE_DIR) -# restoreKeys: -# ccache | $(Agent.OS) | $(COMPILER) -# displayName: Build Ccache - -# - task: Cache@2 -# inputs: -# key: $(Agent.OS) | $(COMPILER) | "$(QT_VER)" | $(VULKAN_SDK_SHA) | $(CCACHE_SHA) | llvm.lock -# path: $(DEPS_CACHE_DIR) -# displayName: Dependencies Cache - -# - bash: .ci/setup-windows.sh -# displayName: Download and unpack dependencies - -# - bash: .ci/export-azure-vars.sh -# displayName: Export Variables - -# - task: VSBuild@1 -# inputs: -# solution: 'rpcs3.sln' -# maximumCpuCount: true -# platform: x64 -# configuration: 'Release' -# msbuildArgs: /p:CLToolPath=$(CCACHE_BIN_DIR) /p:UseMultiToolTask=true /p:CustomAfterMicrosoftCommonTargets="$(Build.SourcesDirectory)\buildfiles\msvc\ci_only.targets" -# displayName: Compile RPCS3 - -# - bash: .ci/deploy-windows.sh -# displayName: Pack up build artifacts - -# - publish: $(Build.ArtifactStagingDirectory) -# condition: succeeded() -# artifact: RPCS3 for Windows - -# - bash: .ci/github-upload.sh -# condition: and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.Repository.Name'], 'RPCS3/rpcs3'), eq(variables['Build.SourceBranch'], 'refs/heads/master')) -# displayName: Push build to GitHub -# env: -# RPCS3_TOKEN: $(RPCS3-Token) - -- job: Mac_Build_x86_64 - timeoutInMinutes: 180 - variables: - CCACHE_DIR: "/tmp/ccache_dir" - CCACHE_MAXSIZE: 300M - CI_HAS_ARTIFACTS: true - UPLOAD_COMMIT_HASH: 51ae32f468089a8169aaf1567de355ff4a3e0842 - UPLOAD_REPO_FULL_NAME: "RPCS3/rpcs3-binaries-mac" - RELEASE_MESSAGE: "../GitHubReleaseMessage.txt" - ARTDIR: $(Build.ArtifactStagingDirectory) - QT_VER: '6.7.3' - QT_VER_MAIN: '6' - LLVM_COMPILER_VER: '19' - - pool: - vmImage: "macOS-14" - - steps: - - task: Cache@2 - inputs: - key: ccache | "$(Agent.OS)" | "$(Agent.OSArchitecture)" | "$(Build.SourceVersion)" - path: $(CCACHE_DIR) - restoreKeys: | - ccache | "$(Agent.OS)" | "$(Agent.OSArchitecture)" - displayName: Ccache cache - - - task: Cache@2 - inputs: - key: qt | "$(Agent.OS)" | "$(Agent.OSArchitecture)" | "$(QT_VER)" - path: /tmp/Qt - restoreKeys: | - qt | "$(Agent.OS)" | "$(Agent.OSArchitecture)" | "$(QT_VER)" - displayName: Qt cache - - # - task: Cache@2 - # inputs: - # key: brew | "$(Agent.OS)" - # path: /Users/runner/Library/Caches/Homebrew - # restoreKeys: | - # brew | "$(Agent.OS)" - # displayName: Homebrew cache - - - bash: | - chmod +x ".ci/build-mac.sh" - chmod +x ".ci/deploy-mac.sh" - chmod +x ".ci/optimize-mac.sh" - ".ci/build-mac.sh" - displayName: Build macOS (x86_64) - - - publish: $(Build.ArtifactStagingDirectory) - condition: succeeded() - artifact: RPCS3 for Mac (Intel) - - - bash: | - source './.ci/export-cirrus-vars.sh' - .ci/github-upload.sh - condition: and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.Repository.Name'], 'RPCS3/rpcs3'), eq(variables['Build.SourceBranch'], 'refs/heads/master')) - displayName: Push build to GitHub - env: - RPCS3_TOKEN: $(RPCS3-Token) - -- job: Mac_Build_arm64 - timeoutInMinutes: 180 - variables: - CCACHE_DIR: "/tmp/ccache_dir" - CCACHE_MAXSIZE: 300M - CI_HAS_ARTIFACTS: true - UPLOAD_COMMIT_HASH: 8e21bdbc40711a3fccd18fbf17b742348b0f4281 - UPLOAD_REPO_FULL_NAME: "RPCS3/rpcs3-binaries-mac-arm64" - RELEASE_MESSAGE: "../GitHubReleaseMessage.txt" - ARTDIR: $(Build.ArtifactStagingDirectory) - QT_VER: '6.7.3' - QT_VER_MAIN: '6' - LLVM_COMPILER_VER: '19' - - pool: - vmImage: "macOS-14" - - steps: - - task: Cache@2 - inputs: - key: ccache | "$(Agent.OS)" | "$(Agent.OSArchitecture)" | "$(Build.SourceVersion)" - path: $(CCACHE_DIR) - restoreKeys: | - ccache | "$(Agent.OS)" | "$(Agent.OSArchitecture)" - displayName: Ccache cache - - - task: Cache@2 - inputs: - key: qt | "$(Agent.OS)" | "$(Agent.OSArchitecture)" | "$(QT_VER)" - path: /tmp/Qt - restoreKeys: | - qt | "$(Agent.OS)" | "$(Agent.OSArchitecture)" | "$(QT_VER)" - displayName: Qt cache - - # - task: Cache@2 - # inputs: - # key: brew | "$(Agent.OS)" - # path: /Users/runner/Library/Caches/Homebrew - # restoreKeys: | - # brew | "$(Agent.OS)" - # displayName: Homebrew cache - - - bash: | - chmod +x ".ci/build-mac-arm64.sh" - chmod +x ".ci/deploy-mac-arm64.sh" - chmod +x ".ci/optimize-mac.sh" - ".ci/build-mac-arm64.sh" - displayName: Build macOS (arm64) - - - publish: $(Build.ArtifactStagingDirectory) - condition: succeeded() - artifact: RPCS3 for Mac (Apple Silicon) - - - bash: | - source './.ci/export-cirrus-vars.sh' - .ci/github-upload.sh - condition: and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.Repository.Name'], 'RPCS3/rpcs3'), eq(variables['Build.SourceBranch'], 'refs/heads/master')) - displayName: Push build to GitHub - env: - RPCS3_TOKEN: $(RPCS3-Token) diff --git a/buildfiles/cmake/TCDarwinARM64.cmake b/buildfiles/cmake/TCDarwinARM64.cmake deleted file mode 100644 index d38b237910..0000000000 --- a/buildfiles/cmake/TCDarwinARM64.cmake +++ /dev/null @@ -1,2 +0,0 @@ -set(CMAKE_SYSTEM_NAME Darwin) -set(CMAKE_SYSTEM_PROCESSOR arm64) diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 50ff807e12..863904af22 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -2130,7 +2130,6 @@ - @@ -2138,7 +2137,6 @@ - diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 2e344fa2ca..da1b92047d 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -1809,9 +1809,6 @@ CI - - CI - CI @@ -1830,9 +1827,6 @@ CI - - CI - CI From aeafbfa2e1c2f19d7ca56a36bd6375d7c7b2e039 Mon Sep 17 00:00:00 2001 From: schm1dtmac Date: Sat, 31 May 2025 14:49:36 +0100 Subject: [PATCH 020/384] Silence warnings --- .ci/build-mac-arm64.sh | 10 +++++----- .ci/build-mac.sh | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.ci/build-mac-arm64.sh b/.ci/build-mac-arm64.sh index e30b5487bf..ece51024ab 100755 --- a/.ci/build-mac-arm64.sh +++ b/.ci/build-mac-arm64.sh @@ -5,14 +5,14 @@ export HOMEBREW_NO_AUTO_UPDATE=1 export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 export HOMEBREW_NO_INSTALL_CLEANUP=1 -/opt/homebrew/bin/brew install -f --overwrite nasm ninja p7zip ccache pipenv gnutls freetype #create-dmg -/opt/homebrew/bin/brew install -f ffmpeg@5 -/opt/homebrew/bin/brew install "llvm@$LLVM_COMPILER_VER" glew cmake sdl3 vulkan-headers coreutils -/opt/homebrew/bin/brew link -f "llvm@$LLVM_COMPILER_VER" ffmpeg@5 +/opt/homebrew/bin/brew install -f --overwrite --quiet nasm ninja p7zip ccache pipenv gnutls freetype #create-dmg +/opt/homebrew/bin/brew install -f --quiet ffmpeg@5 +/opt/homebrew/bin/brew install --quiet "llvm@$LLVM_COMPILER_VER" glew cmake sdl3 vulkan-headers coreutils +/opt/homebrew/bin/brew link -f --quiet "llvm@$LLVM_COMPILER_VER" ffmpeg@5 # moltenvk based on commit for 1.3.0 release wget https://raw.githubusercontent.com/Homebrew/homebrew-core/7255441cbcafabaa8950f67c7ec55ff499dbb2d3/Formula/m/molten-vk.rb -/opt/homebrew/bin/brew install -f --overwrite ./molten-vk.rb +/opt/homebrew/bin/brew install -f --overwrite --formula --quiet ./molten-vk.rb export CXX=clang++ export CC=clang diff --git a/.ci/build-mac.sh b/.ci/build-mac.sh index 5691512d69..66b84089a6 100755 --- a/.ci/build-mac.sh +++ b/.ci/build-mac.sh @@ -8,15 +8,15 @@ export HOMEBREW_NO_INSTALL_CLEANUP=1 #/usr/sbin/softwareupdate --install-rosetta --agree-to-license arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" arch -x86_64 /usr/local/bin/brew update -arch -x86_64 /usr/local/bin/brew install -f --overwrite python || arch -x86_64 /usr/local/bin/brew link --overwrite python -arch -x86_64 /usr/local/bin/brew install -f --overwrite nasm ninja p7zip ccache pipenv gnutls freetype #create-dmg -arch -x86_64 /usr/local/bin/brew install -f ffmpeg@5 -arch -x86_64 /usr/local/bin/brew install "llvm@$LLVM_COMPILER_VER" glew cmake sdl3 vulkan-headers coreutils -arch -x86_64 /usr/local/bin/brew link -f "llvm@$LLVM_COMPILER_VER" ffmpeg@5 +arch -x86_64 /usr/local/bin/brew install -f --overwrite --quiet python || arch -x86_64 /usr/local/bin/brew link --overwrite python +arch -x86_64 /usr/local/bin/brew install -f --overwrite --quiet nasm ninja p7zip ccache pipenv gnutls freetype #create-dmg +arch -x86_64 /usr/local/bin/brew install -f --quiet ffmpeg@5 +arch -x86_64 /usr/local/bin/brew install --quiet "llvm@$LLVM_COMPILER_VER" glew cmake sdl3 vulkan-headers coreutils +arch -x86_64 /usr/local/bin/brew link -f --quiet "llvm@$LLVM_COMPILER_VER" ffmpeg@5 # moltenvk based on commit for 1.3.0 release wget https://raw.githubusercontent.com/Homebrew/homebrew-core/7255441cbcafabaa8950f67c7ec55ff499dbb2d3/Formula/m/molten-vk.rb -arch -x86_64 /usr/local/bin/brew install -f --overwrite ./molten-vk.rb +arch -x86_64 /usr/local/bin/brew install -f --overwrite --formula --quiet ./molten-vk.rb export CXX=clang++ export CC=clang From 55aaffb7b326411e93d83cb923e0c48e17415f09 Mon Sep 17 00:00:00 2001 From: schm1dtmac Date: Sat, 31 May 2025 15:47:17 +0100 Subject: [PATCH 021/384] Readd Homebrew Cache (used to be on Cirrus), silence more warnings --- .ci/build-mac-arm64.sh | 1 + .ci/build-mac.sh | 1 + .github/workflows/rpcs3.yml | 8 ++++++++ 3 files changed, 10 insertions(+) diff --git a/.ci/build-mac-arm64.sh b/.ci/build-mac-arm64.sh index ece51024ab..631aca0ecc 100755 --- a/.ci/build-mac-arm64.sh +++ b/.ci/build-mac-arm64.sh @@ -3,6 +3,7 @@ # shellcheck disable=SC2086 export HOMEBREW_NO_AUTO_UPDATE=1 export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 +export HOMEBREW_NO_ENV_HINTS=1 export HOMEBREW_NO_INSTALL_CLEANUP=1 /opt/homebrew/bin/brew install -f --overwrite --quiet nasm ninja p7zip ccache pipenv gnutls freetype #create-dmg diff --git a/.ci/build-mac.sh b/.ci/build-mac.sh index 66b84089a6..316d845b9a 100755 --- a/.ci/build-mac.sh +++ b/.ci/build-mac.sh @@ -3,6 +3,7 @@ # shellcheck disable=SC2086 export HOMEBREW_NO_AUTO_UPDATE=1 export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 +export HOMEBREW_NO_ENV_HINTS=1 export HOMEBREW_NO_INSTALL_CLEANUP=1 #/usr/sbin/softwareupdate --install-rosetta --agree-to-license diff --git a/.github/workflows/rpcs3.yml b/.github/workflows/rpcs3.yml index 55b8c09aa6..b351c20c83 100644 --- a/.github/workflows/rpcs3.yml +++ b/.github/workflows/rpcs3.yml @@ -144,6 +144,14 @@ jobs: restore-keys: | ${{ runner.os }}-ccache-${{ matrix.name }}- + - name: Setup Homebrew Cache + uses: actions/cache@main + with: + path: "~/Library/Caches/Homebrew" + key: ${{ runner.os }}-homebrew-${{ matrix.name }} + restore-keys: | + ${{ runner.os }}-homebrew-${{ matrix.name }} + - name: Setup Qt Cache uses: actions/cache@main with: From 0f45c08188aa99357b97405b7b0ca44d9139c5bc Mon Sep 17 00:00:00 2001 From: schm1dtmac Date: Sat, 31 May 2025 18:40:12 +0100 Subject: [PATCH 022/384] Suggested review changes --- .ci/build-mac-arm64.sh | 1 - .ci/build-mac.sh | 1 - .github/workflows/rpcs3.yml | 32 +++++++++++--------------------- .vscode/settings.json | 3 +++ 4 files changed, 14 insertions(+), 23 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.ci/build-mac-arm64.sh b/.ci/build-mac-arm64.sh index 631aca0ecc..d1b48c03f9 100755 --- a/.ci/build-mac-arm64.sh +++ b/.ci/build-mac-arm64.sh @@ -72,7 +72,6 @@ git submodule -q update --init --depth=1 --jobs=8 $(awk '/path/ && !/ffmpeg/ && # 3rdparty fixes sed -i '' "s/extern const double NSAppKitVersionNumber;/const double NSAppKitVersionNumber = 1343;/g" 3rdparty/hidapi/hidapi/mac/hid.c -rm -rf build mkdir build && cd build || exit 1 export MACOSX_DEPLOYMENT_TARGET=14.0 diff --git a/.ci/build-mac.sh b/.ci/build-mac.sh index 316d845b9a..675811539e 100755 --- a/.ci/build-mac.sh +++ b/.ci/build-mac.sh @@ -75,7 +75,6 @@ git submodule -q update --init --depth=1 --jobs=8 $(awk '/path/ && !/ffmpeg/ && # 3rdparty fixes sed -i '' "s/extern const double NSAppKitVersionNumber;/const double NSAppKitVersionNumber = 1343;/g" 3rdparty/hidapi/hidapi/mac/hid.c -rm -rf build mkdir build && cd build || exit 1 export MACOSX_DEPLOYMENT_TARGET=14.0 diff --git a/.github/workflows/rpcs3.yml b/.github/workflows/rpcs3.yml index b351c20c83..e2b430701e 100644 --- a/.github/workflows/rpcs3.yml +++ b/.github/workflows/rpcs3.yml @@ -114,20 +114,20 @@ jobs: - name: Intel build_sh: "arch -X86_64 .ci/build-mac.sh" UPLOAD_COMMIT_HASH: 8e21bdbc40711a3fccd18fbf17b742348b0f4281 - UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-mac" + UPLOAD_REPO_FULL_NAME: rpcs3/rpcs3-binaries-mac - name: Apple Silicon - build_sh: ".ci/build-mac-arm64.sh" + build_sh: .ci/build-mac-arm64.sh UPLOAD_COMMIT_HASH: 51ae32f468089a8169aaf1567de355ff4a3e0842 - UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-mac-arm64" + UPLOAD_REPO_FULL_NAME: rpcs3/rpcs3-binaries-mac-arm64 name: RPCS3 Mac ${{ matrix.name }} runs-on: macos-14 env: - CCACHE_DIR: "/tmp/ccache_dir" + CCACHE_DIR: /tmp/ccache_dir CI_HAS_ARTIFACTS: true QT_VER: '6.7.3' QT_VER_MAIN: '6' LLVM_COMPILER_VER: '19' - RELEASE_MESSAGE: "../GitHubReleaseMessage.txt" + RELEASE_MESSAGE: ../GitHubReleaseMessage.txt UPLOAD_COMMIT_HASH: ${{ matrix.UPLOAD_COMMIT_HASH }} UPLOAD_REPO_FULL_NAME: ${{ matrix.UPLOAD_REPO_FULL_NAME }} steps: @@ -141,28 +141,19 @@ jobs: with: path: ${{ env.CCACHE_DIR }} key: ${{ runner.os }}-ccache-${{ matrix.name }}-${{github.run_id}} - restore-keys: | + restore-keys: | ${{ runner.os }}-ccache-${{ matrix.name }}- - - name: Setup Homebrew Cache - uses: actions/cache@main - with: - path: "~/Library/Caches/Homebrew" - key: ${{ runner.os }}-homebrew-${{ matrix.name }} - restore-keys: | - ${{ runner.os }}-homebrew-${{ matrix.name }} - - name: Setup Qt Cache uses: actions/cache@main with: - path: "/tmp/Qt" + path: /tmp/Qt key: ${{ runner.os }}-qt-${{ matrix.name }}-${{ env.QT_VER }} - restore-keys: | + restore-keys: | ${{ runner.os }}-qt-${{ matrix.name }}-${{ env.QT_VER }} - name: Build - run: | - ${{ matrix.build_sh }} + run: ${{ matrix.build_sh }} - name: Upload artifacts uses: actions/upload-artifact@main @@ -183,11 +174,10 @@ jobs: if: | github.event_name != 'pull_request' && github.repository == 'RPCS3/rpcs3' && - github.ref == 'refs/heads/master' + github.ref == 'refs/heads/master' env: RPCS3_TOKEN: ${{ secrets.RPCS3_TOKEN }} - run: | - .ci/github-upload.sh + run: .ci/github-upload.sh Windows_Build: # Only run push event on master branch of main repo, but run all PRs diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..cddac42ba3 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.codeLens": false +} \ No newline at end of file From c93ee3dc1aa684d95868a9c8164701131373df79 Mon Sep 17 00:00:00 2001 From: schm1dtmac Date: Sat, 31 May 2025 18:41:54 +0100 Subject: [PATCH 023/384] thanks vscode --- .vscode/settings.json | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index cddac42ba3..0000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "editor.codeLens": false -} \ No newline at end of file From c437fe9ff052f69c3d151a98e22cd77d3d9e013e Mon Sep 17 00:00:00 2001 From: Zion Nimchuk Date: Sat, 31 May 2025 11:54:02 -0700 Subject: [PATCH 024/384] Fixing the two upload commit hashes got switched around --- .github/workflows/rpcs3.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rpcs3.yml b/.github/workflows/rpcs3.yml index e2b430701e..afafbc2e20 100644 --- a/.github/workflows/rpcs3.yml +++ b/.github/workflows/rpcs3.yml @@ -113,11 +113,11 @@ jobs: include: - name: Intel build_sh: "arch -X86_64 .ci/build-mac.sh" - UPLOAD_COMMIT_HASH: 8e21bdbc40711a3fccd18fbf17b742348b0f4281 + UPLOAD_COMMIT_HASH: 51ae32f468089a8169aaf1567de355ff4a3e0842 UPLOAD_REPO_FULL_NAME: rpcs3/rpcs3-binaries-mac - name: Apple Silicon build_sh: .ci/build-mac-arm64.sh - UPLOAD_COMMIT_HASH: 51ae32f468089a8169aaf1567de355ff4a3e0842 + UPLOAD_COMMIT_HASH: 8e21bdbc40711a3fccd18fbf17b742348b0f4281 UPLOAD_REPO_FULL_NAME: rpcs3/rpcs3-binaries-mac-arm64 name: RPCS3 Mac ${{ matrix.name }} runs-on: macos-14 From 68d25733443297c892b956fff8cd3e7c38c3744e Mon Sep 17 00:00:00 2001 From: Ani Date: Sat, 31 May 2025 22:09:54 +0200 Subject: [PATCH 025/384] rpcs3_version: Bump to 0.0.37 --- rpcs3/rpcs3_version.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/rpcs3_version.cpp b/rpcs3/rpcs3_version.cpp index df428e93de..f78cec9234 100644 --- a/rpcs3/rpcs3_version.cpp +++ b/rpcs3/rpcs3_version.cpp @@ -28,7 +28,7 @@ namespace rpcs3 // Currently accessible by Windows and Linux build scripts, see implementations when doing MACOSX const utils::version& get_version() { - static constexpr utils::version version{ 0, 0, 36, utils::version_type::alpha, 1, RPCS3_GIT_VERSION }; + static constexpr utils::version version{ 0, 0, 37, utils::version_type::alpha, 1, RPCS3_GIT_VERSION }; return version; } From 229c1c38a3fc4fcb5ff24420b6aa1dfd6422d3d9 Mon Sep 17 00:00:00 2001 From: Zion Nimchuk Date: Sat, 31 May 2025 15:14:19 -0700 Subject: [PATCH 026/384] Setup build caches to only save on master builds, to ensure PR caches don't take presidence --- .github/workflows/rpcs3.yml | 69 ++++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 16 deletions(-) diff --git a/.github/workflows/rpcs3.yml b/.github/workflows/rpcs3.yml index afafbc2e20..2d7f0a8282 100644 --- a/.github/workflows/rpcs3.yml +++ b/.github/workflows/rpcs3.yml @@ -63,13 +63,13 @@ jobs: with: fetch-depth: 0 - - name: Setup Cache - uses: actions/cache@main + - name: Restore build Ccache + uses: actions/cache/restore@main + id: restore-build-ccache with: path: ${{ env.CCACHE_DIR }} key: ${{ runner.os }}-ccache-${{ matrix.compiler }}-${{ runner.arch }}-${{github.run_id}} - restore-keys: | - ${{ runner.os }}-ccache-${{ matrix.compiler }}-${{ runner.arch }}- + restore-keys: ${{ runner.os }}-ccache-${{ matrix.compiler }}-${{ runner.arch }}- - name: Docker setup and build run: | @@ -103,6 +103,13 @@ jobs: COMM_HASH=$(git rev-parse --short=8 HEAD) export AVVER="${COMM_TAG}-${COMM_COUNT}" .ci/github-upload.sh + + - name: Save build Ccache + if: github.ref == 'refs/heads/master' + uses: actions/cache/save@main + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.restore-build-ccache.outputs.cache-primary-key }} Mac_Build: # Only run push event on master branch of main repo, but run all PRs @@ -136,21 +143,21 @@ jobs: with: fetch-depth: 0 - - name: Setup Cache - uses: actions/cache@main + - name: Restore Build Ccache + uses: actions/cache/restore@main + id: restore-build-ccache with: path: ${{ env.CCACHE_DIR }} key: ${{ runner.os }}-ccache-${{ matrix.name }}-${{github.run_id}} - restore-keys: | - ${{ runner.os }}-ccache-${{ matrix.name }}- + restore-keys: ${{ runner.os }}-ccache-${{ matrix.name }}- - - name: Setup Qt Cache - uses: actions/cache@main + - name: Restore Qt Cache + uses: actions/cache/restore@main + id: restore-qt-cache with: path: /tmp/Qt key: ${{ runner.os }}-qt-${{ matrix.name }}-${{ env.QT_VER }} - restore-keys: | - ${{ runner.os }}-qt-${{ matrix.name }}-${{ env.QT_VER }} + restore-keys: ${{ runner.os }}-qt-${{ matrix.name }}-${{ env.QT_VER }} - name: Build run: ${{ matrix.build_sh }} @@ -178,6 +185,20 @@ jobs: env: RPCS3_TOKEN: ${{ secrets.RPCS3_TOKEN }} run: .ci/github-upload.sh + + - name: Save Build Ccache + if: github.ref == 'refs/heads/master' + uses: actions/cache/save@main + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.restore-build-ccache.outputs.cache-primary-key }} + + - name: Save Qt Cache + if: github.ref == 'refs/heads/master' + uses: actions/cache/save@main + with: + path: /tmp/Qt + key: ${{ steps.restore-qt-cache.outputs.cache-primary-key }} Windows_Build: # Only run push event on master branch of main repo, but run all PRs @@ -223,15 +244,17 @@ jobs: - name: Get Cache Keys run: .ci/get_keys-windows.sh - - name: Setup Build Ccache - uses: actions/cache@main + - name: Restore Build Ccache + uses: actions/cache/restore@main + id: restore-build-ccache with: path: ${{ env.CCACHE_DIR }} key: "${{ runner.os }}-ccache-${{ env.COMPILER }}-${{github.run_id}}" restore-keys: ${{ runner.os }}-ccache-${{ env.COMPILER }}- - - name: Setup Dependencies Cache - uses: actions/cache@main + - name: Restore Dependencies Cache + uses: actions/cache/restore@main + id: restore-dependencies-cache with: path: ${{ env.DEPS_CACHE_DIR }} key: "${{ runner.os }}-${{ env.COMPILER }}-${{ env.QT_VER }}-${{ env.VULKAN_SDK_SHA }}-${{ env.CCACHE_SHA }}-${{ hashFiles('llvm.lock') }}" @@ -281,3 +304,17 @@ jobs: env: RPCS3_TOKEN: ${{ secrets.RPCS3_TOKEN }} run: .ci/github-upload.sh + + - name: Save Build Ccache + if: github.ref == 'refs/heads/master' + uses: actions/cache/save@main + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.restore-build-ccache.outputs.cache-primary-key }} + + - name: Save Dependencies Cache + if: github.ref == 'refs/heads/master' + uses: actions/cache/save@main + with: + path: ${{ env.DEPS_CACHE_DIR }} + key: ${{ steps.restore-dependencies-cache.outputs.cache-primary-key }} From 663ff55af99e87bc0b78f3fdf56c428c28dd6a48 Mon Sep 17 00:00:00 2001 From: qurious-pixel <62252937+qurious-pixel@users.noreply.github.com> Date: Sat, 31 May 2025 21:24:19 -0700 Subject: [PATCH 027/384] restore ffmpeg dependencies on linux --- .ci/deploy-linux.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/.ci/deploy-linux.sh b/.ci/deploy-linux.sh index 5f0fe2ef8c..f8c3d849c3 100755 --- a/.ci/deploy-linux.sh +++ b/.ci/deploy-linux.sh @@ -26,9 +26,6 @@ if [ "$DEPLOY_APPIMAGE" = "true" ]; then rm -f ./AppDir/usr/lib/libvulkan.so* # Remove unused Qt6 libraries - rm -f ./AppDir/usr/lib/libQt6OpenGL.so* - rm -f ./AppDir/usr/lib/libQt6Qml*.so* - rm -f ./AppDir/usr/lib/libQt6Quick.so* rm -f ./AppDir/usr/lib/libQt6VirtualKeyboard.so* rm -f ./AppDir/usr/plugins/platforminputcontexts/libqtvirtualkeyboardplugin.so* From 70faef3fdb75923fe15220828dcf41bc54b8a5b9 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sun, 1 Jun 2025 18:43:05 +0200 Subject: [PATCH 028/384] Logs: use thread_local --- rpcs3/util/logs.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rpcs3/util/logs.cpp b/rpcs3/util/logs.cpp index f5573c1d65..bcc1235ac7 100644 --- a/rpcs3/util/logs.cpp +++ b/rpcs3/util/logs.cpp @@ -397,8 +397,8 @@ void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, ...) co g_tls_log_control(fmt, 0); // Get text, extract va_args - /*constinit thread_local*/ std::string text; - /*constinit thread_local*/ std::vector args; + thread_local std::string text; + thread_local std::vector args; static constexpr fmt_type_info empty_sup{}; @@ -406,7 +406,7 @@ void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, ...) co for (auto v = sup; v && v->fmt_string; v++) args_count++; - text.reserve(50000); + text.clear(); args.resize(args_count); va_list c_args; From 4704c032096540fa452d4dc7e12e7390b63f6a92 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sun, 1 Jun 2025 20:45:05 +0200 Subject: [PATCH 029/384] Fix some static analysis warnings, including c-style cast --- Utilities/Thread.h | 4 ++-- Utilities/transactional_storage.h | 3 +-- rpcs3/Emu/Memory/vm_reservation.h | 3 ++- rpcs3/Emu/NP/np_allocator.h | 2 +- rpcs3/util/asm.hpp | 2 +- rpcs3/util/atomic.cpp | 4 ++-- rpcs3/util/atomic.hpp | 8 ++++---- rpcs3/util/bless.hpp | 2 ++ rpcs3/util/cpu_stats.cpp | 2 +- 9 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Utilities/Thread.h b/Utilities/Thread.h index 52096a2702..6dc2dc8cf6 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -96,7 +96,7 @@ class thread_future thread_future* prev{}; protected: - atomic_t exec{}; + atomic_t exec{}; atomic_t done{0}; @@ -389,7 +389,7 @@ public: : m_args(std::forward(args)...) , m_func(std::forward(func)) { - thread_future::exec.raw() = +[](thread_base* tb, thread_future* tf) + thread_future::exec.raw() = +[](const thread_base* tb, thread_future* tf) { const auto _this = static_cast(tf); diff --git a/Utilities/transactional_storage.h b/Utilities/transactional_storage.h index 55e8aa9f95..1be923233e 100644 --- a/Utilities/transactional_storage.h +++ b/Utilities/transactional_storage.h @@ -84,9 +84,8 @@ public: transactional_storage& operator=(const transactional_storage&) = delete; transactional_storage(transactional_storage&& other) + : pool(std::move(other.pool)) { - pool = std::move(other.pool); - std::unique_lock lock_other{other.current_mutex}; const std::shared_ptr other_current = other.current; other.current = nullptr; diff --git a/rpcs3/Emu/Memory/vm_reservation.h b/rpcs3/Emu/Memory/vm_reservation.h index c9d2e0c50a..af402249bf 100644 --- a/rpcs3/Emu/Memory/vm_reservation.h +++ b/rpcs3/Emu/Memory/vm_reservation.h @@ -81,7 +81,8 @@ namespace vm static inline atomic_t* reservation_notifier_begin_wait(u32 raddr, u64 rtime) { - atomic_t& waiter = *reservation_notifier(raddr).first; + const auto notifiers = reservation_notifier(raddr); + atomic_t& waiter = *notifiers.first; waiter.atomic_op([](reservation_waiter_t& value) { diff --git a/rpcs3/Emu/NP/np_allocator.h b/rpcs3/Emu/NP/np_allocator.h index 25c65ea2e4..ee8017cb72 100644 --- a/rpcs3/Emu/NP/np_allocator.h +++ b/rpcs3/Emu/NP/np_allocator.h @@ -59,7 +59,7 @@ namespace np u32 last_free = 0; bool found_space = false; - for (auto& a : m_allocs) + for (const auto& a : m_allocs) { if ((a.first - last_free) >= alloc_size) { diff --git a/rpcs3/util/asm.hpp b/rpcs3/util/asm.hpp index 947aa4f54a..14eaa1409d 100644 --- a/rpcs3/util/asm.hpp +++ b/rpcs3/util/asm.hpp @@ -135,7 +135,7 @@ namespace utils #endif } - constexpr void prefetch_write(void* ptr) + constexpr void prefetch_write(const void* ptr) { if (std::is_constant_evaluated()) { diff --git a/rpcs3/util/atomic.cpp b/rpcs3/util/atomic.cpp index c8e76cbf17..67f48f8dc7 100644 --- a/rpcs3/util/atomic.cpp +++ b/rpcs3/util/atomic.cpp @@ -15,12 +15,12 @@ namespace utils { u128 __vectorcall atomic_load16(const void* ptr) { - return std::bit_cast(_mm_load_si128((__m128i*)ptr)); + return std::bit_cast(_mm_load_si128(static_cast(ptr))); } void __vectorcall atomic_store16(void* ptr, u128 value) { - _mm_store_si128((__m128i*)ptr, std::bit_cast<__m128i>(value)); + _mm_store_si128(static_cast<__m128i*>(ptr), std::bit_cast<__m128i>(value)); } } #endif diff --git a/rpcs3/util/atomic.hpp b/rpcs3/util/atomic.hpp index 80d9e34f9d..4503eaac61 100644 --- a/rpcs3/util/atomic.hpp +++ b/rpcs3/util/atomic.hpp @@ -479,7 +479,7 @@ struct atomic_storage #endif #if defined(_M_X64) && defined(_MSC_VER) - return _interlockedbittestandset((long*)dst, bit) != 0; + return _interlockedbittestandset(reinterpret_cast(dst), bit) != 0; #elif defined(ARCH_X64) bool result; __asm__ volatile ("lock btsl %2, 0(%1)\n" : "=@ccc" (result) : "r" (dst), "Ir" (bit) : "cc", "memory"); @@ -506,7 +506,7 @@ struct atomic_storage #endif #if defined(_M_X64) && defined(_MSC_VER) - return _interlockedbittestandreset((long*)dst, bit) != 0; + return _interlockedbittestandreset(reinterpret_cast(dst), bit) != 0; #elif defined(ARCH_X64) bool result; __asm__ volatile ("lock btrl %2, 0(%1)\n" : "=@ccc" (result) : "r" (dst), "Ir" (bit) : "cc", "memory"); @@ -536,9 +536,9 @@ struct atomic_storage while (true) { // Keep trying until we actually invert desired bit - if (!_bittest((long*)dst, bit) && !_interlockedbittestandset((long*)dst, bit)) + if (!_bittest(reinterpret_cast(dst), bit) && !_interlockedbittestandset(reinterpret_cast(dst), bit)) return false; - if (_interlockedbittestandreset((long*)dst, bit)) + if (_interlockedbittestandreset(reinterpret_cast(dst), bit)) return true; } #elif defined(ARCH_X64) diff --git a/rpcs3/util/bless.hpp b/rpcs3/util/bless.hpp index 49ffa8facb..af2f8d32f3 100644 --- a/rpcs3/util/bless.hpp +++ b/rpcs3/util/bless.hpp @@ -16,6 +16,8 @@ namespace utils T* result; __asm__("mov %0, %1" : "=r" (result) : "r" (ptr) : "memory"); return result; +#else +#error "Missing utils::bless() implementation" #endif } } diff --git a/rpcs3/util/cpu_stats.cpp b/rpcs3/util/cpu_stats.cpp index 42c5304bea..8203d1977b 100644 --- a/rpcs3/util/cpu_stats.cpp +++ b/rpcs3/util/cpu_stats.cpp @@ -444,7 +444,7 @@ namespace utils if (proc_dir) { // proc available, iterate through tasks and count them - struct dirent* entry; + const struct dirent* entry; while ((entry = readdir(proc_dir)) != NULL) { if (entry->d_name[0] == '.') From d8bc2d5c7531cb1795cbff1740844f89dff2b1bf Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 2 Jun 2025 00:52:05 +0200 Subject: [PATCH 030/384] input: move copilot code to pad_thread --- rpcs3/Emu/Cell/Modules/cellGem.cpp | 32 +++---- rpcs3/Emu/Cell/Modules/cellPad.cpp | 133 +++++++--------------------- rpcs3/Emu/Cell/Modules/cellPad.h | 1 - rpcs3/Emu/Io/Buzz.cpp | 2 +- rpcs3/Emu/Io/GHLtar.cpp | 2 +- rpcs3/Emu/Io/GameTablet.cpp | 4 +- rpcs3/Emu/Io/GunCon3.cpp | 2 +- rpcs3/Emu/Io/TopShotElite.cpp | 2 +- rpcs3/Emu/Io/TopShotFearmaster.cpp | 2 +- rpcs3/Emu/Io/Turntable.cpp | 2 +- rpcs3/Emu/Io/emulated_pad_config.h | 6 +- rpcs3/Emu/Io/pad_types.h | 9 ++ rpcs3/Emu/Io/usio.cpp | 4 +- rpcs3/Emu/RSX/Overlays/overlays.cpp | 6 +- rpcs3/Input/pad_thread.cpp | 104 ++++++++++++++++++++-- rpcs3/Input/pad_thread.h | 1 + 16 files changed, 173 insertions(+), 139 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellGem.cpp b/rpcs3/Emu/Cell/Modules/cellGem.cpp index bfbeb416df..ba796be28e 100644 --- a/rpcs3/Emu/Cell/Modules/cellGem.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGem.cpp @@ -351,7 +351,7 @@ public: for (u32 i = 0; i < CELL_GEM_MAX_NUM; i++) { const auto& pad = ::at32(handler->GetPads(), pad_num(i)); - const bool connected = pad && pad->is_connected() && i < attribute.max_connect; + const bool connected = pad && pad->is_connected() && !pad->is_copilot() && i < attribute.max_connect; const bool is_real_move = g_cfg.io.move != move_handler::real || pad->m_pad_handler == pad_handler::move; update_connection(i, connected && is_real_move); @@ -407,7 +407,7 @@ public: std::lock_guard pad_lock(pad::g_pad_mutex); const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad && pad->m_pad_handler == pad_handler::move) + if (pad && pad->m_pad_handler == pad_handler::move && !pad->is_copilot()) { if (!pad->move_data.calibration_requested || !pad->move_data.calibration_succeeded) { @@ -437,7 +437,7 @@ public: std::lock_guard pad_lock(pad::g_pad_mutex); const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad && pad->m_pad_handler == pad_handler::move) + if (pad && pad->m_pad_handler == pad_handler::move && !pad->is_copilot()) { pad->move_data.calibration_requested = false; pad->move_data.calibration_succeeded = false; @@ -469,7 +469,7 @@ public: for (u32 i = 0; i < std::min(attribute.max_connect, CELL_GEM_MAX_NUM); i++) { const auto& pad = ::at32(handler->GetPads(), pad_num(i)); - if (pad && pad->m_pad_handler == pad_handler::move && pad->is_connected()) + if (pad && pad->m_pad_handler == pad_handler::move && pad->is_connected() && !pad->is_copilot()) { connected_controllers++; @@ -490,7 +490,7 @@ public: for (u32 i = 0; i < std::min(attribute.max_connect, CELL_GEM_MAX_NUM); i++) { const auto& pad = ::at32(handler->GetPads(), pad_num(i)); - if (pad && pad->is_connected()) + if (pad && pad->is_connected() && !pad->is_copilot()) { connected_controllers++; @@ -1776,7 +1776,7 @@ static void ds3_input_to_pad(const u32 gem_num, be_t& digital_buttons, be_t const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (!pad->is_connected()) + if (!pad->is_connected() || pad->is_copilot()) { return; } @@ -1864,7 +1864,7 @@ static void ds3_pos_to_gem_state(u32 gem_num, gem_config::gem_controller& contro const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (!pad->is_connected()) + if (!pad->is_connected() || pad->is_copilot()) { return; } @@ -1895,7 +1895,7 @@ static void ps_move_pos_to_gem_state(u32 gem_num, gem_config::gem_controller& co const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad->m_pad_handler != pad_handler::move || !pad->is_connected()) + if (pad->m_pad_handler != pad_handler::move || !pad->is_connected() || pad->is_copilot()) { return; } @@ -1940,7 +1940,7 @@ static void ds3_input_to_ext(u32 gem_num, gem_config::gem_controller& controller const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (!pad->is_connected()) + if (!pad->is_connected() || pad->is_copilot()) { return; } @@ -1952,7 +1952,7 @@ static void ds3_input_to_ext(u32 gem_num, gem_config::gem_controller& controller ext.status = controller.ext_status; - for (const AnalogStick& stick : pad->m_sticks) + for (const AnalogStick& stick : pad->m_sticks_external) { switch (stick.m_offset) { @@ -1964,7 +1964,7 @@ static void ds3_input_to_ext(u32 gem_num, gem_config::gem_controller& controller } } - for (const Button& button : pad->m_buttons) + for (const Button& button : pad->m_buttons_external) { if (!button.m_pressed) continue; @@ -2400,7 +2400,7 @@ error_code cellGemEnableMagnetometer(u32 gem_num, u32 enable) const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad && pad->m_pad_handler == pad_handler::move) + if (pad && pad->m_pad_handler == pad_handler::move && !pad->is_copilot()) { pad->move_data.magnetometer_enabled = controller.enabled_magnetometer; } @@ -2448,7 +2448,7 @@ error_code cellGemEnableMagnetometer2(u32 gem_num, u32 enable) const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad && pad->m_pad_handler == pad_handler::move) + if (pad && pad->m_pad_handler == pad_handler::move && !pad->is_copilot()) { pad->move_data.magnetometer_enabled = controller.enabled_magnetometer; } @@ -2777,7 +2777,7 @@ error_code cellGemGetInertialState(u32 gem_num, u32 state_flag, u64 timestamp, v const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad && pad->is_connected()) + if (pad && pad->is_connected() && !pad->is_copilot()) { inertial_state->temperature = pad->move_data.temperature; inertial_state->accelerometer[0] = pad->move_data.accelerometer_x; @@ -3392,7 +3392,7 @@ error_code cellGemReadExternalPortDeviceInfo(u32 gem_num, vm::ptr ext_id, v const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad->m_pad_handler != pad_handler::move || !pad->is_connected()) + if (pad->m_pad_handler != pad_handler::move || !pad->is_connected() || pad->is_copilot()) { return CELL_GEM_NOT_CONNECTED; } @@ -3706,7 +3706,7 @@ error_code cellGemWriteExternalPort(u32 gem_num, vm::ptrGetPads(), pad_num(gem_num)); - if (pad->m_pad_handler != pad_handler::move || !pad->is_connected()) + if (pad->m_pad_handler != pad_handler::move || !pad->is_connected() || pad->is_copilot()) { return CELL_GEM_NOT_CONNECTED; } diff --git a/rpcs3/Emu/Cell/Modules/cellPad.cpp b/rpcs3/Emu/Cell/Modules/cellPad.cpp index 61e29805aa..086a341854 100644 --- a/rpcs3/Emu/Cell/Modules/cellPad.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPad.cpp @@ -411,60 +411,27 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false) } }; - for (const Button& button : pad->m_buttons) + for (const Button& button : pad->m_buttons_external) { // here we check btns, and set pad accordingly, // if something changed, set btnChanged - bool pressed = button.m_pressed; - u16 value = button.m_value; - - // Merge copilots - if (!pad->copilots.empty()) - { - for (const auto& copilot : pad->copilots) - { - if (!copilot || !copilot->is_connected()) - { - continue; - } - - for (const Button& other : copilot->m_buttons) - { - if (button.m_offset == other.m_offset && button.m_outKeyCode == other.m_outKeyCode) - { - if (other.m_pressed) - { - pressed = true; - - if (value < other.m_value) - { - value = other.m_value; - } - } - - break; - } - } - } - } - switch (button.m_offset) { case CELL_PAD_BTN_OFFSET_DIGITAL1: { - if (pressed) + if (button.m_pressed) pad->m_digital_1 |= button.m_outKeyCode; else pad->m_digital_1 &= ~button.m_outKeyCode; switch (button.m_outKeyCode) { - case CELL_PAD_CTRL_LEFT: set_value(pad->m_press_left, value); break; - case CELL_PAD_CTRL_DOWN: set_value(pad->m_press_down, value); break; - case CELL_PAD_CTRL_RIGHT: set_value(pad->m_press_right, value); break; - case CELL_PAD_CTRL_UP: set_value(pad->m_press_up, value); break; - // These arent pressure btns + case CELL_PAD_CTRL_LEFT: set_value(pad->m_press_left, button.m_value); break; + case CELL_PAD_CTRL_DOWN: set_value(pad->m_press_down, button.m_value); break; + case CELL_PAD_CTRL_RIGHT: set_value(pad->m_press_right, button.m_value); break; + case CELL_PAD_CTRL_UP: set_value(pad->m_press_up, button.m_value); break; + // These aren't pressure btns case CELL_PAD_CTRL_R3: case CELL_PAD_CTRL_L3: case CELL_PAD_CTRL_START: @@ -475,21 +442,21 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false) } case CELL_PAD_BTN_OFFSET_DIGITAL2: { - if (pressed) + if (button.m_pressed) pad->m_digital_2 |= button.m_outKeyCode; else pad->m_digital_2 &= ~button.m_outKeyCode; switch (button.m_outKeyCode) { - case CELL_PAD_CTRL_SQUARE: set_value(pad->m_press_square, value); break; - case CELL_PAD_CTRL_CROSS: set_value(pad->m_press_cross, value); break; - case CELL_PAD_CTRL_CIRCLE: set_value(pad->m_press_circle, value); break; - case CELL_PAD_CTRL_TRIANGLE: set_value(pad->m_press_triangle, value); break; - case CELL_PAD_CTRL_R1: set_value(pad->m_press_R1, value); break; - case CELL_PAD_CTRL_L1: set_value(pad->m_press_L1, value); break; - case CELL_PAD_CTRL_R2: set_value(pad->m_press_R2, value); break; - case CELL_PAD_CTRL_L2: set_value(pad->m_press_L2, value); break; + case CELL_PAD_CTRL_SQUARE: set_value(pad->m_press_square, button.m_value); break; + case CELL_PAD_CTRL_CROSS: set_value(pad->m_press_cross, button.m_value); break; + case CELL_PAD_CTRL_CIRCLE: set_value(pad->m_press_circle, button.m_value); break; + case CELL_PAD_CTRL_TRIANGLE: set_value(pad->m_press_triangle, button.m_value); break; + case CELL_PAD_CTRL_R1: set_value(pad->m_press_R1, button.m_value); break; + case CELL_PAD_CTRL_L1: set_value(pad->m_press_L1, button.m_value); break; + case CELL_PAD_CTRL_R2: set_value(pad->m_press_R2, button.m_value); break; + case CELL_PAD_CTRL_L2: set_value(pad->m_press_L2, button.m_value); break; default: break; } break; @@ -498,18 +465,18 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false) { switch (button.m_outKeyCode) { - case CELL_PAD_CTRL_PRESS_RIGHT: set_value(pad->m_press_right, value, true); break; - case CELL_PAD_CTRL_PRESS_LEFT: set_value(pad->m_press_left, value, true); break; - case CELL_PAD_CTRL_PRESS_UP: set_value(pad->m_press_up, value, true); break; - case CELL_PAD_CTRL_PRESS_DOWN: set_value(pad->m_press_down, value, true); break; - case CELL_PAD_CTRL_PRESS_TRIANGLE: set_value(pad->m_press_triangle, value, true, 255, 63); break; // Infrared on RIDE Skateboard - case CELL_PAD_CTRL_PRESS_CIRCLE: set_value(pad->m_press_circle, value, true, 255, 63); break; // Infrared on RIDE Skateboard - case CELL_PAD_CTRL_PRESS_CROSS: set_value(pad->m_press_cross, value, true, 255, 63); break; // Infrared on RIDE Skateboard - case CELL_PAD_CTRL_PRESS_SQUARE: set_value(pad->m_press_square, value, true, 255, 63); break; // Infrared on RIDE Skateboard - case CELL_PAD_CTRL_PRESS_L1: set_value(pad->m_press_L1, value, true); break; - case CELL_PAD_CTRL_PRESS_R1: set_value(pad->m_press_R1, value, true); break; - case CELL_PAD_CTRL_PRESS_L2: set_value(pad->m_press_L2, value, true); break; - case CELL_PAD_CTRL_PRESS_R2: set_value(pad->m_press_R2, value, true); break; + case CELL_PAD_CTRL_PRESS_RIGHT: set_value(pad->m_press_right, button.m_value, true); break; + case CELL_PAD_CTRL_PRESS_LEFT: set_value(pad->m_press_left, button.m_value, true); break; + case CELL_PAD_CTRL_PRESS_UP: set_value(pad->m_press_up, button.m_value, true); break; + case CELL_PAD_CTRL_PRESS_DOWN: set_value(pad->m_press_down, button.m_value, true); break; + case CELL_PAD_CTRL_PRESS_TRIANGLE: set_value(pad->m_press_triangle, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard + case CELL_PAD_CTRL_PRESS_CIRCLE: set_value(pad->m_press_circle, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard + case CELL_PAD_CTRL_PRESS_CROSS: set_value(pad->m_press_cross, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard + case CELL_PAD_CTRL_PRESS_SQUARE: set_value(pad->m_press_square, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard + case CELL_PAD_CTRL_PRESS_L1: set_value(pad->m_press_L1, button.m_value, true); break; + case CELL_PAD_CTRL_PRESS_R1: set_value(pad->m_press_R1, button.m_value, true); break; + case CELL_PAD_CTRL_PRESS_L2: set_value(pad->m_press_L2, button.m_value, true); break; + case CELL_PAD_CTRL_PRESS_R2: set_value(pad->m_press_R2, button.m_value, true); break; default: break; } break; @@ -519,46 +486,14 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false) } } - for (const AnalogStick& stick : pad->m_sticks) + for (const AnalogStick& stick : pad->m_sticks_external) { - u16 value = stick.m_value; - - // Merge copilots - if (!pad->copilots.empty()) - { - const auto normalize = [](s32 value) - { - return (value - 128) / 127.0f; - }; - - f32 accumulated_value = normalize(value); - - for (const auto& copilot : pad->copilots) - { - if (!copilot || !copilot->is_connected()) - { - continue; - } - - for (const AnalogStick& other : copilot->m_sticks) - { - if (stick.m_offset == other.m_offset) - { - accumulated_value += normalize(other.m_value); - break; - } - } - } - - value = static_cast(std::round(std::clamp(accumulated_value * 127.0f + 128.0f, 0.0f, 255.0f))); - } - switch (stick.m_offset) { - case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: set_value(pad->m_analog_left_x, value); break; - case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: set_value(pad->m_analog_left_y, value); break; - case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: set_value(pad->m_analog_right_x, value); break; - case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: set_value(pad->m_analog_right_y, value); break; + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: set_value(pad->m_analog_left_x, stick.m_value); break; + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: set_value(pad->m_analog_left_y, stick.m_value); break; + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: set_value(pad->m_analog_right_x, stick.m_value); break; + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: set_value(pad->m_analog_right_y, stick.m_value); break; default: break; } } @@ -1305,7 +1240,7 @@ error_code cellPadLddGetPortNo(s32 handle) return CELL_PAD_ERROR_UNINITIALIZED; const auto handler = pad::get_pad_thread(); - auto& pads = handler->GetPads(); + const auto& pads = handler->GetPads(); if (handle < 0 || static_cast(handle) >= pads.size()) return CELL_PAD_ERROR_INVALID_PARAMETER; diff --git a/rpcs3/Emu/Cell/Modules/cellPad.h b/rpcs3/Emu/Cell/Modules/cellPad.h index 3394fe6b2b..0d199e488c 100644 --- a/rpcs3/Emu/Cell/Modules/cellPad.h +++ b/rpcs3/Emu/Cell/Modules/cellPad.h @@ -3,7 +3,6 @@ #include "Emu/Io/pad_types.h" #include -#include "util/types.hpp" enum CellPadError : u32 { diff --git a/rpcs3/Emu/Io/Buzz.cpp b/rpcs3/Emu/Io/Buzz.cpp index d5b7fe4f23..840220b967 100644 --- a/rpcs3/Emu/Io/Buzz.cpp +++ b/rpcs3/Emu/Io/Buzz.cpp @@ -173,7 +173,7 @@ void usb_device_buzz::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint*/ { const auto& pad = pads[i]; - if (!pad->is_connected()) + if (!pad->is_connected() || pad->is_copilot()) { continue; } diff --git a/rpcs3/Emu/Io/GHLtar.cpp b/rpcs3/Emu/Io/GHLtar.cpp index 9a2b9d0ce6..0c99c6aabf 100644 --- a/rpcs3/Emu/Io/GHLtar.cpp +++ b/rpcs3/Emu/Io/GHLtar.cpp @@ -152,7 +152,7 @@ void usb_device_ghltar::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), m_controller_index); - if (!pad->is_connected()) + if (!pad->is_connected() || pad->is_copilot()) { return; } diff --git a/rpcs3/Emu/Io/GameTablet.cpp b/rpcs3/Emu/Io/GameTablet.cpp index 0b87a709bf..4c2330d908 100644 --- a/rpcs3/Emu/Io/GameTablet.cpp +++ b/rpcs3/Emu/Io/GameTablet.cpp @@ -198,9 +198,9 @@ void usb_device_gametablet::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endp const auto gamepad_handler = pad::get_pad_thread(); const auto& pads = gamepad_handler->GetPads(); const auto& pad = ::at32(pads, m_controller_index); - if (pad->is_connected()) + if (pad->is_connected() && !pad->is_copilot()) { - for (Button& button : pad->m_buttons) + for (Button& button : pad->m_buttons_external) { if (!button.m_pressed) { diff --git a/rpcs3/Emu/Io/GunCon3.cpp b/rpcs3/Emu/Io/GunCon3.cpp index 8dc5688f73..522369d8a4 100644 --- a/rpcs3/Emu/Io/GunCon3.cpp +++ b/rpcs3/Emu/Io/GunCon3.cpp @@ -258,7 +258,7 @@ void usb_device_guncon3::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint, const auto gamepad_handler = pad::get_pad_thread(); const auto& pads = gamepad_handler->GetPads(); const auto& pad = ::at32(pads, m_controller_index); - if (pad->is_connected()) + if (pad->is_connected() && !pad->is_copilot()) { cfg->handle_input(pad, true, input_callback); } diff --git a/rpcs3/Emu/Io/TopShotElite.cpp b/rpcs3/Emu/Io/TopShotElite.cpp index b7e2b64b98..c241fe1ed4 100644 --- a/rpcs3/Emu/Io/TopShotElite.cpp +++ b/rpcs3/Emu/Io/TopShotElite.cpp @@ -318,7 +318,7 @@ void usb_device_topshotelite::interrupt_transfer(u32 buf_size, u8* buf, u32 /*en const auto gamepad_handler = pad::get_pad_thread(); const auto& pads = gamepad_handler->GetPads(); const auto& pad = ::at32(pads, m_controller_index); - if (pad->is_connected()) + if (pad->is_connected() && !pad->is_copilot()) { cfg->handle_input(pad, true, input_callback); } diff --git a/rpcs3/Emu/Io/TopShotFearmaster.cpp b/rpcs3/Emu/Io/TopShotFearmaster.cpp index 03c634d839..eed7ade977 100644 --- a/rpcs3/Emu/Io/TopShotFearmaster.cpp +++ b/rpcs3/Emu/Io/TopShotFearmaster.cpp @@ -342,7 +342,7 @@ void usb_device_topshotfearmaster::interrupt_transfer(u32 buf_size, u8* buf, u32 const auto gamepad_handler = pad::get_pad_thread(); const auto& pads = gamepad_handler->GetPads(); const auto& pad = ::at32(pads, m_controller_index); - if (pad->is_connected()) + if (pad->is_connected() && !pad->is_copilot()) { cfg->handle_input(pad, true, input_callback); } diff --git a/rpcs3/Emu/Io/Turntable.cpp b/rpcs3/Emu/Io/Turntable.cpp index ec67fabc22..261af88d16 100644 --- a/rpcs3/Emu/Io/Turntable.cpp +++ b/rpcs3/Emu/Io/Turntable.cpp @@ -166,7 +166,7 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo const auto& pads = handler->GetPads(); const auto& pad = ::at32(pads, m_controller_index); - if (!pad->is_connected()) + if (!pad->is_connected() || pad->is_copilot()) return; const auto& cfg = ::at32(g_cfg_turntable.players, m_controller_index); diff --git a/rpcs3/Emu/Io/emulated_pad_config.h b/rpcs3/Emu/Io/emulated_pad_config.h index e2b46d3daa..b9bf68a223 100644 --- a/rpcs3/Emu/Io/emulated_pad_config.h +++ b/rpcs3/Emu/Io/emulated_pad_config.h @@ -90,10 +90,10 @@ public: void handle_input(std::shared_ptr pad, bool press_only, const std::function& func) const { - if (!pad) + if (!pad || pad->is_copilot()) return; - for (const Button& button : pad->m_buttons) + for (const Button& button : pad->m_buttons_external) { if (button.m_pressed || !press_only) { @@ -104,7 +104,7 @@ public: } } - for (const AnalogStick& stick : pad->m_sticks) + for (const AnalogStick& stick : pad->m_sticks_external) { if (handle_input(func, stick.m_offset, get_axis_keycode(stick.m_offset, stick.m_value), stick.m_value, true, true)) { diff --git a/rpcs3/Emu/Io/pad_types.h b/rpcs3/Emu/Io/pad_types.h index 57634a66b4..356c86d6ae 100644 --- a/rpcs3/Emu/Io/pad_types.h +++ b/rpcs3/Emu/Io/pad_types.h @@ -543,6 +543,9 @@ struct Pad std::array m_sensors{}; std::array m_vibrateMotors{}; + std::vector