mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-08-06 00:00:04 +00:00
update
This commit is contained in:
parent
9d8f3b7bc4
commit
dc2e45bc89
30 changed files with 177 additions and 79 deletions
3
3rdparty/wolfssl/CMakeLists.txt
vendored
3
3rdparty/wolfssl/CMakeLists.txt
vendored
|
@ -22,6 +22,5 @@ else()
|
||||||
|
|
||||||
add_subdirectory(wolfssl EXCLUDE_FROM_ALL)
|
add_subdirectory(wolfssl EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
target_compile_definitions(wolfssl PUBLIC WOLFSSL_DES_ECB HAVE_WRITE_DUP)
|
target_compile_definitions(wolfssl PUBLIC WOLFSSL_DES_ECB HAVE_WRITE_DUP FP_MAX_BITS=8192 WOLFSSL_NO_OPTIONS_H)
|
||||||
target_compile_definitions(wolfssl PUBLIC FP_MAX_BITS=8192)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -33,7 +33,8 @@ enum class thread_state : u32
|
||||||
aborting = 1, // The thread has been joined in the destructor or explicitly aborted
|
aborting = 1, // The thread has been joined in the destructor or explicitly aborted
|
||||||
errored = 2, // Set after the emergency_exit call
|
errored = 2, // Set after the emergency_exit call
|
||||||
finished = 3, // Final state, always set at the end of thread execution
|
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 <class Context>
|
template <class Context>
|
||||||
|
@ -702,14 +703,17 @@ public:
|
||||||
thread::m_sync.notify_all();
|
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
|
// This participates in emulation stopping, use destruction-alike semantics
|
||||||
thread::join(true);
|
thread::join(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s == thread_state::destroying_context)
|
||||||
|
{
|
||||||
if constexpr (std::is_assignable_v<Context&, thread_state>)
|
if constexpr (std::is_assignable_v<Context&, thread_state>)
|
||||||
{
|
{
|
||||||
static_cast<Context&>(*this) = thread_state::finished;
|
static_cast<Context&>(*this) = thread_state::destroying_context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ enum class cheat_type : u8
|
||||||
signed_16_cheat,
|
signed_16_cheat,
|
||||||
signed_32_cheat,
|
signed_32_cheat,
|
||||||
signed_64_cheat,
|
signed_64_cheat,
|
||||||
|
float_32_cheat,
|
||||||
max
|
max
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,7 @@ elseif(WIN32)
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/GuiConfigs $<TARGET_FILE_DIR:rpcs3>/GuiConfigs
|
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/GuiConfigs $<TARGET_FILE_DIR:rpcs3>/GuiConfigs
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/git $<TARGET_FILE_DIR:rpcs3>/git
|
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/git $<TARGET_FILE_DIR:rpcs3>/git
|
||||||
COMMAND "${WINDEPLOYQT_EXECUTABLE}" --no-compiler-runtime --no-opengl-sw --no-patchqt
|
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 "$<IF:$<CXX_COMPILER_ID:MSVC>,$<TARGET_FILE_DIR:rpcs3>/plugins,$<TARGET_FILE_DIR:rpcs3>/share/qt6/plugins>"
|
--plugindir "$<IF:$<CXX_COMPILER_ID:MSVC>,$<TARGET_FILE_DIR:rpcs3>/plugins,$<TARGET_FILE_DIR:rpcs3>/share/qt6/plugins>"
|
||||||
--verbose 0 "$<TARGET_FILE:rpcs3>")
|
--verbose 0 "$<TARGET_FILE:rpcs3>")
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -71,7 +71,7 @@ CellError lv2_cond::on_id_create()
|
||||||
|
|
||||||
std::function<void(void*)> lv2_cond::load(utils::serial& ar)
|
std::function<void(void*)> lv2_cond::load(utils::serial& ar)
|
||||||
{
|
{
|
||||||
return load_func(make_shared<lv2_cond>(ar));
|
return load_func(make_shared<lv2_cond>(stx::exact_t<utils::serial&>(ar)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void lv2_cond::save(utils::serial& ar)
|
void lv2_cond::save(utils::serial& ar)
|
||||||
|
|
|
@ -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
|
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<lv2_config>())
|
if (auto global = g_fxo->try_get<lv2_config>())
|
||||||
{
|
{
|
||||||
|
@ -133,6 +133,23 @@ lv2_config_service_event& lv2_config_service_event::operator=(thread_state s) no
|
||||||
return *this;
|
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
|
// LV2 Config Service Listener
|
||||||
bool lv2_config_service_listener::check_service(const lv2_config_service& service) const
|
bool lv2_config_service_listener::check_service(const lv2_config_service& service) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -161,6 +161,8 @@ public:
|
||||||
|
|
||||||
return null_ptr;
|
return null_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~lv2_config() noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -276,7 +278,7 @@ public:
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
usz get_size() const { return sizeof(sys_config_service_event_t)-1 + data.size(); }
|
usz get_size() const { return sizeof(sys_config_service_event_t)-1 + data.size(); }
|
||||||
shared_ptr<lv2_config_service> get_shared_ptr () const { return idm::get_unlocked<lv2_config_service>(idm_id); }
|
shared_ptr<lv2_config_service> get_shared_ptr () const { return stx::make_shared_from_this<lv2_config_service>(this); }
|
||||||
u32 get_id() const { return idm_id; }
|
u32 get_id() const { return idm_id; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -342,7 +344,7 @@ public:
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
u32 get_id() const { return idm_id; }
|
u32 get_id() const { return idm_id; }
|
||||||
shared_ptr<lv2_config_service_listener> get_shared_ptr() const { return idm::get_unlocked<lv2_config_service_listener>(idm_id); }
|
shared_ptr<lv2_config_service_listener> get_shared_ptr() const { return stx::make_shared_from_this<lv2_config_service_listener>(this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -360,6 +362,10 @@ class lv2_config_service_event
|
||||||
return g_fxo->get<service_event_id>().next_id++;
|
return g_fxo->get<service_event_id>().next_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic_t<bool> m_destroyed = false;
|
||||||
|
|
||||||
|
friend class lv2_config;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const u32 id;
|
const u32 id;
|
||||||
|
|
||||||
|
@ -391,8 +397,7 @@ public:
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
lv2_config_service_event& operator=(thread_state s) noexcept;
|
lv2_config_service_event& operator=(thread_state s) noexcept;
|
||||||
|
~lv2_config_service_event() noexcept;
|
||||||
~lv2_config_service_event() noexcept = default;
|
|
||||||
|
|
||||||
// Notify queue that this event exists
|
// Notify queue that this event exists
|
||||||
bool notify() const;
|
bool notify() const;
|
||||||
|
|
|
@ -37,8 +37,8 @@ lv2_event_queue::lv2_event_queue(utils::serial& ar) noexcept
|
||||||
|
|
||||||
std::function<void(void*)> lv2_event_queue::load(utils::serial& ar)
|
std::function<void(void*)> lv2_event_queue::load(utils::serial& ar)
|
||||||
{
|
{
|
||||||
auto queue = make_shared<lv2_event_queue>(ar);
|
auto queue = make_shared<lv2_event_queue>(stx::exact_t<utils::serial&>(ar));
|
||||||
return [ptr = lv2_obj::load(queue->key, queue)](void* storage) { *static_cast<shared_ptr<lv2_obj>*>(storage) = ptr; };
|
return [ptr = lv2_obj::load(queue->key, queue)](void* storage) { *static_cast<atomic_ptr<lv2_obj>*>(storage) = ptr; };
|
||||||
}
|
}
|
||||||
|
|
||||||
void lv2_event_queue::save(utils::serial& ar)
|
void lv2_event_queue::save(utils::serial& ar)
|
||||||
|
|
|
@ -24,7 +24,7 @@ lv2_event_flag::lv2_event_flag(utils::serial& ar)
|
||||||
|
|
||||||
std::function<void(void*)> lv2_event_flag::load(utils::serial& ar)
|
std::function<void(void*)> lv2_event_flag::load(utils::serial& ar)
|
||||||
{
|
{
|
||||||
return load_func(make_shared<lv2_event_flag>(ar));
|
return load_func(make_shared<lv2_event_flag>(stx::exact_t<utils::serial&>(ar)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void lv2_event_flag::save(utils::serial& ar)
|
void lv2_event_flag::save(utils::serial& ar)
|
||||||
|
|
|
@ -33,7 +33,7 @@ std::function<void(void*)> lv2_memory_container::load(utils::serial& ar)
|
||||||
// Use idm::last_id() only for the instances at IDM
|
// Use idm::last_id() only for the instances at IDM
|
||||||
return [ptr = make_shared<lv2_memory_container>(stx::exact_t<utils::serial&>(ar), true)](void* storage)
|
return [ptr = make_shared<lv2_memory_container>(stx::exact_t<utils::serial&>(ar), true)](void* storage)
|
||||||
{
|
{
|
||||||
*static_cast<shared_ptr<lv2_memory_container>*>(storage) = ptr;
|
*static_cast<atomic_ptr<lv2_memory_container>*>(storage) = ptr;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ CellError lv2_memory::on_id_create()
|
||||||
|
|
||||||
std::function<void(void*)> lv2_memory::load(utils::serial& ar)
|
std::function<void(void*)> lv2_memory::load(utils::serial& ar)
|
||||||
{
|
{
|
||||||
auto mem = make_shared<lv2_memory>(ar);
|
auto mem = make_shared<lv2_memory>(stx::exact_t<utils::serial&>(ar));
|
||||||
mem->exists++; // Disable on_id_create()
|
mem->exists++; // Disable on_id_create()
|
||||||
auto func = load_func(mem, +mem->pshared);
|
auto func = load_func(mem, +mem->pshared);
|
||||||
mem->exists--;
|
mem->exists--;
|
||||||
|
|
|
@ -27,7 +27,7 @@ lv2_mutex::lv2_mutex(utils::serial& ar)
|
||||||
|
|
||||||
std::function<void(void*)> lv2_mutex::load(utils::serial& ar)
|
std::function<void(void*)> lv2_mutex::load(utils::serial& ar)
|
||||||
{
|
{
|
||||||
return load_func(make_shared<lv2_mutex>(ar));
|
return load_func(make_shared<lv2_mutex>(stx::exact_t<utils::serial&>(ar)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void lv2_mutex::save(utils::serial& ar)
|
void lv2_mutex::save(utils::serial& ar)
|
||||||
|
|
|
@ -293,7 +293,7 @@ std::function<void(void*)> lv2_socket::load(utils::serial& ar)
|
||||||
sock_lv2->bind(sock_lv2->last_bound_addr);
|
sock_lv2->bind(sock_lv2->last_bound_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [ptr = sock_lv2](void* storage) { *static_cast<shared_ptr<lv2_socket>*>(storage) = ptr; };;
|
return [ptr = sock_lv2](void* storage) { *static_cast<atomic_ptr<lv2_socket>*>(storage) = ptr; };;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lv2_socket::save(utils::serial& ar, bool save_only_this_class)
|
void lv2_socket::save(utils::serial& ar, bool save_only_this_class)
|
||||||
|
|
|
@ -178,7 +178,7 @@ void lv2_socket::queue_wake(ppu_thread* ppu)
|
||||||
|
|
||||||
lv2_socket& lv2_socket::operator=(thread_state s) noexcept
|
lv2_socket& lv2_socket::operator=(thread_state s) noexcept
|
||||||
{
|
{
|
||||||
if (s == thread_state::finished)
|
if (s == thread_state::destroying_context)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ std::function<void(void*)> lv2_overlay::load(utils::serial& ar)
|
||||||
|
|
||||||
return [ovlm](void* storage)
|
return [ovlm](void* storage)
|
||||||
{
|
{
|
||||||
*static_cast<shared_ptr<lv2_obj>*>(storage) = ovlm;
|
*static_cast<atomic_ptr<lv2_obj>*>(storage) = ovlm;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -372,7 +372,7 @@ std::function<void(void*)> lv2_prx::load(utils::serial& ar)
|
||||||
|
|
||||||
return [prx](void* storage)
|
return [prx](void* storage)
|
||||||
{
|
{
|
||||||
*static_cast<shared_ptr<lv2_obj>*>(storage) = prx;
|
*static_cast<atomic_ptr<lv2_obj>*>(storage) = prx;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -449,7 +449,7 @@ public:
|
||||||
static std::function<void(void*)> load_func(shared_ptr<T> make, u64 pshared = umax)
|
static std::function<void(void*)> load_func(shared_ptr<T> make, u64 pshared = umax)
|
||||||
{
|
{
|
||||||
const u64 key = make->key;
|
const u64 key = make->key;
|
||||||
return [ptr = load<T>(key, make, pshared)](void* storage) { *static_cast<shared_ptr<Storage>*>(storage) = ptr; };
|
return [ptr = load<T>(key, make, pshared)](void* storage) { *static_cast<atomic_ptr<Storage>*>(storage) = ptr; };
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool wait_timeout(u64 usec, ppu_thread* cpu = {}, bool scale = true, bool is_usleep = false);
|
static bool wait_timeout(u64 usec, ppu_thread* cpu = {}, bool scale = true, bool is_usleep = false);
|
||||||
|
|
|
@ -123,7 +123,7 @@ namespace id_manager
|
||||||
ptr = stx::make_shared<T>(stx::exact_t<utils::serial&>(ar));
|
ptr = stx::make_shared<T>(stx::exact_t<utils::serial&>(ar));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [ptr](void* storage) { *static_cast<stx::shared_ptr<T>*>(storage) = ptr; };
|
return [ptr](void* storage) { *static_cast<stx::atomic_ptr<T>*>(storage) = ptr; };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -805,8 +805,8 @@ public:
|
||||||
{
|
{
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
constexpr thread_state finished{3};
|
constexpr thread_state destroying_context{7};
|
||||||
*static_cast<Get*>(ptr.get()) = finished;
|
*static_cast<Get*>(ptr.get()) = destroying_context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -837,8 +837,8 @@ public:
|
||||||
{
|
{
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
constexpr thread_state finished{3};
|
constexpr thread_state destroying_context{7};
|
||||||
*static_cast<Get*>(ptr.get()) = finished;
|
*static_cast<Get*>(ptr.get()) = destroying_context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,7 @@ namespace vk
|
||||||
break;
|
break;
|
||||||
case vk::driver_vendor::LAVAPIPE:
|
case vk::driver_vendor::LAVAPIPE:
|
||||||
case vk::driver_vendor::V3DV:
|
case vk::driver_vendor::V3DV:
|
||||||
|
case vk::driver_vendor::PANVK:
|
||||||
// TODO: Actually bench this. Using 32 for now to match other common configurations.
|
// TODO: Actually bench this. Using 32 for now to match other common configurations.
|
||||||
case vk::driver_vendor::DOZEN:
|
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
|
// Actual optimal size depends on the D3D device. Use 32 since it should work well on both AMD and NVIDIA
|
||||||
|
|
|
@ -144,6 +144,9 @@ namespace vk
|
||||||
case driver_vendor::HONEYKRISP:
|
case driver_vendor::HONEYKRISP:
|
||||||
// Needs more testing
|
// Needs more testing
|
||||||
break;
|
break;
|
||||||
|
case driver_vendor::PANVK:
|
||||||
|
// Needs more testing
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
rsx_log.warning("Unsupported device: %s", gpu_name);
|
rsx_log.warning("Unsupported device: %s", gpu_name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,6 +190,7 @@ namespace vk
|
||||||
case driver_vendor::LAVAPIPE:
|
case driver_vendor::LAVAPIPE:
|
||||||
case driver_vendor::V3DV:
|
case driver_vendor::V3DV:
|
||||||
case driver_vendor::HONEYKRISP:
|
case driver_vendor::HONEYKRISP:
|
||||||
|
case driver_vendor::PANVK:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,8 @@ namespace vk
|
||||||
LAVAPIPE,
|
LAVAPIPE,
|
||||||
NVK,
|
NVK,
|
||||||
V3DV,
|
V3DV,
|
||||||
HONEYKRISP
|
HONEYKRISP,
|
||||||
|
PANVK
|
||||||
};
|
};
|
||||||
|
|
||||||
driver_vendor get_driver_vendor();
|
driver_vendor get_driver_vendor();
|
||||||
|
|
|
@ -302,6 +302,11 @@ namespace vk
|
||||||
return driver_vendor::HONEYKRISP;
|
return driver_vendor::HONEYKRISP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gpu_name.find("Panfrost") != umax)
|
||||||
|
{
|
||||||
|
return driver_vendor::PANVK;
|
||||||
|
}
|
||||||
|
|
||||||
return driver_vendor::unknown;
|
return driver_vendor::unknown;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -329,6 +334,8 @@ namespace vk
|
||||||
return driver_vendor::V3DV;
|
return driver_vendor::V3DV;
|
||||||
case VK_DRIVER_ID_MESA_HONEYKRISP:
|
case VK_DRIVER_ID_MESA_HONEYKRISP:
|
||||||
return driver_vendor::HONEYKRISP;
|
return driver_vendor::HONEYKRISP;
|
||||||
|
case VK_DRIVER_ID_MESA_PANVK:
|
||||||
|
return driver_vendor::PANVK;
|
||||||
default:
|
default:
|
||||||
// Mobile?
|
// Mobile?
|
||||||
return driver_vendor::unknown;
|
return driver_vendor::unknown;
|
||||||
|
@ -659,6 +666,12 @@ namespace vk
|
||||||
enabled_features.textureCompressionBC = VK_FALSE;
|
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 = {};
|
VkDeviceCreateInfo device = {};
|
||||||
device.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
device.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||||
device.pNext = nullptr;
|
device.pNext = nullptr;
|
||||||
|
|
|
@ -41,6 +41,7 @@ void progress_dialog_server::operator()()
|
||||||
{
|
{
|
||||||
std::shared_ptr<rsx::overlays::progress_dialog> native_dlg;
|
std::shared_ptr<rsx::overlays::progress_dialog> native_dlg;
|
||||||
g_system_progress_stopping = false;
|
g_system_progress_stopping = false;
|
||||||
|
g_system_progress_canceled = false;
|
||||||
|
|
||||||
const auto get_state = []()
|
const auto get_state = []()
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,6 +43,7 @@ void fmt_class_string<cheat_type>::format(std::string& out, u64 arg)
|
||||||
case cheat_type::signed_16_cheat: return "Signed 16 bits";
|
case cheat_type::signed_16_cheat: return "Signed 16 bits";
|
||||||
case cheat_type::signed_32_cheat: return "Signed 32 bits";
|
case cheat_type::signed_32_cheat: return "Signed 32 bits";
|
||||||
case cheat_type::signed_64_cheat: return "Signed 64 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;
|
case cheat_type::max: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,8 +613,9 @@ cheat_manager_dialog::cheat_manager_dialog(QWidget* parent)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success;
|
bool success = false;
|
||||||
u64 result_value;
|
u64 result_value {};
|
||||||
|
f64 result_value_f {};
|
||||||
|
|
||||||
switch (cheat->type)
|
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<s16>(final_offset, success); break;
|
case cheat_type::signed_16_cheat: result_value = cheat_engine::get_value<s16>(final_offset, success); break;
|
||||||
case cheat_type::signed_32_cheat: result_value = cheat_engine::get_value<s32>(final_offset, success); break;
|
case cheat_type::signed_32_cheat: result_value = cheat_engine::get_value<s32>(final_offset, success); break;
|
||||||
case cheat_type::signed_64_cheat: result_value = cheat_engine::get_value<s64>(final_offset, success); break;
|
case cheat_type::signed_64_cheat: result_value = cheat_engine::get_value<s64>(final_offset, success); break;
|
||||||
|
case cheat_type::float_32_cheat: result_value_f = cheat_engine::get_value<f32>(final_offset, success); break;
|
||||||
default: log_cheat.fatal("Unsupported cheat type"); return;
|
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)
|
if (cheat->type >= cheat_type::signed_8_cheat && cheat->type <= cheat_type::signed_64_cheat)
|
||||||
edt_value_final->setText(tr("%1").arg(static_cast<s64>(result_value)));
|
edt_value_final->setText(tr("%1").arg(static_cast<s64>(result_value)));
|
||||||
|
else if (cheat->type == cheat_type::float_32_cheat)
|
||||||
|
edt_value_final->setText(tr("%1").arg(result_value_f));
|
||||||
else
|
else
|
||||||
edt_value_final->setText(tr("%1").arg(result_value));
|
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<s16>(final_offset); break;
|
case cheat_type::signed_16_cheat: results = convert_and_set<s16>(final_offset); break;
|
||||||
case cheat_type::signed_32_cheat: results = convert_and_set<s32>(final_offset); break;
|
case cheat_type::signed_32_cheat: results = convert_and_set<s32>(final_offset); break;
|
||||||
case cheat_type::signed_64_cheat: results = convert_and_set<s64>(final_offset); break;
|
case cheat_type::signed_64_cheat: results = convert_and_set<s64>(final_offset); break;
|
||||||
|
case cheat_type::float_32_cheat: results = convert_and_set<f32>(final_offset); break;
|
||||||
default: log_cheat.fatal("Unsupported cheat type"); return;
|
default: log_cheat.fatal("Unsupported cheat type"); return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,8 +894,6 @@ cheat_manager_dialog* cheat_manager_dialog::get_dlg(QWidget* parent)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T cheat_manager_dialog::convert_from_QString(const QString& str, bool& success)
|
T cheat_manager_dialog::convert_from_QString(const QString& str, bool& success)
|
||||||
{
|
{
|
||||||
T result;
|
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, u8>)
|
if constexpr (std::is_same_v<T, u8>)
|
||||||
{
|
{
|
||||||
const u16 result_16 = str.toUShort(&success);
|
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)
|
if (result_16 > 0xFF)
|
||||||
success = false;
|
success = false;
|
||||||
|
|
||||||
result = static_cast<T>(result_16);
|
return static_cast<T>(result_16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, u16>)
|
if constexpr (std::is_same_v<T, u16>)
|
||||||
result = str.toUShort(&success);
|
return str.toUShort(&success);
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, u32>)
|
if constexpr (std::is_same_v<T, u32>)
|
||||||
result = str.toUInt(&success);
|
return str.toUInt(&success);
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, u64>)
|
if constexpr (std::is_same_v<T, u64>)
|
||||||
result = str.toULongLong(&success);
|
return str.toULongLong(&success);
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, s8>)
|
if constexpr (std::is_same_v<T, s8>)
|
||||||
{
|
{
|
||||||
|
@ -915,28 +919,31 @@ T cheat_manager_dialog::convert_from_QString(const QString& str, bool& success)
|
||||||
if (result_16 < -128 || result_16 > 127)
|
if (result_16 < -128 || result_16 > 127)
|
||||||
success = false;
|
success = false;
|
||||||
|
|
||||||
result = static_cast<T>(result_16);
|
return static_cast<T>(result_16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, s16>)
|
if constexpr (std::is_same_v<T, s16>)
|
||||||
result = str.toShort(&success);
|
return str.toShort(&success);
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, s32>)
|
if constexpr (std::is_same_v<T, s32>)
|
||||||
result = str.toInt(&success);
|
return str.toInt(&success);
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, s64>)
|
if constexpr (std::is_same_v<T, s64>)
|
||||||
result = str.toLongLong(&success);
|
return str.toLongLong(&success);
|
||||||
|
|
||||||
return result;
|
if constexpr (std::is_same_v<T, f32>)
|
||||||
|
return str.toFloat(&success);
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool cheat_manager_dialog::convert_and_search()
|
bool cheat_manager_dialog::convert_and_search()
|
||||||
{
|
{
|
||||||
bool res_conv;
|
bool res_conv = false;
|
||||||
const QString to_search = edt_cheat_search_value->text();
|
const QString to_search = edt_cheat_search_value->text();
|
||||||
|
|
||||||
T value = convert_from_QString<T>(to_search, res_conv);
|
const T value = convert_from_QString<T>(to_search, res_conv);
|
||||||
|
|
||||||
if (!res_conv)
|
if (!res_conv)
|
||||||
return false;
|
return false;
|
||||||
|
@ -948,10 +955,10 @@ bool cheat_manager_dialog::convert_and_search()
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::pair<bool, bool> cheat_manager_dialog::convert_and_set(u32 offset)
|
std::pair<bool, bool> cheat_manager_dialog::convert_and_set(u32 offset)
|
||||||
{
|
{
|
||||||
bool res_conv;
|
bool res_conv = false;
|
||||||
const QString to_set = edt_value_final->text();
|
const QString to_set = edt_value_final->text();
|
||||||
|
|
||||||
T value = convert_from_QString<T>(to_set, res_conv);
|
const T value = convert_from_QString<T>(to_set, res_conv);
|
||||||
|
|
||||||
if (!res_conv)
|
if (!res_conv)
|
||||||
return {false, false};
|
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<s16>(); break;
|
case cheat_type::signed_16_cheat: res_conv = convert_and_search<s16>(); break;
|
||||||
case cheat_type::signed_32_cheat: res_conv = convert_and_search<s32>(); break;
|
case cheat_type::signed_32_cheat: res_conv = convert_and_search<s32>(); break;
|
||||||
case cheat_type::signed_64_cheat: res_conv = convert_and_search<s64>(); break;
|
case cheat_type::signed_64_cheat: res_conv = convert_and_search<s64>(); break;
|
||||||
|
case cheat_type::float_32_cheat: res_conv = convert_and_search<f32>(); break;
|
||||||
default: log_cheat.fatal("Unsupported cheat type"); 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_16_cheat: return tr("Signed 16 bits");
|
||||||
case cheat_type::signed_32_cheat: return tr("Signed 32 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::signed_64_cheat: return tr("Signed 64 bits");
|
||||||
|
case cheat_type::float_32_cheat: return tr("Float 32 bits");
|
||||||
case cheat_type::max: break;
|
case cheat_type::max: break;
|
||||||
}
|
}
|
||||||
std::string type_formatted;
|
std::string type_formatted;
|
||||||
|
|
|
@ -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);
|
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<std::string>& serials, QString progressLabel, std::function<bool(const std::string&)> action, std::function<void(u32, u32)> cancel_log, bool refresh_on_finish, bool can_be_concurrent, std::function<bool()> should_wait_cb)
|
void game_list_frame::BatchActionBySerials(progress_dialog* pdlg, const std::set<std::string>& serials, QString progressLabel, std::function<bool(const std::string&)> action, std::function<void(u32, u32)> cancel_log, bool refresh_on_finish, bool can_be_concurrent, std::function<bool()> should_wait_cb)
|
||||||
{
|
{
|
||||||
// Concurrent tasks should not wait (at least not in current implementation)
|
// Concurrent tasks should not wait (at least not in current implementation)
|
||||||
ensure(!should_wait_cb || !can_be_concurrent);
|
ensure(!should_wait_cb || !can_be_concurrent);
|
||||||
|
|
||||||
|
g_system_progress_canceled = false;
|
||||||
|
|
||||||
const std::shared_ptr<std::function<bool(int)>> iterate_over_serial = std::make_shared<std::function<bool(int)>>();
|
const std::shared_ptr<std::function<bool(int)>> iterate_over_serial = std::make_shared<std::function<bool(int)>>();
|
||||||
|
|
||||||
const std::shared_ptr<atomic_t<int>> index = std::make_shared<atomic_t<int>>(0);
|
const std::shared_ptr<atomic_t<int>> index = std::make_shared<atomic_t<int>>(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);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
else if (action(serial))
|
|
||||||
|
if (action(serial))
|
||||||
{
|
{
|
||||||
const int done = index_ptr->load();
|
const int done = index_ptr->load();
|
||||||
pdlg->setLabelText(progressLabel.arg(done + 1).arg(serials_size));
|
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))
|
if ((*iterate_over_serial)(*index))
|
||||||
{
|
{
|
||||||
QTimer::singleShot(1, this, *periodic_func);
|
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));
|
Refresh(true);
|
||||||
pdlg->setCancelButtonText(tr("OK"));
|
|
||||||
QApplication::beep();
|
|
||||||
|
|
||||||
if (refresh_on_finish && index)
|
|
||||||
{
|
|
||||||
Refresh(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
pdlg->deleteLater();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2414,6 +2418,14 @@ void game_list_frame::BatchCreateCPUCaches(const std::vector<game_info>& game_da
|
||||||
pdlg->setAutoReset(false);
|
pdlg->setAutoReset(false);
|
||||||
pdlg->open();
|
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),
|
BatchActionBySerials(pdlg, serials, tr("%0\nProgress: %1/%2 caches compiled").arg(main_label),
|
||||||
[&, game_data](const std::string& serial)
|
[&, game_data](const std::string& serial)
|
||||||
{
|
{
|
||||||
|
|
|
@ -394,7 +394,7 @@ void main_window::OnMissingFw()
|
||||||
{
|
{
|
||||||
const QString title = tr("Missing Firmware Detected!");
|
const QString title = tr("Missing Firmware Detected!");
|
||||||
const QString message = tr("Commercial games require the firmware (PS3UPDAT.PUP file) to be installed."
|
const QString message = tr("Commercial games require the firmware (PS3UPDAT.PUP file) to be installed."
|
||||||
"\n<br>For information about how to obtain the required firmware read the <a %0 href=\"https://rpcs3.net/quickstart\">quickstart guide</a>.").arg(gui::utils::get_link_style());
|
"\n<br>For information about how to obtain the required firmware read the <a %0 href=\"https://rpcs3.net/quickstart\">quickstart guide</a>.").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);
|
QMessageBox* mb = new QMessageBox(QMessageBox::Question, title, message, QMessageBox::Ok | QMessageBox::Cancel, this, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowStaysOnTopHint);
|
||||||
mb->setTextFormat(Qt::RichText);
|
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::NotifyEmuSettingsChange);
|
||||||
connect(dlg, &settings_dialog::EmuSettingsApplied, this, &main_window::update_gui_pad_thread);
|
connect(dlg, &settings_dialog::EmuSettingsApplied, this, &main_window::update_gui_pad_thread);
|
||||||
connect(dlg, &settings_dialog::EmuSettingsApplied, m_log_frame, &log_frame::LoadSettings);
|
connect(dlg, &settings_dialog::EmuSettingsApplied, m_log_frame, &log_frame::LoadSettings);
|
||||||
|
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
dlg->open();
|
dlg->open();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1247,7 +1247,16 @@ bool patch_manager_dialog::handle_json(const QByteArray& data)
|
||||||
if (patch_engine::load(patches, "From Download", content, true, &log_message))
|
if (patch_engine::load(patches, "From Download", content, true, &log_message))
|
||||||
{
|
{
|
||||||
patch_log.notice("Successfully validated downloaded patch file");
|
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
|
// Back up current patch file if possible
|
||||||
if (fs::is_file(path))
|
if (fs::is_file(path))
|
||||||
|
|
|
@ -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
|
// Destroy objects in reverse order
|
||||||
for (; _max; _max--)
|
for (; _max; _max--)
|
||||||
{
|
{
|
||||||
|
|
|
@ -361,13 +361,8 @@ namespace stx
|
||||||
[[deprecated("Use null_ptr")]] shared_ptr(std::nullptr_t) = delete;
|
[[deprecated("Use null_ptr")]] shared_ptr(std::nullptr_t) = delete;
|
||||||
|
|
||||||
// Not-so-aliasing constructor: emulates std::enable_shared_from_this without its overhead
|
// Not-so-aliasing constructor: emulates std::enable_shared_from_this without its overhead
|
||||||
explicit shared_ptr(T* _this) noexcept
|
template <typename Type>
|
||||||
: m_ptr(_this)
|
friend shared_ptr<Type> make_shared_from_this(const Type* _this) noexcept;
|
||||||
{
|
|
||||||
// Random checks which may fail on invalid pointer
|
|
||||||
ensure((reinterpret_cast<u64>(d()->destroy) - 0x10000) >> 47 == 0);
|
|
||||||
ensure((d()->refs++ - 1) >> 58 == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U> requires same_ptr_implicit_v<T, U>
|
template <typename U> requires same_ptr_implicit_v<T, U>
|
||||||
shared_ptr(const shared_ptr<U>& r) noexcept
|
shared_ptr(const shared_ptr<U>& r) noexcept
|
||||||
|
@ -562,11 +557,29 @@ namespace stx
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires (std::is_constructible_v<std::remove_reference_t<T>, T&&>)
|
requires (std::is_constructible_v<std::remove_reference_t<T>, T&&>)
|
||||||
static shared_ptr<std::remove_reference_t<T>> make_shared_value(T&& value)
|
static shared_ptr<std::remove_reference_t<T>> make_shared_value(T&& value) noexcept
|
||||||
{
|
{
|
||||||
return make_single_value(std::forward<T>(value));
|
return make_single_value(std::forward<T>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Not-so-aliasing constructor: emulates std::enable_shared_from_this without its overhead
|
||||||
|
template <typename T>
|
||||||
|
static shared_ptr<T> make_shared_from_this(const T* _this) noexcept
|
||||||
|
{
|
||||||
|
shared_ptr<T> r;
|
||||||
|
r.m_ptr = const_cast<T*>(_this);
|
||||||
|
|
||||||
|
if (!_this) [[unlikely]]
|
||||||
|
{
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Random checks which may fail on invalid pointer
|
||||||
|
ensure((reinterpret_cast<u64>(r.d()->destroy.load()) - 0x10000) >> 47 == 0);
|
||||||
|
ensure((r.d()->refs++ - 1) >> 58 == 0);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
// Atomic simplified shared pointer
|
// Atomic simplified shared pointer
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class atomic_ptr
|
class atomic_ptr
|
||||||
|
@ -1059,9 +1072,9 @@ namespace stx
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Update old head with current value
|
// Update old head with current value
|
||||||
next.m_ptr = reinterpret_cast<T*>(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<uptr>(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)
|
// This argument is consumed (moved from)
|
||||||
exch.m_ptr = nullptr;
|
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
|
// Simple atomic load is much more effective than load(), but it's a non-owning reference
|
||||||
T* observe() const noexcept
|
T* observe() const noexcept
|
||||||
{
|
{
|
||||||
return reinterpret_cast<T*>(m_val >> c_ref_size);
|
return std::launder(ptr_to(m_val));
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit constexpr operator bool() const noexcept
|
explicit constexpr operator bool() const noexcept
|
||||||
|
@ -1138,11 +1151,6 @@ namespace stx
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr std::nullptr_t get() const noexcept
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
} null_ptr;
|
} null_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue