From 7965a0313cb70e1aa450492bb34cd2feaf9a9868 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sat, 11 Jan 2025 02:46:53 +0300 Subject: [PATCH 1/9] rsx: Improved shader interpreter support when hw instancing is active --- rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp | 15 ++++++++------- rpcs3/Emu/RSX/Core/RSXDrawCommands.h | 2 +- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 14 ++++++++++---- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 21 +++++++++++++-------- 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp b/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp index 095903832d..7be332fc60 100644 --- a/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp +++ b/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp @@ -735,7 +735,7 @@ namespace rsx utils::stream_vector(dst + 4, 0u, fog_mode, std::bit_cast(wpos_scale), std::bit_cast(wpos_bias)); } - void draw_command_processor::fill_constants_instancing_buffer(rsx::io_buffer& indirection_table_buf, rsx::io_buffer& constants_data_array_buffer, const VertexProgramBase& prog) const + void draw_command_processor::fill_constants_instancing_buffer(rsx::io_buffer& indirection_table_buf, rsx::io_buffer& constants_data_array_buffer, const VertexProgramBase* prog) const { auto& draw_call = REGS(m_ctx)->current_draw_clause; @@ -745,8 +745,9 @@ namespace rsx // Temp indirection table. Used to track "running" updates. rsx::simple_array instancing_indirection_table; // indirection table size - const auto reloc_table = prog.has_indexed_constants ? decltype(prog.constant_ids){} : prog.constant_ids; - const auto redirection_table_size = prog.has_indexed_constants ? 468u : ::size32(prog.constant_ids); + const auto full_reupload = !prog || prog->has_indexed_constants; + const auto reloc_table = full_reupload ? decltype(prog->constant_ids){} : prog->constant_ids; + const auto redirection_table_size = full_reupload ? 468u : ::size32(prog->constant_ids); instancing_indirection_table.resize(redirection_table_size); // Temp constants data @@ -787,9 +788,9 @@ namespace rsx continue; } - const int translated_offset = prog.has_indexed_constants + const int translated_offset = full_reupload ? instance_config.patch_load_offset - : prog.TranslateConstantsRange(instance_config.patch_load_offset, instance_config.patch_load_count); + : prog->TranslateConstantsRange(instance_config.patch_load_offset, instance_config.patch_load_count); if (translated_offset >= 0) { @@ -809,14 +810,14 @@ namespace rsx continue; } - ensure(!prog.has_indexed_constants); + ensure(!full_reupload); // Sparse update. Update records individually instead of bulk // FIXME: Range batching optimization const auto load_end = instance_config.patch_load_offset + instance_config.patch_load_count; for (u32 i = 0; i < redirection_table_size; ++i) { - const auto read_index = prog.constant_ids[i]; + const auto read_index = prog->constant_ids[i]; if (read_index < instance_config.patch_load_offset || read_index >= load_end) { // Reading outside "hot" range. diff --git a/rpcs3/Emu/RSX/Core/RSXDrawCommands.h b/rpcs3/Emu/RSX/Core/RSXDrawCommands.h index b69a918401..5bc5991a18 100644 --- a/rpcs3/Emu/RSX/Core/RSXDrawCommands.h +++ b/rpcs3/Emu/RSX/Core/RSXDrawCommands.h @@ -105,6 +105,6 @@ namespace rsx // Fill instancing buffers. A single iobuf is used for both. 256byte alignment enforced to allow global bind // Returns offsets to the index redirection lookup table and constants field array - void fill_constants_instancing_buffer(rsx::io_buffer& indirection_table_buf, rsx::io_buffer& constants_data_array_buffer, const VertexProgramBase& prog) const; + void fill_constants_instancing_buffer(rsx::io_buffer& indirection_table_buf, rsx::io_buffer& constants_data_array_buffer, const VertexProgramBase* prog) const; }; } diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 90bc7cacbd..34f0380ad3 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -878,7 +878,7 @@ void GLGSRender::load_program_env() } } - if (update_fragment_constants && !update_instruction_buffers) + if (update_fragment_constants && !m_shader_interpreter.is_interpreter(m_program)) { // Fragment constants auto mapping = m_fragment_constants_buffer->alloc_from_heap(fragment_constants_size, m_uniform_buffer_offset_align); @@ -978,12 +978,18 @@ void GLGSRender::load_program_env() } } - m_graphics_state.clear( + rsx::flags32_t handled_flags = rsx::pipeline_state::fragment_state_dirty | rsx::pipeline_state::vertex_state_dirty | rsx::pipeline_state::transform_constants_dirty | - rsx::pipeline_state::fragment_constants_dirty | - rsx::pipeline_state::fragment_texture_state_dirty); + rsx::pipeline_state::fragment_texture_state_dirty; + + if (update_fragment_constants && !m_shader_interpreter.is_interpreter(m_program)) + { + handled_flags |= rsx::pipeline_state::fragment_constants_dirty; + } + + m_graphics_state.clear(handled_flags); } bool GLGSRender::is_current_program_interpreted() const diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 6e53891fbf..ea3d83cdf3 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -688,10 +688,10 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar) } // Initialize optional allocation information with placeholders - m_vertex_env_buffer_info = { m_vertex_env_ring_info.heap->value, 0, 32 }; - m_vertex_constants_buffer_info = { m_transform_constants_ring_info.heap->value, 0, 32 }; - m_fragment_env_buffer_info = { m_fragment_env_ring_info.heap->value, 0, 32 }; - m_fragment_texture_params_buffer_info = { m_fragment_texture_params_ring_info.heap->value, 0, 32 }; + m_vertex_env_buffer_info = { m_vertex_env_ring_info.heap->value, 0, 16 }; + m_vertex_constants_buffer_info = { m_transform_constants_ring_info.heap->value, 0, 16 }; + m_fragment_env_buffer_info = { m_fragment_env_ring_info.heap->value, 0, 16 }; + 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(); @@ -2192,7 +2192,7 @@ void VKGSRender::load_program_env() return std::make_pair(m_instancing_buffer_ring_info.map(constants_data_table_offset, size), size); }); - m_draw_processor.fill_constants_instancing_buffer(indirection_table_buf, constants_array_buf, *m_vertex_prog); + m_draw_processor.fill_constants_instancing_buffer(indirection_table_buf, constants_array_buf, m_vertex_prog); m_instancing_buffer_ring_info.unmap(); m_instancing_indirection_buffer_info = { m_instancing_buffer_ring_info.heap->value, indirection_table_offset, indirection_table_buf.size() }; @@ -2219,7 +2219,7 @@ void VKGSRender::load_program_env() } } - if (update_fragment_constants && !update_instruction_buffers) + if (update_fragment_constants && !m_shader_interpreter.is_interpreter(m_program)) { check_heap_status(VK_HEAP_CHECK_FRAGMENT_CONSTANTS_STORAGE); @@ -2350,9 +2350,9 @@ void VKGSRender::load_program_env() } // Clear flags - u32 handled_flags = rsx::pipeline_state::fragment_state_dirty | + rsx::flags32_t handled_flags = + rsx::pipeline_state::fragment_state_dirty | rsx::pipeline_state::vertex_state_dirty | - rsx::pipeline_state::fragment_constants_dirty | rsx::pipeline_state::fragment_texture_state_dirty; if (!update_instancing_data) @@ -2360,6 +2360,11 @@ void VKGSRender::load_program_env() handled_flags |= rsx::pipeline_state::transform_constants_dirty; } + if (update_fragment_constants && !m_shader_interpreter.is_interpreter(m_program)) + { + handled_flags |= rsx::pipeline_state::fragment_constants_dirty; + } + m_graphics_state.clear(handled_flags); } From e1c6df0df3d5cedbc053a0e8bdde9c4852ca6a68 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sat, 11 Jan 2025 21:02:13 +0300 Subject: [PATCH 2/9] rsx: Fix dynamic constants patching when draw call is skipped - Also adds an optimization to skip reuploads when patch occurs outside our critical range. --- rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp | 2 +- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 10 +++++++-- rpcs3/Emu/RSX/Program/program_util.cpp | 29 +++++++++++++++++++++++++- rpcs3/Emu/RSX/Program/program_util.h | 5 ++++- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 10 +++++++-- 5 files changed, 49 insertions(+), 7 deletions(-) diff --git a/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp b/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp index 7be332fc60..389efe0a2e 100644 --- a/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp +++ b/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp @@ -790,7 +790,7 @@ namespace rsx const int translated_offset = full_reupload ? instance_config.patch_load_offset - : prog->TranslateConstantsRange(instance_config.patch_load_offset, instance_config.patch_load_count); + : prog->translate_constants_range(instance_config.patch_load_offset, instance_config.patch_load_count); if (translated_offset >= 0) { diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 34f0380ad3..c37228afe9 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -1045,13 +1045,19 @@ void GLGSRender::update_vertex_env(const gl::vertex_upload_info& upload_info) void GLGSRender::patch_transform_constants(rsx::context* ctx, u32 index, u32 count) { - if (!m_vertex_prog) + if (!m_program || !m_vertex_prog) { // Shouldn't be reachable, but handle it correctly anyway m_graphics_state |= rsx::pipeline_state::transform_constants_dirty; return; } + if (!m_vertex_prog->overlaps_constants_range(index, count)) + { + // Nothing meaningful to us + return; + } + std::pair data_range {}; void* data_source = nullptr; const auto bound_range = m_transform_constants_buffer->bound_range(); @@ -1065,7 +1071,7 @@ void GLGSRender::patch_transform_constants(rsx::context* ctx, u32 index, u32 cou data_range = { bound_range.first + byte_offset, byte_count}; data_source = ®S(ctx)->transform_constants[index]; } - else if (auto xform_id = m_vertex_prog->TranslateConstantsRange(index, count); xform_id >= 0) + else if (auto xform_id = m_vertex_prog->translate_constants_range(index, count); xform_id >= 0) { const auto write_offset = xform_id * 16; const auto byte_count = count * 16; diff --git a/rpcs3/Emu/RSX/Program/program_util.cpp b/rpcs3/Emu/RSX/Program/program_util.cpp index 9f44f05505..e5daf319fc 100644 --- a/rpcs3/Emu/RSX/Program/program_util.cpp +++ b/rpcs3/Emu/RSX/Program/program_util.cpp @@ -110,7 +110,7 @@ namespace rsx multisampled_textures == other.multisampled_textures; } - int VertexProgramBase::TranslateConstantsRange(int first_index, int count) const + int VertexProgramBase::translate_constants_range(int first_index, int count) const { // The constant ids should be sorted, so just find the first one and check for continuity int index = -1; @@ -157,4 +157,31 @@ namespace rsx // OOB or partial match return -1; } + + bool VertexProgramBase::overlaps_constants_range(int first_index, int count) const + { + if (has_indexed_constants) + { + return true; + } + + const int last_index = first_index + count - 1; + + // Early rejection test + if (constant_ids.empty() || first_index > constant_ids.back() || last_index < first_index) + { + return false; + } + + // Check for any hits + for (auto& idx : constant_ids) + { + if (idx >= first_index && idx <= last_index) + { + return true; + } + } + + return false; + } } diff --git a/rpcs3/Emu/RSX/Program/program_util.h b/rpcs3/Emu/RSX/Program/program_util.h index c8011a3db2..8159b27845 100644 --- a/rpcs3/Emu/RSX/Program/program_util.h +++ b/rpcs3/Emu/RSX/Program/program_util.h @@ -67,6 +67,9 @@ namespace rsx // Translates an incoming range of constants against our mapping. // If there is no linear mapping available, return -1, otherwise returns the translated index of the first slot // TODO: Move this somewhere else during refactor - int TranslateConstantsRange(int first_index, int count) const; + int translate_constants_range(int first_index, int count) const; + + // Returns true if this program consumes any constants in the range [first, first + count - 1] + bool overlaps_constants_range(int first_index, int count) const; }; } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index ea3d83cdf3..8ebb41c099 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -2443,13 +2443,19 @@ void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_ void VKGSRender::patch_transform_constants(rsx::context* ctx, u32 index, u32 count) { - if (!m_vertex_prog) + if (!m_program || !m_vertex_prog) { // Shouldn't be reachable, but handle it correctly anyway m_graphics_state |= rsx::pipeline_state::transform_constants_dirty; return; } + if (!m_vertex_prog->overlaps_constants_range(index, count)) + { + // Nothing meaningful to us + return; + } + // Hot-patching transform constants mid-draw (instanced draw) std::pair data_range; void* data_source = nullptr; @@ -2463,7 +2469,7 @@ void VKGSRender::patch_transform_constants(rsx::context* ctx, u32 index, u32 cou data_range = { m_vertex_constants_buffer_info.offset + byte_offset, byte_count }; data_source = ®S(ctx)->transform_constants[index]; } - else if (auto xform_id = m_vertex_prog->TranslateConstantsRange(index, count); xform_id >= 0) + else if (auto xform_id = m_vertex_prog->translate_constants_range(index, count); xform_id >= 0) { const auto write_offset = xform_id * 16; const auto byte_count = count * 16; From 7da0822419db57700acfcb9bcb000955d591b979 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 12 Jan 2025 15:51:15 +0300 Subject: [PATCH 3/9] rsx/shaders: Fix MSAA coords wrapping when input is negative --- .../GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOps.glsl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOps.glsl b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOps.glsl index d250e2efb4..8575508f54 100644 --- a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOps.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOps.glsl @@ -34,7 +34,8 @@ vec2 texture2DMSCoord(const in vec2 coords, const in uint flags) return coords; } - const vec2 wrapped_coords = mod(coords, vec2(1.0)); + const vec2 wrapped_coords_raw = mod(coords, vec2(1.0)); + const vec2 wrapped_coords = mod(wrapped_coords_raw + vec2(1.0), vec2(1.0)); const bvec2 wrap_control_mask = bvec2(uvec2(flags) & uvec2(WRAP_S_MASK, WRAP_T_MASK)); return _select(coords, wrapped_coords, wrap_control_mask); } From efc9ae98ed5ddf488b555fd84b318762e68483f6 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 31 Dec 2024 00:36:31 +0300 Subject: [PATCH 4/9] vk: Fix out-of-bounds write when emitting MSAA unresolve clear command for NVIDIA fallback --- rpcs3/Emu/RSX/VK/VKResolveHelper.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKResolveHelper.h b/rpcs3/Emu/RSX/VK/VKResolveHelper.h index ab9e827db9..6b83a5af9c 100644 --- a/rpcs3/Emu/RSX/VK/VKResolveHelper.h +++ b/rpcs3/Emu/RSX/VK/VKResolveHelper.h @@ -387,7 +387,7 @@ namespace vk struct stencilonly_unresolve : depth_resolve_base { - VkClearRect region{}; + VkClearRect clear_region{}; VkClearAttachment clear_info{}; stencilonly_unresolve() @@ -402,8 +402,8 @@ namespace vk renderpass_config.set_depth_mask(false); clear_info.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - region.baseArrayLayer = 0; - region.layerCount = 1; + clear_region.baseArrayLayer = 0; + clear_region.layerCount = 1; static_parameters_width = 3; @@ -425,7 +425,7 @@ namespace vk void emit_geometry(vk::command_buffer& cmd) override { - vkCmdClearAttachments(cmd, 1, &clear_info, 1, ®ion); + vkCmdClearAttachments(cmd, 1, &clear_info, 1, &clear_region); for (s32 write_mask = 0x1; write_mask <= 0x80; write_mask <<= 1) { @@ -444,8 +444,8 @@ namespace vk auto stencil_view = resolve_image->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_IDENTITY), VK_IMAGE_ASPECT_STENCIL_BIT); - region.rect.extent.width = resolve_image->width(); - region.rect.extent.height = resolve_image->height(); + clear_region.rect.extent.width = msaa_image->width(); + clear_region.rect.extent.height = msaa_image->height(); overlay_pass::run( cmd, From 09580594e68619dc6421b56557e640648f5b2546 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Thu, 16 Jan 2025 01:03:42 +0300 Subject: [PATCH 5/9] rsx: Fix shader cache loading --- rpcs3/Emu/RSX/rsx_cache.h | 1 + 1 file changed, 1 insertion(+) diff --git a/rpcs3/Emu/RSX/rsx_cache.h b/rpcs3/Emu/RSX/rsx_cache.h index 7f82c210d9..f5eca2c85b 100644 --- a/rpcs3/Emu/RSX/rsx_cache.h +++ b/rpcs3/Emu/RSX/rsx_cache.h @@ -400,6 +400,7 @@ namespace rsx fp.texture_state.multisampled_textures = data.fp_multisampled_textures; fp.texcoord_control_mask = data.fp_texcoord_control; fp.two_sided_lighting = !!(data.fp_lighting_flags & 0x1); + fp.mrt_buffers_count = data.fp_mrt_count; return result; } From 5c2c4a66490db0bc5a8e282699939fdd823e0dae Mon Sep 17 00:00:00 2001 From: Megamouse Date: Tue, 14 Jan 2025 00:03:56 +0100 Subject: [PATCH 6/9] input: issue basic mouse move event on window leave This may help with moving the mouse to the screen borders in windowed mode --- rpcs3/Emu/Io/MouseHandler.cpp | 6 +-- rpcs3/Emu/Io/MouseHandler.h | 2 +- rpcs3/Input/basic_mouse_handler.cpp | 84 +++++++++++++++++------------ rpcs3/Input/basic_mouse_handler.h | 1 + 4 files changed, 56 insertions(+), 37 deletions(-) diff --git a/rpcs3/Emu/Io/MouseHandler.cpp b/rpcs3/Emu/Io/MouseHandler.cpp index b6c09bcb0d..c80d7556dc 100644 --- a/rpcs3/Emu/Io/MouseHandler.cpp +++ b/rpcs3/Emu/Io/MouseHandler.cpp @@ -31,12 +31,12 @@ void MouseHandlerBase::save(utils::serial& ar) ar(inited ? m_info.max_connect : 0); } -bool MouseHandlerBase::is_time_for_update(double elapsed_time) +bool MouseHandlerBase::is_time_for_update(double elapsed_time_ms) { steady_clock::time_point now = steady_clock::now(); - const double elapsed = (now - last_update).count() / 1000'000.; + const double elapsed_ms = (now - last_update).count() / 1'000'000.; - if (elapsed > elapsed_time) + if (elapsed_ms > elapsed_time_ms) { last_update = now; return true; diff --git a/rpcs3/Emu/Io/MouseHandler.h b/rpcs3/Emu/Io/MouseHandler.h index 007f71ee23..8a88241523 100644 --- a/rpcs3/Emu/Io/MouseHandler.h +++ b/rpcs3/Emu/Io/MouseHandler.h @@ -127,7 +127,7 @@ protected: std::vector m_mice; steady_clock::time_point last_update{}; - bool is_time_for_update(double elapsed_time = 10.0); // 4-10 ms, let's use 10 for now + bool is_time_for_update(double elapsed_time_ms = 10.0); // 4-10 ms, let's use 10 for now public: shared_mutex mutex; diff --git a/rpcs3/Input/basic_mouse_handler.cpp b/rpcs3/Input/basic_mouse_handler.cpp index 30eed46cbd..4ce238441b 100644 --- a/rpcs3/Input/basic_mouse_handler.cpp +++ b/rpcs3/Input/basic_mouse_handler.cpp @@ -125,6 +125,18 @@ bool basic_mouse_handler::eventFilter(QObject* target, QEvent* ev) case QEvent::KeyRelease: Key(static_cast(ev), false); break; + case QEvent::Leave: + { + // Issue mouse move on leave. Otherwise we may not get any mouse event at the screen borders. + const QPoint window_pos = m_target->mapToGlobal(m_target->position()) / m_target->devicePixelRatio(); + const QPoint cursor_pos = QCursor::pos() - window_pos; + + if (cursor_pos.x() <= 0 || cursor_pos.x() >= m_target->width() || cursor_pos.y() <= 0 || cursor_pos.y() >= m_target->height()) + { + MouseMove(cursor_pos); + } + break; + } default: return false; } @@ -218,38 +230,44 @@ void basic_mouse_handler::MouseMove(QMouseEvent* event) if (is_time_for_update()) { - // get the screen dimensions - const QSize screen = m_target->size(); - const QPoint e_pos = event->pos(); - - if (m_target && m_target->isActive() && get_mouse_lock_state()) - { - // get the center of the screen in global coordinates - QPoint p_center = m_target->geometry().topLeft() + QPoint(screen.width() / 2, screen.height() / 2); - - // reset the mouse to the center for consistent results since edge movement won't be registered - QCursor::setPos(m_target->screen(), p_center); - - // convert the center into screen coordinates - p_center = m_target->mapFromGlobal(p_center); - - // current mouse position, starting at the center - static QPoint p_real(p_center); - - // get the delta of the mouse position to the screen center - const QPoint p_delta = e_pos - p_center; - - // update the current position without leaving the screen borders - p_real.setX(std::clamp(p_real.x() + p_delta.x(), 0, screen.width())); - p_real.setY(std::clamp(p_real.y() + p_delta.y(), 0, screen.height())); - - // pass the 'real' position and the current delta to the screen center - MouseHandlerBase::Move(0, p_real.x(), p_real.y(), screen.width(), screen.height(), true, p_delta.x(), p_delta.y()); - } - else - { - // pass the absolute position - MouseHandlerBase::Move(0, e_pos.x(), e_pos.y(), screen.width(), screen.height()); - } + MouseMove(event->pos()); + } +} + +void basic_mouse_handler::MouseMove(const QPoint& e_pos) +{ + if (!m_target) return; + + // get the screen dimensions + const QSize screen = m_target->size(); + + if (m_target->isActive() && get_mouse_lock_state()) + { + // get the center of the screen in global coordinates + QPoint p_center = m_target->geometry().topLeft() + QPoint(screen.width() / 2, screen.height() / 2); + + // reset the mouse to the center for consistent results since edge movement won't be registered + QCursor::setPos(m_target->screen(), p_center); + + // convert the center into screen coordinates + p_center = m_target->mapFromGlobal(p_center); + + // current mouse position, starting at the center + static QPoint p_real(p_center); + + // get the delta of the mouse position to the screen center + const QPoint p_delta = e_pos - p_center; + + // update the current position without leaving the screen borders + p_real.setX(std::clamp(p_real.x() + p_delta.x(), 0, screen.width())); + p_real.setY(std::clamp(p_real.y() + p_delta.y(), 0, screen.height())); + + // pass the 'real' position and the current delta to the screen center + MouseHandlerBase::Move(0, p_real.x(), p_real.y(), screen.width(), screen.height(), true, p_delta.x(), p_delta.y()); + } + else + { + // pass the absolute position + MouseHandlerBase::Move(0, e_pos.x(), e_pos.y(), screen.width(), screen.height()); } } diff --git a/rpcs3/Input/basic_mouse_handler.h b/rpcs3/Input/basic_mouse_handler.h index 2c5b58ab80..e10dafc2f6 100644 --- a/rpcs3/Input/basic_mouse_handler.h +++ b/rpcs3/Input/basic_mouse_handler.h @@ -24,6 +24,7 @@ public: void MouseButton(QMouseEvent* event, bool pressed); void MouseScroll(QWheelEvent* event); void MouseMove(QMouseEvent* event); + void MouseMove(const QPoint& e_pos); bool eventFilter(QObject* obj, QEvent* ev) override; private: From 451e953d26a2ddee066c1f5ae60d41eb60fd751a Mon Sep 17 00:00:00 2001 From: Megamouse Date: Thu, 2 Jan 2025 12:24:25 +0100 Subject: [PATCH 7/9] windows: move config.yml and games.yml to /config/ --- Utilities/File.cpp | 10 +++++++++- Utilities/File.h | 4 ++-- Utilities/bin_patch.cpp | 10 +++------- rpcs3/Emu/IPC_config.cpp | 8 ++------ rpcs3/Emu/Io/camera_config.cpp | 6 +----- rpcs3/Emu/Io/emulated_pad_config.h | 4 ++-- rpcs3/Emu/Io/mouse_config.cpp | 6 +----- rpcs3/Emu/Io/rb3drums_config.cpp | 8 +------- rpcs3/Emu/Io/recording_config.cpp | 6 +----- rpcs3/Emu/NP/np_handler.cpp | 8 ++------ rpcs3/Emu/NP/rpcn_config.cpp | 8 ++------ rpcs3/Emu/NP/upnp_config.cpp | 8 ++------ rpcs3/Emu/System.cpp | 19 +++++++++++++++++-- rpcs3/Emu/games_config.cpp | 21 +++++++++++++++++++-- rpcs3/Emu/system_utils.cpp | 12 ++---------- rpcs3/Emu/vfs_config.cpp | 8 ++------ rpcs3/Input/ps_move_config.cpp | 6 +----- rpcs3/Input/raw_mouse_config.cpp | 4 ++-- rpcs3/rpcs3qt/emu_settings.cpp | 4 ++-- rpcs3/rpcs3qt/uuid.cpp | 10 +++------- 20 files changed, 76 insertions(+), 94 deletions(-) diff --git a/Utilities/File.cpp b/Utilities/File.cpp index e2dd842ae6..3753c68271 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -2021,7 +2021,7 @@ std::string fs::get_executable_dir() return s_exe_dir; } -const std::string& fs::get_config_dir() +const std::string& fs::get_config_dir([[maybe_unused]] bool get_config_subdirectory) { // Use magic static static const std::string s_dir = [] @@ -2103,6 +2103,14 @@ const std::string& fs::get_config_dir() return dir; }(); +#ifdef _WIN32 + if (get_config_subdirectory) + { + static const std::string subdir = s_dir + "config/"; + return subdir; + } +#endif + return s_dir; } diff --git a/Utilities/File.h b/Utilities/File.h index 4768b24ac0..7773eb8db0 100644 --- a/Utilities/File.h +++ b/Utilities/File.h @@ -599,8 +599,8 @@ namespace fs // Get executable containing directory std::string get_executable_dir(); - // Get configuration directory - const std::string& get_config_dir(); + // Get configuration directory. Set get_config_subdirectory to true to get the nested config dir on windows. + const std::string& get_config_dir(bool get_config_subdirectory = false); // Get common cache directory const std::string& get_cache_dir(); diff --git a/Utilities/bin_patch.cpp b/Utilities/bin_patch.cpp index 933e148e2e..e726d9dbc8 100644 --- a/Utilities/bin_patch.cpp +++ b/Utilities/bin_patch.cpp @@ -125,19 +125,15 @@ patch_engine::patch_engine() std::string patch_engine::get_patch_config_path() { -#ifdef _WIN32 - const std::string config_dir = fs::get_config_dir() + "config/"; + const std::string config_dir = fs::get_config_dir(true); const std::string patch_path = config_dir + "patch_config.yml"; - +#ifdef _WIN32 if (!fs::create_path(config_dir)) { patch_log.error("Could not create path: %s (%s)", patch_path, fs::g_tls_error); } - - return patch_path; -#else - return fs::get_config_dir() + "patch_config.yml"; #endif + return patch_path; } std::string patch_engine::get_patches_path() diff --git a/rpcs3/Emu/IPC_config.cpp b/rpcs3/Emu/IPC_config.cpp index 5aa95f4c34..6a51e80324 100644 --- a/rpcs3/Emu/IPC_config.cpp +++ b/rpcs3/Emu/IPC_config.cpp @@ -25,7 +25,7 @@ void cfg_ipc::load() void cfg_ipc::save() const { #ifdef _WIN32 - const std::string path_to_cfg = fs::get_config_dir() + "config/"; + const std::string path_to_cfg = fs::get_config_dir(true); if (!fs::create_path(path_to_cfg)) { IPC.error("Could not create path: %s", path_to_cfg); @@ -42,11 +42,7 @@ void cfg_ipc::save() const std::string cfg_ipc::get_path() { -#ifdef _WIN32 - return fs::get_config_dir() + "config/ipc.yml"; -#else - return fs::get_config_dir() + "ipc.yml"; -#endif + return fs::get_config_dir(true) + "ipc.yml"; } bool cfg_ipc::get_server_enabled() const diff --git a/rpcs3/Emu/Io/camera_config.cpp b/rpcs3/Emu/Io/camera_config.cpp index 9767405646..d7071b05c3 100644 --- a/rpcs3/Emu/Io/camera_config.cpp +++ b/rpcs3/Emu/Io/camera_config.cpp @@ -8,11 +8,7 @@ cfg_camera g_cfg_camera; cfg_camera::cfg_camera() : cfg::node() -#ifdef _WIN32 - , path(fs::get_config_dir() + "config/camera.yml") -#else - , path(fs::get_config_dir() + "camera.yml") -#endif + , path(fs::get_config_dir(true) + "camera.yml") { } diff --git a/rpcs3/Emu/Io/emulated_pad_config.h b/rpcs3/Emu/Io/emulated_pad_config.h index 3b0887459c..ad74e0dfc2 100644 --- a/rpcs3/Emu/Io/emulated_pad_config.h +++ b/rpcs3/Emu/Io/emulated_pad_config.h @@ -235,7 +235,7 @@ struct emulated_pads_config : cfg::node m_mutex.lock(); bool result = false; - const std::string cfg_name = fmt::format("%sconfig/%s.yml", fs::get_config_dir(), cfg_id); + const std::string cfg_name = fmt::format("%s%s.yml", fs::get_config_dir(true), cfg_id); cfg_log.notice("Loading %s config: %s", cfg_id, cfg_name); from_default(); @@ -272,7 +272,7 @@ struct emulated_pads_config : cfg::node { std::lock_guard lock(m_mutex); - const std::string cfg_name = fmt::format("%sconfig/%s.yml", fs::get_config_dir(), cfg_id); + const std::string cfg_name = fmt::format("%s%s.yml", fs::get_config_dir(true), cfg_id); cfg_log.notice("Saving %s config to '%s'", cfg_id, cfg_name); if (!fs::create_path(fs::get_parent_dir(cfg_name))) diff --git a/rpcs3/Emu/Io/mouse_config.cpp b/rpcs3/Emu/Io/mouse_config.cpp index b7dcec7e59..07ec4b525a 100644 --- a/rpcs3/Emu/Io/mouse_config.cpp +++ b/rpcs3/Emu/Io/mouse_config.cpp @@ -4,11 +4,7 @@ #include "Utilities/File.h" mouse_config::mouse_config() -#ifdef _WIN32 - : cfg_name(fs::get_config_dir() + "config/config_mouse.yml") -#else - : cfg_name(fs::get_config_dir() + "config_mouse.yml") -#endif + : cfg_name(fs::get_config_dir(true) + "config_mouse.yml") { } diff --git a/rpcs3/Emu/Io/rb3drums_config.cpp b/rpcs3/Emu/Io/rb3drums_config.cpp index 1e308d8b70..34c289818c 100644 --- a/rpcs3/Emu/Io/rb3drums_config.cpp +++ b/rpcs3/Emu/Io/rb3drums_config.cpp @@ -8,13 +8,7 @@ cfg_rb3drums g_cfg_rb3drums; cfg_rb3drums::cfg_rb3drums() : cfg::node() -#ifdef _WIN32 - , - path(fs::get_config_dir() + "config/rb3drums.yml") -#else - , - path(fs::get_config_dir() + "rb3drums.yml") -#endif + , path(fs::get_config_dir(true) + "rb3drums.yml") { } diff --git a/rpcs3/Emu/Io/recording_config.cpp b/rpcs3/Emu/Io/recording_config.cpp index 0457317d80..357106e074 100644 --- a/rpcs3/Emu/Io/recording_config.cpp +++ b/rpcs3/Emu/Io/recording_config.cpp @@ -8,11 +8,7 @@ cfg_recording g_cfg_recording; cfg_recording::cfg_recording() : cfg::node() -#ifdef _WIN32 - , path(fs::get_config_dir() + "config/recording.yml") -#else - , path(fs::get_config_dir() + "recording.yml") -#endif + , path(fs::get_config_dir(true) + "recording.yml") { } diff --git a/rpcs3/Emu/NP/np_handler.cpp b/rpcs3/Emu/NP/np_handler.cpp index 3bcff2f960..7c9723a25f 100644 --- a/rpcs3/Emu/NP/np_handler.cpp +++ b/rpcs3/Emu/NP/np_handler.cpp @@ -59,11 +59,7 @@ namespace np { std::string get_players_history_path() { -#ifdef _WIN32 - return fs::get_config_dir() + "config/players_history.yml"; -#else - return fs::get_config_dir() + "players_history.yml"; -#endif + return fs::get_config_dir(true) + "players_history.yml"; } std::map load_players_history() @@ -1440,7 +1436,7 @@ namespace np void np_handler::save_players_history() { #ifdef _WIN32 - const std::string path_to_cfg = fs::get_config_dir() + "config/"; + const std::string path_to_cfg = fs::get_config_dir(true); if (!fs::create_path(path_to_cfg)) { nph_log.error("Could not create path: %s", path_to_cfg); diff --git a/rpcs3/Emu/NP/rpcn_config.cpp b/rpcs3/Emu/NP/rpcn_config.cpp index ff802e554e..1f52d60a05 100644 --- a/rpcs3/Emu/NP/rpcn_config.cpp +++ b/rpcs3/Emu/NP/rpcn_config.cpp @@ -34,7 +34,7 @@ void cfg_rpcn::load() void cfg_rpcn::save() const { #ifdef _WIN32 - const std::string path_to_cfg = fs::get_config_dir() + "config/"; + const std::string path_to_cfg = fs::get_config_dir(true); if (!fs::create_path(path_to_cfg)) { rpcn_log.error("Could not create path: %s", path_to_cfg); @@ -51,11 +51,7 @@ void cfg_rpcn::save() const std::string cfg_rpcn::get_path() { -#ifdef _WIN32 - return fs::get_config_dir() + "config/rpcn.yml"; -#else - return fs::get_config_dir() + "rpcn.yml"; -#endif + return fs::get_config_dir(true) + "rpcn.yml"; } std::string cfg_rpcn::generate_npid() diff --git a/rpcs3/Emu/NP/upnp_config.cpp b/rpcs3/Emu/NP/upnp_config.cpp index 13a4f72698..bf43b8e55b 100644 --- a/rpcs3/Emu/NP/upnp_config.cpp +++ b/rpcs3/Emu/NP/upnp_config.cpp @@ -24,7 +24,7 @@ void cfg_upnp::load() void cfg_upnp::save() const { #ifdef _WIN32 - const std::string path_to_cfg = fs::get_config_dir() + "config/"; + const std::string path_to_cfg = fs::get_config_dir(true); if (!fs::create_path(path_to_cfg)) { upnp_cfg_log.error("Could not create path: %s", path_to_cfg); @@ -51,9 +51,5 @@ void cfg_upnp::set_device_url(std::string_view url) std::string cfg_upnp::get_path() { -#ifdef _WIN32 - return fs::get_config_dir() + "config/upnp.yml"; -#else - return fs::get_config_dir() + "upnp.yml"; -#endif + return fs::get_config_dir(true) + "upnp.yml"; } diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index dd41a5f71d..4ddf0df692 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -374,7 +374,22 @@ void Emulator::Init() g_cfg_defaults = g_cfg.to_string(); - const std::string cfg_path = fs::get_config_dir() + "/config.yml"; + const std::string cfg_path = fs::get_config_dir(true) + "config.yml"; + + // Move file from deprecated location to new location +#ifdef _WIN32 + const std::string old_path = fs::get_config_dir(false) + "config.yml"; + + if (fs::is_file(old_path)) + { + sys_log.notice("Found deprecated config.yml file: '%s'", old_path); + + if (!fs::rename(old_path, cfg_path, false)) + { + sys_log.error("Failed to move '%s' to '%s' (error='%s')", old_path, cfg_path, fs::g_tls_error); + } + } +#endif // Save new global config if it doesn't exist or is empty if (fs::stat_t info{}; !fs::get_stat(cfg_path, info) || info.size == 0) @@ -4466,7 +4481,7 @@ void Emulator::SaveSettings(const std::string& settings, const std::string& titl if (title_id.empty()) { - config_name = fs::get_config_dir() + "/config.yml"; + config_name = fs::get_config_dir(true) + "config.yml"; } else { diff --git a/rpcs3/Emu/games_config.cpp b/rpcs3/Emu/games_config.cpp index 0979a01585..27c086abdf 100644 --- a/rpcs3/Emu/games_config.cpp +++ b/rpcs3/Emu/games_config.cpp @@ -123,7 +123,7 @@ bool games_config::save_nl() YAML::Emitter out; out << m_games; - fs::pending_file temp(fs::get_config_dir() + "/games.yml"); + fs::pending_file temp(fs::get_config_dir(true) + "games.yml"); if (temp.file && temp.file.write(out.c_str(), out.size()) >= out.size() && temp.commit()) { @@ -147,7 +147,24 @@ void games_config::load() m_games.clear(); - if (fs::file f{fs::get_config_dir() + "/games.yml", fs::read + fs::create}) + const std::string path = fs::get_config_dir(true) + "games.yml"; + + // Move file from deprecated location to new location +#ifdef _WIN32 + const std::string old_path = fs::get_config_dir(false) + "games.yml"; + + if (fs::is_file(old_path)) + { + cfg_log.notice("Found deprecated games.yml file: '%s'", old_path); + + if (!fs::rename(old_path, path, false)) + { + cfg_log.error("Failed to move '%s' to '%s' (error='%s')", old_path, path, fs::g_tls_error); + } + } +#endif + + if (fs::file f{path, fs::read + fs::create}) { auto [result, error] = yaml_load(f.to_string()); diff --git a/rpcs3/Emu/system_utils.cpp b/rpcs3/Emu/system_utils.cpp index 050f0839c2..49439dc3fc 100644 --- a/rpcs3/Emu/system_utils.cpp +++ b/rpcs3/Emu/system_utils.cpp @@ -311,11 +311,7 @@ namespace rpcs3::utils std::string get_custom_config_dir() { -#ifdef _WIN32 - return fs::get_config_dir() + "config/custom_configs/"; -#else - return fs::get_config_dir() + "custom_configs/"; -#endif + return fs::get_config_dir(true) + "custom_configs/"; } std::string get_custom_config_path(const std::string& identifier) @@ -330,11 +326,7 @@ namespace rpcs3::utils std::string get_input_config_root() { -#ifdef _WIN32 - return fs::get_config_dir() + "config/input_configs/"; -#else - return fs::get_config_dir() + "input_configs/"; -#endif + return fs::get_config_dir(true) + "input_configs/"; } std::string get_input_config_dir(const std::string& title_id) diff --git a/rpcs3/Emu/vfs_config.cpp b/rpcs3/Emu/vfs_config.cpp index c650bfaeeb..0d7508a284 100644 --- a/rpcs3/Emu/vfs_config.cpp +++ b/rpcs3/Emu/vfs_config.cpp @@ -115,7 +115,7 @@ void cfg_vfs::load() void cfg_vfs::save() const { #ifdef _WIN32 - const std::string path_to_cfg = fs::get_config_dir() + "config/"; + const std::string path_to_cfg = fs::get_config_dir(true); if (!fs::create_path(path_to_cfg)) { vfs_log.error("Could not create path: %s", path_to_cfg); @@ -140,9 +140,5 @@ void cfg_vfs::save() const std::string cfg_vfs::get_path() { -#ifdef _WIN32 - return fs::get_config_dir() + "config/vfs.yml"; -#else - return fs::get_config_dir() + "vfs.yml"; -#endif + return fs::get_config_dir(true) + "vfs.yml"; } diff --git a/rpcs3/Input/ps_move_config.cpp b/rpcs3/Input/ps_move_config.cpp index 14f9d081fe..bb9daa528a 100644 --- a/rpcs3/Input/ps_move_config.cpp +++ b/rpcs3/Input/ps_move_config.cpp @@ -7,11 +7,7 @@ cfg_ps_moves g_cfg_move; cfg_ps_moves::cfg_ps_moves() : cfg::node() -#ifdef _WIN32 - , path(fs::get_config_dir() + "config/ps_move.yml") -#else - , path(fs::get_config_dir() + "ps_move.yml") -#endif + , path(fs::get_config_dir(true) + "ps_move.yml") { } diff --git a/rpcs3/Input/raw_mouse_config.cpp b/rpcs3/Input/raw_mouse_config.cpp index cc5506dd16..c5284c6ef5 100644 --- a/rpcs3/Input/raw_mouse_config.cpp +++ b/rpcs3/Input/raw_mouse_config.cpp @@ -96,7 +96,7 @@ bool raw_mice_config::load() m_mutex.lock(); bool result = false; - const std::string cfg_name = fmt::format("%sconfig/%s.yml", fs::get_config_dir(), cfg_id); + const std::string cfg_name = fmt::format("%s%s.yml", fs::get_config_dir(true), cfg_id); cfg_log.notice("Loading %s config: %s", cfg_id, cfg_name); from_default(); @@ -123,7 +123,7 @@ void raw_mice_config::save() { std::lock_guard lock(m_mutex); - const std::string cfg_name = fmt::format("%sconfig/%s.yml", fs::get_config_dir(), cfg_id); + const std::string cfg_name = fmt::format("%s%s.yml", fs::get_config_dir(true), cfg_id); cfg_log.notice("Saving %s config to '%s'", cfg_id, cfg_name); if (!fs::create_path(fs::get_parent_dir(cfg_name))) diff --git a/rpcs3/rpcs3qt/emu_settings.cpp b/rpcs3/rpcs3qt/emu_settings.cpp index 2b4d4a0b87..eb6439243a 100644 --- a/rpcs3/rpcs3qt/emu_settings.cpp +++ b/rpcs3/rpcs3qt/emu_settings.cpp @@ -93,7 +93,7 @@ void emu_settings::LoadSettings(const std::string& title_id, bool create_config_ m_title_id = title_id; // Create config path if necessary - fs::create_path(title_id.empty() ? fs::get_config_dir() : rpcs3::utils::get_custom_config_dir()); + fs::create_path(title_id.empty() ? fs::get_config_dir(true) : rpcs3::utils::get_custom_config_dir()); // Load default config auto [default_config, default_error] = yaml_load(g_cfg_defaults); @@ -113,7 +113,7 @@ void emu_settings::LoadSettings(const std::string& title_id, bool create_config_ if (create_config_from_global) { // Add global config - const std::string global_config_path = fs::get_config_dir() + "config.yml"; + const std::string global_config_path = fs::get_config_dir(true) + "config.yml"; fs::g_tls_error = fs::error::ok; fs::file config(global_config_path, fs::read + fs::create); auto [global_config, global_error] = yaml_load(config ? config.to_string() : ""); diff --git a/rpcs3/rpcs3qt/uuid.cpp b/rpcs3/rpcs3qt/uuid.cpp index 0ade0218d3..d3f3f58b77 100644 --- a/rpcs3/rpcs3qt/uuid.cpp +++ b/rpcs3/rpcs3qt/uuid.cpp @@ -13,19 +13,15 @@ namespace gui { std::string get_uuid_path() { -#ifdef _WIN32 - const std::string config_dir = fs::get_config_dir() + "config/"; + const std::string config_dir = fs::get_config_dir(true); const std::string uuid_path = config_dir + "uuid"; - +#ifdef _WIN32 if (!fs::create_path(config_dir)) { uuid_log.error("Could not create path: %s (%s)", uuid_path, fs::g_tls_error); } - - return uuid_path; -#else - return fs::get_config_dir() + "uuid"; #endif + return uuid_path; } std::string make_uuid() From a7edfa221e1853be823fc6949fe32c7d1b88b1f6 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Thu, 2 Jan 2025 17:42:05 +0100 Subject: [PATCH 8/9] windows: move logs to log dir --- Utilities/File.cpp | 10 ++++++ Utilities/File.h | 3 ++ rpcs3/Emu/System.cpp | 64 ++++++++++++++++++----------------- rpcs3/main.cpp | 2 +- rpcs3/rpcs3qt/log_frame.cpp | 2 +- rpcs3/rpcs3qt/main_window.cpp | 4 +-- 6 files changed, 50 insertions(+), 35 deletions(-) diff --git a/Utilities/File.cpp b/Utilities/File.cpp index 3753c68271..ec0f49c89e 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -2152,6 +2152,16 @@ const std::string& fs::get_cache_dir() return s_dir; } +const std::string& fs::get_log_dir() +{ +#ifdef _WIN32 + static const std::string s_dir = fs::get_config_dir() + "log/"; + return s_dir; +#else + return fs::get_cache_dir(); +#endif +} + const std::string& fs::get_temp_dir() { static const std::string s_dir = [] diff --git a/Utilities/File.h b/Utilities/File.h index 7773eb8db0..f3adaa15d4 100644 --- a/Utilities/File.h +++ b/Utilities/File.h @@ -605,6 +605,9 @@ namespace fs // Get common cache directory const std::string& get_cache_dir(); + // Get common log directory + const std::string& get_log_dir(); + // Temporary directory const std::string& get_temp_dir(); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 4ddf0df692..179eb7f1ad 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -347,9 +347,40 @@ void Emulator::Init() { jit_runtime::initialize(); + const std::string emu_dir = rpcs3::utils::get_emu_dir(); + auto make_path_verbose = [&](const std::string& path, bool must_exist_outside_emu_dir) + { + if (fs::is_dir(path)) + { + return true; + } + + if (must_exist_outside_emu_dir) + { + const std::string parent = fs::get_parent_dir(path); + const std::string emu_dir_no_delim = emu_dir.substr(0, emu_dir.find_last_not_of(fs::delim) + 1); + + if (parent != emu_dir_no_delim && GetCallbacks().resolve_path(parent) != GetCallbacks().resolve_path(emu_dir_no_delim)) + { + sys_log.fatal("Cannot use '%s' for Virtual File System because it does not exist.\nPlease specify an existing and writable directory path in Toolbar -> Manage -> Virtual File System.", path); + return false; + } + } + + if (!fs::create_path(path)) + { + sys_log.fatal("Failed to create path: %s (%s)", path, fs::g_tls_error); + return false; + } + + return true; + }; + if (!g_tty) { - const auto tty_path = fs::get_cache_dir() + "TTY.log"; + make_path_verbose(fs::get_log_dir(), true); + + const auto tty_path = fs::get_log_dir() + "TTY.log"; g_tty.open(tty_path, fs::rewrite + fs::append); if (!g_tty) @@ -402,7 +433,6 @@ void Emulator::Init() sys_log.notice("Using VFS config:\n%s", g_cfg_vfs.to_string()); // Mount all devices - const std::string emu_dir = rpcs3::utils::get_emu_dir(); const std::string elf_dir = fs::get_parent_dir(m_path); const std::string dev_bdvd = g_cfg_vfs.get(g_cfg_vfs.dev_bdvd, emu_dir); // Only used for make_path const std::string dev_hdd0 = g_cfg_vfs.get(g_cfg_vfs.dev_hdd0, emu_dir); @@ -502,34 +532,6 @@ void Emulator::Init() g_backup_cfg.from_string(g_cfg.to_string()); // Create directories (can be disabled if necessary) - auto make_path_verbose = [&](const std::string& path, bool must_exist_outside_emu_dir) - { - if (fs::is_dir(path)) - { - return true; - } - - if (must_exist_outside_emu_dir) - { - const std::string parent = fs::get_parent_dir(path); - const std::string emu_dir_no_delim = emu_dir.substr(0, emu_dir.find_last_not_of(fs::delim) + 1); - - if (parent != emu_dir_no_delim && GetCallbacks().resolve_path(parent) != GetCallbacks().resolve_path(emu_dir_no_delim)) - { - sys_log.fatal("Cannot use '%s' for Virtual File System because it does not exist.\nPlease specify an existing and writable directory path in Toolbar -> Manage -> Virtual File System.", path); - return false; - } - } - - if (!fs::create_path(path)) - { - sys_log.fatal("Failed to create path: %s (%s)", path, fs::g_tls_error); - return false; - } - - return true; - }; - const std::string save_path = dev_hdd0 + "home/" + m_usr + "/savedata/"; const std::string user_path = dev_hdd0 + "home/" + m_usr + "/localusername"; @@ -3636,7 +3638,7 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s if (usz attempted_read_size = utils::sub_saturate(g_tty.pos(), m_tty_file_init_pos)) { - if (fs::file tty_read_fd{fs::get_cache_dir() + "TTY.log"}) + if (fs::file tty_read_fd{fs::get_log_dir() + "TTY.log"}) { // Enforce an arbitrary limit for now to avoid OOM in case the guest code has bombarded TTY // 3MB, this should be enough diff --git a/rpcs3/main.cpp b/rpcs3/main.cpp index f67670ccc9..82002913d4 100644 --- a/rpcs3/main.cpp +++ b/rpcs3/main.cpp @@ -569,7 +569,7 @@ int main(int argc, char** argv) } const std::string lock_name = fs::get_cache_dir() + "RPCS3.buf"; - const std::string log_name = fs::get_cache_dir() + "RPCS3.log"; + const std::string log_name = fs::get_log_dir() + "RPCS3.log"; static fs::file instance_lock; diff --git a/rpcs3/rpcs3qt/log_frame.cpp b/rpcs3/rpcs3qt/log_frame.cpp index cde2803a30..a318a9c03d 100644 --- a/rpcs3/rpcs3qt/log_frame.cpp +++ b/rpcs3/rpcs3qt/log_frame.cpp @@ -157,7 +157,7 @@ log_frame::log_frame(std::shared_ptr _gui_settings, QWidget* paren setWidget(m_tabWidget); // Open or create TTY.log - m_tty_file.open(fs::get_cache_dir() + "TTY.log", fs::read + fs::create); + m_tty_file.open(fs::get_log_dir() + "TTY.log", fs::read + fs::create); CreateAndConnectActions(); LoadSettings(); diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index b4bc2af5d6..e23d9b32bc 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -2676,8 +2676,8 @@ void main_window::CreateConnects() return; } - const std::string archived_path = fs::get_cache_dir() + "RPCS3.log.gz"; - const std::string raw_file_path = fs::get_cache_dir() + "RPCS3.log"; + const std::string archived_path = fs::get_log_dir() + "RPCS3.log.gz"; + const std::string raw_file_path = fs::get_log_dir() + "RPCS3.log"; fs::stat_t raw_stat{}; fs::stat_t archived_stat{}; From 0a6f9ed9676d6886bb2aa678ab5c210045c50b5c Mon Sep 17 00:00:00 2001 From: Megamouse Date: Thu, 16 Jan 2025 23:29:13 +0100 Subject: [PATCH 9/9] windows: Ignore OneDrive in PATH. It leads to false positives --- rpcs3/main.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/rpcs3/main.cpp b/rpcs3/main.cpp index 82002913d4..894115ecc8 100644 --- a/rpcs3/main.cpp +++ b/rpcs3/main.cpp @@ -115,14 +115,16 @@ LOG_CHANNEL(q_debug, "QDEBUG"); std::set get_one_drive_paths() { std::set paths; - for (const char* key : { "OneDrive", "OneDriveConsumer", "OneDriveCommercial" }) - { - if (const char* env_path = std::getenv(key)) - { - sys_log.notice("get_one_drive_paths: Found OneDrive env path: '%s' (key='%s')", env_path, key); - paths.insert(env_path); - } - } + + // NOTE: Disabled. The environment variables can lead to false positives. + //for (const char* key : { "OneDrive", "OneDriveConsumer", "OneDriveCommercial" }) + //{ + // if (const char* env_path = std::getenv(key)) + // { + // sys_log.notice("get_one_drive_paths: Found OneDrive env path: '%s' (key='%s')", env_path, key); + // paths.insert(env_path); + // } + //} for (const wchar_t* key : { L"Software\\Microsoft\\OneDrive\\Accounts\\Personal" }) { @@ -135,7 +137,6 @@ std::set get_one_drive_paths() } std::wstring path_buffer; - static_cast(path_buffer.size() - 1); DWORD type = 0U; do @@ -154,7 +155,7 @@ std::set get_one_drive_paths() if (status != ERROR_SUCCESS) { - sys_log.error("get_one_drive_paths: RegQueryValueExW failed: %s", fmt::win_error{static_cast(status), nullptr}); + sys_log.trace("get_one_drive_paths: RegQueryValueExW failed: %s", fmt::win_error{static_cast(status), nullptr}); continue; }