diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index f1ec2251bfa9..b16a41597d5d 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2861,7 +2861,7 @@ namespace rsx const std::string file_path = fs::get_config_dir() + "captures/" + Emu.GetTitleID() + "_" + date_time::current_time_narrow() + "_capture.rrc"; // todo: may want to compress this data? - serial_save save_manager; + utils::serial_save save_manager; save_manager.reserve(0x800'0000); // 128MB save_manager(frame_capture); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index bbecdce06f27..445bf29983b7 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "stdafx.h" #include "VFS.h" #include "Utilities/bin_patch.h" #include "Emu/Memory/vm.h" @@ -380,7 +380,7 @@ bool Emulator::BootRsxCapture(const std::string& path) } std::unique_ptr frame = std::make_unique(); - serial_load load_manager{ in_file.to_vector() }; + utils::serial_load load_manager{ in_file.to_vector() }; load_manager(*frame); in_file.close(); diff --git a/rpcs3/util/serialization.hpp b/rpcs3/util/serialization.hpp index ef15e702f4b0..8b750ae6a150 100644 --- a/rpcs3/util/serialization.hpp +++ b/rpcs3/util/serialization.hpp @@ -3,250 +3,266 @@ #include "util/types.hpp" #include -struct serial_load +namespace utils { - const std::vector data; - usz pos = 0; - - bool read(void* ptr, usz size) - { - if (pos == umax || data.size() - pos < size) - { - ensure(false); - //std::memset(ptr, 0, size); - //pos = -1; - //return false; - } - - std::memcpy(ptr, &data[pos], size); - pos += size; - return true; - } + template + concept serializable = requires (Archive& ar, T& obj) { obj.serialize(ar); }; template - bool read(T& obj) - { - return read(std::addressof(obj), sizeof(obj)); - } + concept vector_alike = requires (T& obj) { obj.data()[0]; obj.reserve(0); }; template - bool read(T& obj) requires requires (T& obj) { obj.serialize(std::declval()); } - { - obj.serialize(*this); - return operator bool(); - } + concept array_alike = (!(requires (T& obj) { obj.clear(); })) && requires (T& obj) { std::data(obj)[0]; }; - // std::vector, std::basic_string template - bool read(T& obj) requires (std::is_constructible_v) && requires (T& obj) { obj.data()[0]; obj.reserve(0); std::declval().read(obj[0]); } + concept iterators_valid_most = (!(requires (T& obj) { obj.data()[0]; })) && requires (T& obj) { obj.insert(obj.end(), std::declval()); }; + + struct serial_load { - usz size = 0; + const std::vector data; + usz pos = 0; - if (!read(size)) + bool read(void* ptr, usz size) { - obj.clear(); - return false; + if (pos == umax || data.size() - pos < size) + { + ensure(false); + //std::memset(ptr, 0, size); + //pos = -1; + //return false; + } + + std::memcpy(ptr, &data[pos], size); + pos += size; + return true; } - obj.resize(size); + template + bool read(T& obj) + { + return read(std::addressof(obj), sizeof(obj)); + } - if constexpr (std::is_trivially_copyable_v) + template + bool read(T& obj) requires serializable { - if (!read(obj.data(), sizeof(obj[0]) * size)) + obj.serialize(*this); + return operator bool(); + } + + // std::vector, std::basic_string + template + bool read(T& obj) requires vector_alike + { + obj.clear(); + + usz size = 0; + + if (!read(size)) { - obj.clear(); return false; } - } - else - { - for (auto&& value : obj) + + obj.resize(size); + + if constexpr (std::is_trivially_copyable_v) { - if (!read(value)) + if (!read(obj.data(), sizeof(obj[0]) * size)) { obj.clear(); return false; } } - } - - return true; - } - - // std::array, C-array - template - bool read(T& obj) requires (!requires (T& obj) { obj.clear(); }) && requires (T& obj) { std::size(obj); std::declval().read(obj[0]); } - { - if constexpr (std::is_trivially_copyable_v()[0])>>) - { - return read(std::data(obj), sizeof(obj[0]) * std::size(obj)); - } - else - { - for (auto&& value : obj) + else { - if (!read(value)) + for (auto&& value : obj) { - return false; + if (!read(value)) + { + obj.clear(); + return false; + } } } return true; } - } - - // std::deque, std::set, std::map, std::multiset, std::multimap - template - bool read(T& obj) requires (!requires (T& obj) { obj.data()[0]; }) && requires (T& obj) { obj.insert(obj.end(), std::declval()); } - { - usz size = 0; - if (!read(size)) + // std::array, C-array + template + bool read(T& obj) requires array_alike { - obj.clear(); - return false; + if constexpr (std::is_trivially_copyable_v()[0])>>) + { + return read(std::data(obj), sizeof(obj[0]) * std::size(obj)); + } + else + { + for (auto&& value : obj) + { + if (!read(value)) + { + return false; + } + } + + return true; + } } - for (usz i = 0; i < size; i++) + // std::deque, std::set, std::map, std::multiset, std::multimap + template + bool read(T& obj) requires iterators_valid_most { - if constexpr (std::is_trivially_copyable_v) - { - char buf[sizeof(typename T::value_type)]{}; + obj.clear(); - if (!read(buf)) - { - obj.clear(); - return false; - } + usz size = 0; - obj.insert(obj.end(), std::bit_cast(buf)); + if (!read(size)) + { + return false; } - else + + for (usz i = 0; i < size; i++) { - typename T::value_type value{}; + using type = typename T::value_type; - if (!read(value)) + if constexpr (std::is_trivially_copyable_v) { - obj.clear(); - return false; + char buf[sizeof(type)]{}; + + if (!read(buf)) + { + obj.clear(); + return false; + } + + obj.insert(obj.end(), std::bit_cast(buf)); } + else + { + type value{}; + + if (!read(value)) + { + obj.clear(); + return false; + } - obj.insert(obj.end(), std::move(value)); + obj.insert(obj.end(), std::move(value)); + } } - } - return true; - } + return true; + } - template requires (std::is_copy_constructible_v && (std::is_constructible_v || std::is_trivially_copyable_v)) - operator T() - { - if constexpr (std::is_constructible_v) + template requires (std::is_copy_constructible_v && (std::is_constructible_v || std::is_trivially_copyable_v)) + operator T() { - T value{}; - read(value); - return value; + if constexpr (std::is_constructible_v) + { + T value{}; + read(value); + return value; + } + else + { + char buf[sizeof(T)]{}; + read(buf); + return std::bit_cast(buf); + } } - else + + explicit operator bool() const { - char buf[sizeof(T)]{}; - read(buf); - return std::bit_cast(buf); + return pos <= data.size(); } - } - explicit operator bool() const - { - return pos <= data.size(); - } - - template - bool operator()(T&... args) - { - return (read(args), ...); - } -}; - -struct serial_save -{ - std::vector data; + template + bool operator()(T&... args) + { + return (read(args), ...); + } + }; - void reserve(usz size) - { - data.reserve(data.size() + size); - } + struct serial_save + { + std::vector data; - void write(const void* ptr, usz size) - { - data.insert(data.end(), static_cast(ptr), static_cast(ptr) + size); - } - - template - void write(T&& obj) - { - write(std::addressof(obj), sizeof(obj)); - } + void reserve(usz size) + { + data.reserve(data.size() + size); + } - template - void write(T&& obj) requires requires (T&& obj) { obj.serialize(std::declval()); } - { - obj.serialize(*this); - } + void write(const void* ptr, usz size) + { + data.insert(data.end(), static_cast(ptr), static_cast(ptr) + size); + } - // std::vector, std::basic_string - template - void write(T&& obj) requires (std::is_constructible_v::value_type>) && - requires (std::remove_cvref_t& obj) { obj.data()[0]; obj.reserve(0); std::declval().write(obj[0]); } - { - write(obj.size()); + template + void write(T&& obj) + { + write(std::addressof(obj), sizeof(obj)); + } - if constexpr (std::is_trivially_copyable_v::value_type>) + template + void write(T&& obj) requires serializable> { - write(obj.data(), sizeof(obj[0]) * obj.size()); + obj.serialize(*this); } - else + + // std::vector, std::basic_string + template + void write(T&& obj) requires vector_alike> { - for (auto&& value : obj) + write(obj.size()); + + if constexpr (std::is_trivially_copyable_v::value_type>) { - write(value); + write(obj.data(), sizeof(obj[0]) * obj.size()); + } + else + { + for (auto&& value : obj) + { + write(value); + } } } - } - // std::array, C-array - template - void write(T&& obj) requires (!requires (std::remove_cvref_t& obj) { obj.clear(); }) && - requires (T&& obj) { std::size(obj); std::declval().read(obj[0]); } - { - if constexpr (std::is_trivially_copyable_v()[0])>>) + // std::array, C-array + template + void write(T&& obj) requires array_alike> { - write(obj.data(), sizeof(obj[0]) * std::size(obj)); + if constexpr (std::is_trivially_copyable_v()[0])>>) + { + write(obj.data(), sizeof(obj[0]) * std::size(obj)); + } + else + { + for (auto&& value : obj) + { + write(value); + } + } } - else + + // std::deque, std::set, std::map, std::multiset, std::multimap + template + void write(T&& obj) requires iterators_valid_most> { + write(obj.size()); + for (auto&& value : obj) { write(value); } } - } - // std::deque, std::set, std::map, std::multiset, std::multimap - template - void write(T&& obj) requires (!requires (std::remove_cvref_t& obj) { obj.data()[0]; }) && - requires (std::remove_cvref_t& obj) { obj.insert(obj.end(), std::declval()); } - { - write(obj.size()); - - for (auto&& value : obj) + template + void operator()(T&&... args) { - write(value); + (write(std::forward(args)), ...); } - } - - template - void operator()(T&&... args) - { - (write(std::forward(args)), ...); - } -}; + }; +}