#pragma once #include "util/serialization.hpp" #include namespace fs { class file; } struct version_entry { u16 type; u16 version; ENABLE_BITWISE_SERIALIZATION; }; // Uncompressed file serialization handler struct uncompressed_serialization_file_handler : utils::serialization_file_handler { const std::unique_ptr m_file_storage; const std::add_pointer_t m_file; explicit uncompressed_serialization_file_handler(fs::file&& file) noexcept : utils::serialization_file_handler() , m_file_storage(std::make_unique(std::move(file))) , m_file(m_file_storage.get()) { } explicit uncompressed_serialization_file_handler(const fs::file& file) noexcept : utils::serialization_file_handler() , m_file_storage(nullptr) , m_file(std::addressof(file)) { } uncompressed_serialization_file_handler(const uncompressed_serialization_file_handler&) = delete; // Handle file read and write requests bool handle_file_op(utils::serial& ar, usz pos, usz size, const void* data) override; // Get available memory or file size // Preferably memory size if is already greater/equal to recommended to avoid additional file ops usz get_size(const utils::serial& ar, usz recommended) const override; void finalize(utils::serial& ar) override; }; template requires (std::is_same_v, fs::file>) inline std::unique_ptr make_uncompressed_serialization_file_handler(File&& file) { ensure(file); return std::make_unique(std::forward(file)); } // Compressed file serialization handler struct compressed_serialization_file_handler : utils::serialization_file_handler { const std::unique_ptr m_file_storage; const std::add_pointer_t m_file; std::vector m_stream_data; usz m_stream_data_index = 0; usz m_file_read_index = 0; bool m_write_inited = false; bool m_read_inited = false; std::any m_stream; explicit compressed_serialization_file_handler(fs::file&& file) noexcept : utils::serialization_file_handler() , m_file_storage(std::make_unique(std::move(file))) , m_file(m_file_storage.get()) { } explicit compressed_serialization_file_handler(const fs::file& file) noexcept : utils::serialization_file_handler() , m_file_storage(nullptr) , m_file(std::addressof(file)) { } compressed_serialization_file_handler(const compressed_serialization_file_handler&) = delete; // Handle file read and write requests bool handle_file_op(utils::serial& ar, usz pos, usz size, const void* data) override; // Get available memory or file size // Preferably memory size if is already greater/equal to recommended to avoid additional file ops usz get_size(const utils::serial& ar, usz recommended) const override; void skip_until(utils::serial& ar) override; void finalize(utils::serial& ar) override; private: usz read_at(utils::serial& ar, usz read_pos, void* data, usz size); void initialize(utils::serial& ar); }; template requires (std::is_same_v, fs::file>) inline std::unique_ptr make_compressed_serialization_file_handler(File&& file) { ensure(file); return std::make_unique(std::forward(file)); } // Null file serialization handler struct null_serialization_file_handler : utils::serialization_file_handler { explicit null_serialization_file_handler() noexcept { } // Handle file read and write requests bool handle_file_op(utils::serial& ar, usz pos, usz size, const void* data) override; void finalize(utils::serial& ar) override; bool is_null() const override { return true; } }; inline std::unique_ptr make_null_serialization_file_handler() { return std::make_unique(); } bool load_and_check_reserved(utils::serial& ar, usz size); bool is_savestate_version_compatible(const std::vector& data, bool is_boot_check); std::vector get_savestate_versioning_data(fs::file&& file, std::string_view filepath); bool is_savestate_compatible(fs::file&& file, std::string_view filepath); std::vector read_used_savestate_versions(); std::string get_savestate_file(std::string_view title_id, std::string_view boot_path, s64 abs_id, s64 rel_id);