From dc2e45bc89f63609db974d488bd55553328ed02d Mon Sep 17 00:00:00 2001 From: digant Date: Mon, 6 Jan 2025 14:41:21 +0100 Subject: [PATCH] update --- 3rdparty/wolfssl/CMakeLists.txt | 3 +- Utilities/Thread.h | 10 ++++-- Utilities/cheat_info.h | 1 + rpcs3/CMakeLists.txt | 2 +- rpcs3/Emu/Cell/lv2/sys_cond.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_config.cpp | 19 +++++++++- rpcs3/Emu/Cell/lv2/sys_config.h | 13 ++++--- rpcs3/Emu/Cell/lv2/sys_event.cpp | 4 +-- rpcs3/Emu/Cell/lv2/sys_event_flag.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_memory.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_mmapper.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_mutex.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_net.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_overlay.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_prx.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_sync.h | 2 +- rpcs3/Emu/IdManager.h | 10 +++--- rpcs3/Emu/RSX/VK/VKCompute.cpp | 1 + rpcs3/Emu/RSX/VK/VKHelpers.cpp | 3 ++ rpcs3/Emu/RSX/VK/VKRenderTargets.h | 1 + rpcs3/Emu/RSX/VK/vkutils/chip_class.h | 3 +- rpcs3/Emu/RSX/VK/vkutils/device.cpp | 13 +++++++ rpcs3/Emu/system_progress.cpp | 1 + rpcs3/rpcs3qt/cheat_manager.cpp | 43 ++++++++++++++--------- rpcs3/rpcs3qt/game_list_frame.cpp | 42 ++++++++++++++-------- rpcs3/rpcs3qt/main_window.cpp | 3 +- rpcs3/rpcs3qt/patch_manager_dialog.cpp | 11 +++++- rpcs3/util/fixed_typemap.hpp | 13 +++++++ rpcs3/util/shared_ptr.hpp | 40 ++++++++++++--------- 30 files changed, 177 insertions(+), 79 deletions(-) diff --git a/3rdparty/wolfssl/CMakeLists.txt b/3rdparty/wolfssl/CMakeLists.txt index f74f604269..cf1a66a1f5 100644 --- a/3rdparty/wolfssl/CMakeLists.txt +++ b/3rdparty/wolfssl/CMakeLists.txt @@ -22,6 +22,5 @@ else() add_subdirectory(wolfssl EXCLUDE_FROM_ALL) - target_compile_definitions(wolfssl PUBLIC WOLFSSL_DES_ECB HAVE_WRITE_DUP) - target_compile_definitions(wolfssl PUBLIC FP_MAX_BITS=8192) + target_compile_definitions(wolfssl PUBLIC WOLFSSL_DES_ECB HAVE_WRITE_DUP FP_MAX_BITS=8192 WOLFSSL_NO_OPTIONS_H) endif() diff --git a/Utilities/Thread.h b/Utilities/Thread.h index 4350915d70..37c4a56f4c 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -33,7 +33,8 @@ enum class thread_state : u32 aborting = 1, // The thread has been joined in the destructor or explicitly aborted errored = 2, // Set after the emergency_exit call finished = 3, // Final state, always set at the end of thread execution - mask = 3 + mask = 3, + destroying_context = 7, // Special value assigned to destroy data explicitly before the destructor }; template @@ -702,14 +703,17 @@ public: thread::m_sync.notify_all(); } - if (s == thread_state::finished) + if (s == thread_state::finished || s == thread_state::destroying_context) { // This participates in emulation stopping, use destruction-alike semantics thread::join(true); + } + if (s == thread_state::destroying_context) + { if constexpr (std::is_assignable_v) { - static_cast(*this) = thread_state::finished; + static_cast(*this) = thread_state::destroying_context; } } diff --git a/Utilities/cheat_info.h b/Utilities/cheat_info.h index 9c77d8dd7f..3ceb32716b 100644 --- a/Utilities/cheat_info.h +++ b/Utilities/cheat_info.h @@ -14,6 +14,7 @@ enum class cheat_type : u8 signed_16_cheat, signed_32_cheat, signed_64_cheat, + float_32_cheat, max }; diff --git a/rpcs3/CMakeLists.txt b/rpcs3/CMakeLists.txt index 059d0a4dbf..2b76f3c5e7 100644 --- a/rpcs3/CMakeLists.txt +++ b/rpcs3/CMakeLists.txt @@ -164,7 +164,7 @@ elseif(WIN32) COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/GuiConfigs $/GuiConfigs COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/git $/git COMMAND "${WINDEPLOYQT_EXECUTABLE}" --no-compiler-runtime --no-opengl-sw --no-patchqt - --no-translations --no-quick --no-system-d3d-compiler --no-quick-import + --no-translations --no-system-d3d-compiler --no-quick-import --plugindir "$,$/plugins,$/share/qt6/plugins>" --verbose 0 "$") endif() diff --git a/rpcs3/Emu/Cell/lv2/sys_cond.cpp b/rpcs3/Emu/Cell/lv2/sys_cond.cpp index bcfe83aed3..4387d27306 100644 --- a/rpcs3/Emu/Cell/lv2/sys_cond.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_cond.cpp @@ -71,7 +71,7 @@ CellError lv2_cond::on_id_create() std::function lv2_cond::load(utils::serial& ar) { - return load_func(make_shared(ar)); + return load_func(make_shared(stx::exact_t(ar))); } void lv2_cond::save(utils::serial& ar) diff --git a/rpcs3/Emu/Cell/lv2/sys_config.cpp b/rpcs3/Emu/Cell/lv2/sys_config.cpp index c39444ccd0..6740759d3b 100644 --- a/rpcs3/Emu/Cell/lv2/sys_config.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_config.cpp @@ -122,7 +122,7 @@ void lv2_config::remove_service_event(u32 id) lv2_config_service_event& lv2_config_service_event::operator=(thread_state s) noexcept { - if (s == thread_state::finished) + if (s == thread_state::destroying_context && !m_destroyed.exchange(true)) { if (auto global = g_fxo->try_get()) { @@ -133,6 +133,23 @@ lv2_config_service_event& lv2_config_service_event::operator=(thread_state s) no return *this; } +lv2_config_service_event::~lv2_config_service_event() noexcept +{ + operator=(thread_state::destroying_context); +} + +lv2_config::~lv2_config() noexcept +{ + for (auto& [key, event] : events) + { + if (event) + { + // Avoid collision with lv2_config_service_event destructor + event->m_destroyed = true; + } + } +} + // LV2 Config Service Listener bool lv2_config_service_listener::check_service(const lv2_config_service& service) const { diff --git a/rpcs3/Emu/Cell/lv2/sys_config.h b/rpcs3/Emu/Cell/lv2/sys_config.h index 3915dfc8cb..ea9b9da76d 100644 --- a/rpcs3/Emu/Cell/lv2/sys_config.h +++ b/rpcs3/Emu/Cell/lv2/sys_config.h @@ -161,6 +161,8 @@ public: return null_ptr; } + + ~lv2_config() noexcept; }; /* @@ -276,7 +278,7 @@ public: // Utilities usz get_size() const { return sizeof(sys_config_service_event_t)-1 + data.size(); } - shared_ptr get_shared_ptr () const { return idm::get_unlocked(idm_id); } + shared_ptr get_shared_ptr () const { return stx::make_shared_from_this(this); } u32 get_id() const { return idm_id; } }; @@ -342,7 +344,7 @@ public: // Utilities u32 get_id() const { return idm_id; } - shared_ptr get_shared_ptr() const { return idm::get_unlocked(idm_id); } + shared_ptr get_shared_ptr() const { return stx::make_shared_from_this(this); } }; /* @@ -360,6 +362,10 @@ class lv2_config_service_event return g_fxo->get().next_id++; } + atomic_t m_destroyed = false; + + friend class lv2_config; + public: const u32 id; @@ -391,8 +397,7 @@ public: // Destructor lv2_config_service_event& operator=(thread_state s) noexcept; - - ~lv2_config_service_event() noexcept = default; + ~lv2_config_service_event() noexcept; // Notify queue that this event exists bool notify() const; diff --git a/rpcs3/Emu/Cell/lv2/sys_event.cpp b/rpcs3/Emu/Cell/lv2/sys_event.cpp index 0428fd0f11..d5ad126142 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_event.cpp @@ -37,8 +37,8 @@ lv2_event_queue::lv2_event_queue(utils::serial& ar) noexcept std::function lv2_event_queue::load(utils::serial& ar) { - auto queue = make_shared(ar); - return [ptr = lv2_obj::load(queue->key, queue)](void* storage) { *static_cast*>(storage) = ptr; }; + auto queue = make_shared(stx::exact_t(ar)); + return [ptr = lv2_obj::load(queue->key, queue)](void* storage) { *static_cast*>(storage) = ptr; }; } void lv2_event_queue::save(utils::serial& ar) diff --git a/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp b/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp index 6c630e9261..971408e042 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp @@ -24,7 +24,7 @@ lv2_event_flag::lv2_event_flag(utils::serial& ar) std::function lv2_event_flag::load(utils::serial& ar) { - return load_func(make_shared(ar)); + return load_func(make_shared(stx::exact_t(ar))); } void lv2_event_flag::save(utils::serial& ar) diff --git a/rpcs3/Emu/Cell/lv2/sys_memory.cpp b/rpcs3/Emu/Cell/lv2/sys_memory.cpp index de5590426e..6cfc3a1860 100644 --- a/rpcs3/Emu/Cell/lv2/sys_memory.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_memory.cpp @@ -33,7 +33,7 @@ std::function lv2_memory_container::load(utils::serial& ar) // Use idm::last_id() only for the instances at IDM return [ptr = make_shared(stx::exact_t(ar), true)](void* storage) { - *static_cast*>(storage) = ptr; + *static_cast*>(storage) = ptr; }; } diff --git a/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp b/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp index d134102a73..805d5db0ad 100644 --- a/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp @@ -84,7 +84,7 @@ CellError lv2_memory::on_id_create() std::function lv2_memory::load(utils::serial& ar) { - auto mem = make_shared(ar); + auto mem = make_shared(stx::exact_t(ar)); mem->exists++; // Disable on_id_create() auto func = load_func(mem, +mem->pshared); mem->exists--; diff --git a/rpcs3/Emu/Cell/lv2/sys_mutex.cpp b/rpcs3/Emu/Cell/lv2/sys_mutex.cpp index c8ac190c25..f2d23291ff 100644 --- a/rpcs3/Emu/Cell/lv2/sys_mutex.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_mutex.cpp @@ -27,7 +27,7 @@ lv2_mutex::lv2_mutex(utils::serial& ar) std::function lv2_mutex::load(utils::serial& ar) { - return load_func(make_shared(ar)); + return load_func(make_shared(stx::exact_t(ar))); } void lv2_mutex::save(utils::serial& ar) diff --git a/rpcs3/Emu/Cell/lv2/sys_net.cpp b/rpcs3/Emu/Cell/lv2/sys_net.cpp index 97d40d6d47..aae2454619 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net.cpp @@ -293,7 +293,7 @@ std::function lv2_socket::load(utils::serial& ar) sock_lv2->bind(sock_lv2->last_bound_addr); } - return [ptr = sock_lv2](void* storage) { *static_cast*>(storage) = ptr; };; + return [ptr = sock_lv2](void* storage) { *static_cast*>(storage) = ptr; };; } void lv2_socket::save(utils::serial& ar, bool save_only_this_class) diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.cpp index d95c6935fc..7bdd18b3fd 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.cpp @@ -178,7 +178,7 @@ void lv2_socket::queue_wake(ppu_thread* ppu) lv2_socket& lv2_socket::operator=(thread_state s) noexcept { - if (s == thread_state::finished) + if (s == thread_state::destroying_context) { close(); } diff --git a/rpcs3/Emu/Cell/lv2/sys_overlay.cpp b/rpcs3/Emu/Cell/lv2/sys_overlay.cpp index 99b5981795..66481ed280 100644 --- a/rpcs3/Emu/Cell/lv2/sys_overlay.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_overlay.cpp @@ -112,7 +112,7 @@ std::function lv2_overlay::load(utils::serial& ar) return [ovlm](void* storage) { - *static_cast*>(storage) = ovlm; + *static_cast*>(storage) = ovlm; }; } diff --git a/rpcs3/Emu/Cell/lv2/sys_prx.cpp b/rpcs3/Emu/Cell/lv2/sys_prx.cpp index 42903d7454..f918070a4e 100644 --- a/rpcs3/Emu/Cell/lv2/sys_prx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_prx.cpp @@ -372,7 +372,7 @@ std::function lv2_prx::load(utils::serial& ar) return [prx](void* storage) { - *static_cast*>(storage) = prx; + *static_cast*>(storage) = prx; }; } diff --git a/rpcs3/Emu/Cell/lv2/sys_sync.h b/rpcs3/Emu/Cell/lv2/sys_sync.h index 644e0c90f2..bd6004dfaa 100644 --- a/rpcs3/Emu/Cell/lv2/sys_sync.h +++ b/rpcs3/Emu/Cell/lv2/sys_sync.h @@ -449,7 +449,7 @@ public: static std::function load_func(shared_ptr make, u64 pshared = umax) { const u64 key = make->key; - return [ptr = load(key, make, pshared)](void* storage) { *static_cast*>(storage) = ptr; }; + return [ptr = load(key, make, pshared)](void* storage) { *static_cast*>(storage) = ptr; }; } static bool wait_timeout(u64 usec, ppu_thread* cpu = {}, bool scale = true, bool is_usleep = false); diff --git a/rpcs3/Emu/IdManager.h b/rpcs3/Emu/IdManager.h index 99082462f9..7846d6f70f 100644 --- a/rpcs3/Emu/IdManager.h +++ b/rpcs3/Emu/IdManager.h @@ -123,7 +123,7 @@ namespace id_manager ptr = stx::make_shared(stx::exact_t(ar)); } - return [ptr](void* storage) { *static_cast*>(storage) = ptr; }; + return [ptr](void* storage) { *static_cast*>(storage) = ptr; }; }; }; @@ -805,8 +805,8 @@ public: { if (ptr) { - constexpr thread_state finished{3}; - *static_cast(ptr.get()) = finished; + constexpr thread_state destroying_context{7}; + *static_cast(ptr.get()) = destroying_context; } } @@ -837,8 +837,8 @@ public: { if (ptr) { - constexpr thread_state finished{3}; - *static_cast(ptr.get()) = finished; + constexpr thread_state destroying_context{7}; + *static_cast(ptr.get()) = destroying_context; } } diff --git a/rpcs3/Emu/RSX/VK/VKCompute.cpp b/rpcs3/Emu/RSX/VK/VKCompute.cpp index 499976b660..e7cfb617ba 100644 --- a/rpcs3/Emu/RSX/VK/VKCompute.cpp +++ b/rpcs3/Emu/RSX/VK/VKCompute.cpp @@ -78,6 +78,7 @@ namespace vk break; case vk::driver_vendor::LAVAPIPE: case vk::driver_vendor::V3DV: + case vk::driver_vendor::PANVK: // TODO: Actually bench this. Using 32 for now to match other common configurations. case vk::driver_vendor::DOZEN: // Actual optimal size depends on the D3D device. Use 32 since it should work well on both AMD and NVIDIA diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.cpp b/rpcs3/Emu/RSX/VK/VKHelpers.cpp index 7789661ef2..2a31ffa51d 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.cpp +++ b/rpcs3/Emu/RSX/VK/VKHelpers.cpp @@ -144,6 +144,9 @@ namespace vk case driver_vendor::HONEYKRISP: // Needs more testing break; + case driver_vendor::PANVK: + // Needs more testing + break; default: rsx_log.warning("Unsupported device: %s", gpu_name); } diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index 4bee28227a..19c9f04f63 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -190,6 +190,7 @@ namespace vk case driver_vendor::LAVAPIPE: case driver_vendor::V3DV: case driver_vendor::HONEYKRISP: + case driver_vendor::PANVK: break; } diff --git a/rpcs3/Emu/RSX/VK/vkutils/chip_class.h b/rpcs3/Emu/RSX/VK/vkutils/chip_class.h index 07b087d403..a905b7cc07 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/chip_class.h +++ b/rpcs3/Emu/RSX/VK/vkutils/chip_class.h @@ -54,7 +54,8 @@ namespace vk LAVAPIPE, NVK, V3DV, - HONEYKRISP + HONEYKRISP, + PANVK }; driver_vendor get_driver_vendor(); diff --git a/rpcs3/Emu/RSX/VK/vkutils/device.cpp b/rpcs3/Emu/RSX/VK/vkutils/device.cpp index 25b2a57d62..aa326982f6 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/device.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/device.cpp @@ -302,6 +302,11 @@ namespace vk return driver_vendor::HONEYKRISP; } + if (gpu_name.find("Panfrost") != umax) + { + return driver_vendor::PANVK; + } + return driver_vendor::unknown; } else @@ -329,6 +334,8 @@ namespace vk return driver_vendor::V3DV; case VK_DRIVER_ID_MESA_HONEYKRISP: return driver_vendor::HONEYKRISP; + case VK_DRIVER_ID_MESA_PANVK: + return driver_vendor::PANVK; default: // Mobile? return driver_vendor::unknown; @@ -659,6 +666,12 @@ namespace vk enabled_features.textureCompressionBC = VK_FALSE; } + if (!pgpu->features.textureCompressionBC && pgpu->get_driver_vendor() == driver_vendor::PANVK) + { + rsx_log.error("Your GPU running on the PANVK driver does not support full texture block compression. Graphics may not render correctly."); + enabled_features.textureCompressionBC = VK_FALSE; + } + VkDeviceCreateInfo device = {}; device.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device.pNext = nullptr; diff --git a/rpcs3/Emu/system_progress.cpp b/rpcs3/Emu/system_progress.cpp index feeaea352d..66d59af65b 100644 --- a/rpcs3/Emu/system_progress.cpp +++ b/rpcs3/Emu/system_progress.cpp @@ -41,6 +41,7 @@ void progress_dialog_server::operator()() { std::shared_ptr native_dlg; g_system_progress_stopping = false; + g_system_progress_canceled = false; const auto get_state = []() { diff --git a/rpcs3/rpcs3qt/cheat_manager.cpp b/rpcs3/rpcs3qt/cheat_manager.cpp index 27e0860232..d5af8a1a2f 100644 --- a/rpcs3/rpcs3qt/cheat_manager.cpp +++ b/rpcs3/rpcs3qt/cheat_manager.cpp @@ -43,6 +43,7 @@ void fmt_class_string::format(std::string& out, u64 arg) case cheat_type::signed_16_cheat: return "Signed 16 bits"; case cheat_type::signed_32_cheat: return "Signed 32 bits"; case cheat_type::signed_64_cheat: return "Signed 64 bits"; + case cheat_type::float_32_cheat: return "Float 32 bits"; case cheat_type::max: break; } @@ -612,8 +613,9 @@ cheat_manager_dialog::cheat_manager_dialog(QWidget* parent) return; } - bool success; - u64 result_value; + bool success = false; + u64 result_value {}; + f64 result_value_f {}; switch (cheat->type) { @@ -625,6 +627,7 @@ cheat_manager_dialog::cheat_manager_dialog(QWidget* parent) case cheat_type::signed_16_cheat: result_value = cheat_engine::get_value(final_offset, success); break; case cheat_type::signed_32_cheat: result_value = cheat_engine::get_value(final_offset, success); break; case cheat_type::signed_64_cheat: result_value = cheat_engine::get_value(final_offset, success); break; + case cheat_type::float_32_cheat: result_value_f = cheat_engine::get_value(final_offset, success); break; default: log_cheat.fatal("Unsupported cheat type"); return; } @@ -632,6 +635,8 @@ cheat_manager_dialog::cheat_manager_dialog(QWidget* parent) { if (cheat->type >= cheat_type::signed_8_cheat && cheat->type <= cheat_type::signed_64_cheat) edt_value_final->setText(tr("%1").arg(static_cast(result_value))); + else if (cheat->type == cheat_type::float_32_cheat) + edt_value_final->setText(tr("%1").arg(result_value_f)); else edt_value_final->setText(tr("%1").arg(result_value)); } @@ -795,6 +800,7 @@ cheat_manager_dialog::cheat_manager_dialog(QWidget* parent) case cheat_type::signed_16_cheat: results = convert_and_set(final_offset); break; case cheat_type::signed_32_cheat: results = convert_and_set(final_offset); break; case cheat_type::signed_64_cheat: results = convert_and_set(final_offset); break; + case cheat_type::float_32_cheat: results = convert_and_set(final_offset); break; default: log_cheat.fatal("Unsupported cheat type"); return; } @@ -888,8 +894,6 @@ cheat_manager_dialog* cheat_manager_dialog::get_dlg(QWidget* parent) template T cheat_manager_dialog::convert_from_QString(const QString& str, bool& success) { - T result; - if constexpr (std::is_same_v) { const u16 result_16 = str.toUShort(&success); @@ -897,17 +901,17 @@ T cheat_manager_dialog::convert_from_QString(const QString& str, bool& success) if (result_16 > 0xFF) success = false; - result = static_cast(result_16); + return static_cast(result_16); } if constexpr (std::is_same_v) - result = str.toUShort(&success); + return str.toUShort(&success); if constexpr (std::is_same_v) - result = str.toUInt(&success); + return str.toUInt(&success); if constexpr (std::is_same_v) - result = str.toULongLong(&success); + return str.toULongLong(&success); if constexpr (std::is_same_v) { @@ -915,28 +919,31 @@ T cheat_manager_dialog::convert_from_QString(const QString& str, bool& success) if (result_16 < -128 || result_16 > 127) success = false; - result = static_cast(result_16); + return static_cast(result_16); } if constexpr (std::is_same_v) - result = str.toShort(&success); + return str.toShort(&success); if constexpr (std::is_same_v) - result = str.toInt(&success); + return str.toInt(&success); if constexpr (std::is_same_v) - result = str.toLongLong(&success); + return str.toLongLong(&success); - return result; + if constexpr (std::is_same_v) + return str.toFloat(&success); + + return {}; } template bool cheat_manager_dialog::convert_and_search() { - bool res_conv; + bool res_conv = false; const QString to_search = edt_cheat_search_value->text(); - T value = convert_from_QString(to_search, res_conv); + const T value = convert_from_QString(to_search, res_conv); if (!res_conv) return false; @@ -948,10 +955,10 @@ bool cheat_manager_dialog::convert_and_search() template std::pair cheat_manager_dialog::convert_and_set(u32 offset) { - bool res_conv; + bool res_conv = false; const QString to_set = edt_value_final->text(); - T value = convert_from_QString(to_set, res_conv); + const T value = convert_from_QString(to_set, res_conv); if (!res_conv) return {false, false}; @@ -974,6 +981,7 @@ void cheat_manager_dialog::do_the_search() case cheat_type::signed_16_cheat: res_conv = convert_and_search(); break; case cheat_type::signed_32_cheat: res_conv = convert_and_search(); break; case cheat_type::signed_64_cheat: res_conv = convert_and_search(); break; + case cheat_type::float_32_cheat: res_conv = convert_and_search(); break; default: log_cheat.fatal("Unsupported cheat type"); break; } @@ -1065,6 +1073,7 @@ QString cheat_manager_dialog::get_localized_cheat_type(cheat_type type) case cheat_type::signed_16_cheat: return tr("Signed 16 bits"); case cheat_type::signed_32_cheat: return tr("Signed 32 bits"); case cheat_type::signed_64_cheat: return tr("Signed 64 bits"); + case cheat_type::float_32_cheat: return tr("Float 32 bits"); case cheat_type::max: break; } std::string type_formatted; diff --git a/rpcs3/rpcs3qt/game_list_frame.cpp b/rpcs3/rpcs3qt/game_list_frame.cpp index 12886b8664..02ca16716e 100644 --- a/rpcs3/rpcs3qt/game_list_frame.cpp +++ b/rpcs3/rpcs3qt/game_list_frame.cpp @@ -2277,11 +2277,13 @@ void game_list_frame::RemoveHDD1Cache(const std::string& base_dir, const std::st game_list_log.fatal("Only %d/%d HDD1 cache directories could be removed in %s (%s)", dirs_removed, dirs_total, base_dir, title_id); } -void game_list_frame::BatchActionBySerials(progress_dialog* pdlg, const std::set& serials, QString progressLabel, std::function action, std::function cancel_log, bool refresh_on_finish, bool can_be_concurrent, std::function should_wait_cb) +void game_list_frame::BatchActionBySerials(progress_dialog* pdlg, const std::set& serials, QString progressLabel, std::function action, std::function cancel_log, bool refresh_on_finish, bool can_be_concurrent, std::function should_wait_cb) { // Concurrent tasks should not wait (at least not in current implementation) ensure(!should_wait_cb || !can_be_concurrent); + g_system_progress_canceled = false; + const std::shared_ptr> iterate_over_serial = std::make_shared>(); const std::shared_ptr> index = std::make_shared>(0); @@ -2297,12 +2299,16 @@ void game_list_frame::BatchActionBySerials(progress_dialog* pdlg, const std::set const std::string& serial = *std::next(serials.begin(), index); - if (pdlg->wasCanceled() || g_system_progress_canceled) + if (pdlg->wasCanceled() || g_system_progress_canceled.exchange(false)) { - cancel_log(index, serials_size); + if (cancel_log) + { + cancel_log(index, serials_size); + } return false; } - else if (action(serial)) + + if (action(serial)) { const int done = index_ptr->load(); pdlg->setLabelText(progressLabel.arg(done + 1).arg(serials_size)); @@ -2360,19 +2366,17 @@ void game_list_frame::BatchActionBySerials(progress_dialog* pdlg, const std::set if ((*iterate_over_serial)(*index)) { QTimer::singleShot(1, this, *periodic_func); + return; } - else + + pdlg->setLabelText(progressLabel.arg(*index).arg(serials_size)); + pdlg->setCancelButtonText(tr("OK")); + connect(pdlg, &progress_dialog::canceled, this, [pdlg](){ pdlg->deleteLater(); }); + QApplication::beep(); + + if (refresh_on_finish && index) { - pdlg->setLabelText(progressLabel.arg(*index).arg(serials_size)); - pdlg->setCancelButtonText(tr("OK")); - QApplication::beep(); - - if (refresh_on_finish && index) - { - Refresh(true); - } - - pdlg->deleteLater(); + Refresh(true); } }; @@ -2414,6 +2418,14 @@ void game_list_frame::BatchCreateCPUCaches(const std::vector& game_da pdlg->setAutoReset(false); pdlg->open(); + connect(pdlg, &progress_dialog::canceled, this, []() + { + if (!Emu.IsStopped()) + { + Emu.GracefulShutdown(false, true); + } + }); + BatchActionBySerials(pdlg, serials, tr("%0\nProgress: %1/%2 caches compiled").arg(main_label), [&, game_data](const std::string& serial) { diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index 3526cce235..f499cd6474 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -394,7 +394,7 @@ void main_window::OnMissingFw() { const QString title = tr("Missing Firmware Detected!"); const QString message = tr("Commercial games require the firmware (PS3UPDAT.PUP file) to be installed." - "\n
For information about how to obtain the required firmware read the quickstart guide.").arg(gui::utils::get_link_style()); + "\n
For information about how to obtain the required firmware read the quickstart guide.").arg(gui::utils::get_link_style()); QMessageBox* mb = new QMessageBox(QMessageBox::Question, title, message, QMessageBox::Ok | QMessageBox::Cancel, this, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowStaysOnTopHint); mb->setTextFormat(Qt::RichText); @@ -2852,6 +2852,7 @@ void main_window::CreateConnects() connect(dlg, &settings_dialog::EmuSettingsApplied, this, &main_window::NotifyEmuSettingsChange); connect(dlg, &settings_dialog::EmuSettingsApplied, this, &main_window::update_gui_pad_thread); connect(dlg, &settings_dialog::EmuSettingsApplied, m_log_frame, &log_frame::LoadSettings); + dlg->setAttribute(Qt::WA_DeleteOnClose); dlg->open(); }; diff --git a/rpcs3/rpcs3qt/patch_manager_dialog.cpp b/rpcs3/rpcs3qt/patch_manager_dialog.cpp index 74b25a0b5c..a504e5790f 100644 --- a/rpcs3/rpcs3qt/patch_manager_dialog.cpp +++ b/rpcs3/rpcs3qt/patch_manager_dialog.cpp @@ -1247,7 +1247,16 @@ bool patch_manager_dialog::handle_json(const QByteArray& data) if (patch_engine::load(patches, "From Download", content, true, &log_message)) { patch_log.notice("Successfully validated downloaded patch file"); - const std::string path = patch_engine::get_patches_path() + "patch.yml"; + + const std::string patches_path = patch_engine::get_patches_path(); + + if (!fs::create_path(patches_path)) + { + patch_log.fatal("Failed to create path: %s (%s)", patches_path, fs::g_tls_error); + return false; + } + + const std::string path = patches_path + "patch.yml"; // Back up current patch file if possible if (fs::is_file(path)) diff --git a/rpcs3/util/fixed_typemap.hpp b/rpcs3/util/fixed_typemap.hpp index c742f8b03b..85d04c57a1 100644 --- a/rpcs3/util/fixed_typemap.hpp +++ b/rpcs3/util/fixed_typemap.hpp @@ -347,6 +347,19 @@ namespace stx } } + // Order semi-destructors before the actual destructors + // This allows to safely access data that may be deallocated or destroyed from other members of FXO regardless of their intialization time + for (u32 i = 0; i < _max; i++) + { + const auto info = (*std::prev(m_info, i + 1)); + + if (auto op = info->thread_op) + { + constexpr thread_state destroying_context{7}; + op(*std::prev(m_order, i + 1), destroying_context); + } + } + // Destroy objects in reverse order for (; _max; _max--) { diff --git a/rpcs3/util/shared_ptr.hpp b/rpcs3/util/shared_ptr.hpp index fb3c2c4019..e9bdf83b3b 100644 --- a/rpcs3/util/shared_ptr.hpp +++ b/rpcs3/util/shared_ptr.hpp @@ -361,13 +361,8 @@ namespace stx [[deprecated("Use null_ptr")]] shared_ptr(std::nullptr_t) = delete; // Not-so-aliasing constructor: emulates std::enable_shared_from_this without its overhead - explicit shared_ptr(T* _this) noexcept - : m_ptr(_this) - { - // Random checks which may fail on invalid pointer - ensure((reinterpret_cast(d()->destroy) - 0x10000) >> 47 == 0); - ensure((d()->refs++ - 1) >> 58 == 0); - } + template + friend shared_ptr make_shared_from_this(const Type* _this) noexcept; template requires same_ptr_implicit_v shared_ptr(const shared_ptr& r) noexcept @@ -562,11 +557,29 @@ namespace stx template requires (std::is_constructible_v, T&&>) - static shared_ptr> make_shared_value(T&& value) + static shared_ptr> make_shared_value(T&& value) noexcept { return make_single_value(std::forward(value)); } + // Not-so-aliasing constructor: emulates std::enable_shared_from_this without its overhead + template + static shared_ptr make_shared_from_this(const T* _this) noexcept + { + shared_ptr r; + r.m_ptr = const_cast(_this); + + if (!_this) [[unlikely]] + { + return r; + } + + // Random checks which may fail on invalid pointer + ensure((reinterpret_cast(r.d()->destroy.load()) - 0x10000) >> 47 == 0); + ensure((r.d()->refs++ - 1) >> 58 == 0); + return r; + } + // Atomic simplified shared pointer template class atomic_ptr @@ -1059,9 +1072,9 @@ namespace stx do { // Update old head with current value - next.m_ptr = reinterpret_cast(old.m_val.raw() >> c_ref_size); + next.m_ptr = std::launder(ptr_to(old.m_val.raw())); - } while (!m_val.compare_exchange(old.m_val.raw(), reinterpret_cast(exch.m_ptr) << c_ref_size)); + } while (!m_val.compare_exchange(old.m_val.raw(), to_val(exch.m_ptr))); // This argument is consumed (moved from) exch.m_ptr = nullptr; @@ -1076,7 +1089,7 @@ namespace stx // Simple atomic load is much more effective than load(), but it's a non-owning reference T* observe() const noexcept { - return reinterpret_cast(m_val >> c_ref_size); + return std::launder(ptr_to(m_val)); } explicit constexpr operator bool() const noexcept @@ -1138,11 +1151,6 @@ namespace stx return false; } - constexpr std::nullptr_t get() const noexcept - { - return nullptr; - } - } null_ptr; }