Merge pull request #4908 from hamish-milne/feature/savestates-2
Save states
This commit is contained in:
commit
c605bb42db
354 changed files with 6100 additions and 604 deletions
|
@ -54,6 +54,7 @@ add_custom_command(OUTPUT scm_rev.cpp
|
|||
add_library(common STATIC
|
||||
alignment.h
|
||||
announce_multiplayer_room.h
|
||||
archives.h
|
||||
assert.h
|
||||
detached_tasks.cpp
|
||||
detached_tasks.h
|
||||
|
@ -66,6 +67,7 @@ add_library(common STATIC
|
|||
common_funcs.h
|
||||
common_paths.h
|
||||
common_types.h
|
||||
construct.h
|
||||
file_util.cpp
|
||||
file_util.h
|
||||
hash.h
|
||||
|
@ -78,6 +80,8 @@ add_library(common STATIC
|
|||
logging/text_formatter.cpp
|
||||
logging/text_formatter.h
|
||||
math_util.h
|
||||
memory_ref.h
|
||||
memory_ref.cpp
|
||||
microprofile.cpp
|
||||
microprofile.h
|
||||
microprofileui.h
|
||||
|
@ -89,6 +93,11 @@ add_library(common STATIC
|
|||
scm_rev.cpp
|
||||
scm_rev.h
|
||||
scope_exit.h
|
||||
serialization/atomic.h
|
||||
serialization/boost_discrete_interval.hpp
|
||||
serialization/boost_flat_set.h
|
||||
serialization/boost_small_vector.hpp
|
||||
serialization/boost_vector.hpp
|
||||
string_util.cpp
|
||||
string_util.h
|
||||
swap.h
|
||||
|
@ -121,7 +130,7 @@ endif()
|
|||
|
||||
create_target_directory_groups(common)
|
||||
|
||||
target_link_libraries(common PUBLIC fmt microprofile)
|
||||
target_link_libraries(common PUBLIC fmt microprofile Boost::boost Boost::serialization)
|
||||
target_link_libraries(common PRIVATE libzstd_static)
|
||||
if (ARCHITECTURE_x86_64)
|
||||
target_link_libraries(common PRIVATE xbyak)
|
||||
|
|
21
src/common/archives.h
Normal file
21
src/common/archives.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2020 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/archive/binary_iarchive.hpp>
|
||||
#include <boost/archive/binary_oarchive.hpp>
|
||||
#include <boost/serialization/export.hpp>
|
||||
|
||||
using iarchive = boost::archive::binary_iarchive;
|
||||
using oarchive = boost::archive::binary_oarchive;
|
||||
|
||||
#define SERIALIZE_IMPL(A) \
|
||||
template void A::serialize<iarchive>(iarchive & ar, const unsigned int file_version); \
|
||||
template void A::serialize<oarchive>(oarchive & ar, const unsigned int file_version);
|
||||
|
||||
#define SERIALIZE_EXPORT_IMPL(A) \
|
||||
BOOST_CLASS_EXPORT_IMPLEMENT(A) \
|
||||
BOOST_SERIALIZATION_REGISTER_ARCHIVE(iarchive) \
|
||||
BOOST_SERIALIZATION_REGISTER_ARCHIVE(oarchive)
|
|
@ -47,6 +47,7 @@
|
|||
#define DUMP_DIR "dump"
|
||||
#define LOAD_DIR "load"
|
||||
#define SHADER_DIR "shaders"
|
||||
#define STATES_DIR "states"
|
||||
|
||||
// Filenames
|
||||
// Files in the directory returned by GetUserPath(UserPath::LogDir)
|
||||
|
|
34
src/common/construct.h
Normal file
34
src/common/construct.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2020 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/serialization/serialization.hpp>
|
||||
|
||||
/// Allows classes to define `save_construct` and `load_construct` methods for serialization
|
||||
/// This is used where we don't call the default constructor during deserialization, as a shortcut
|
||||
/// instead of using load_construct_data directly
|
||||
class construct_access {
|
||||
public:
|
||||
template <class Archive, class T>
|
||||
static void save_construct(Archive& ar, const T* t, const unsigned int file_version) {
|
||||
t->save_construct(ar, file_version);
|
||||
}
|
||||
template <class Archive, class T>
|
||||
static void load_construct(Archive& ar, T* t, const unsigned int file_version) {
|
||||
T::load_construct(ar, t, file_version);
|
||||
}
|
||||
};
|
||||
|
||||
#define BOOST_SERIALIZATION_CONSTRUCT(T) \
|
||||
namespace boost::serialization { \
|
||||
template <class Archive> \
|
||||
void save_construct_data(Archive& ar, const T* t, const unsigned int file_version) { \
|
||||
construct_access::save_construct(ar, t, file_version); \
|
||||
} \
|
||||
template <class Archive> \
|
||||
void load_construct_data(Archive& ar, T* t, const unsigned int file_version) { \
|
||||
construct_access::load_construct(ar, t, file_version); \
|
||||
} \
|
||||
}
|
|
@ -726,6 +726,34 @@ void SetUserPath(const std::string& path) {
|
|||
g_paths.emplace(UserPath::ShaderDir, user_path + SHADER_DIR DIR_SEP);
|
||||
g_paths.emplace(UserPath::DumpDir, user_path + DUMP_DIR DIR_SEP);
|
||||
g_paths.emplace(UserPath::LoadDir, user_path + LOAD_DIR DIR_SEP);
|
||||
g_paths.emplace(UserPath::StatesDir, user_path + STATES_DIR DIR_SEP);
|
||||
}
|
||||
|
||||
std::string g_currentRomPath{};
|
||||
|
||||
void SetCurrentRomPath(const std::string& path) {
|
||||
g_currentRomPath = path;
|
||||
}
|
||||
|
||||
bool StringReplace(std::string& haystack, const std::string& a, const std::string& b, bool swap) {
|
||||
const auto& needle = swap ? b : a;
|
||||
const auto& replacement = swap ? a : b;
|
||||
if (needle.empty()) {
|
||||
return false;
|
||||
}
|
||||
auto index = haystack.find(needle, 0);
|
||||
if (index == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
haystack.replace(index, needle.size(), replacement);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string SerializePath(const std::string& input, bool is_saving) {
|
||||
auto result = input;
|
||||
StringReplace(result, "%CITRA_ROM_FILE%", g_currentRomPath, is_saving);
|
||||
StringReplace(result, "%CITRA_USER_DIR%", GetUserPath(UserPath::UserDir), is_saving);
|
||||
return result;
|
||||
}
|
||||
|
||||
const std::string& GetUserPath(UserPath path) {
|
||||
|
@ -882,8 +910,9 @@ std::string SanitizePath(std::string_view path_, DirectorySeparator directory_se
|
|||
|
||||
IOFile::IOFile() {}
|
||||
|
||||
IOFile::IOFile(const std::string& filename, const char openmode[], int flags) {
|
||||
Open(filename, openmode, flags);
|
||||
IOFile::IOFile(const std::string& filename, const char openmode[], int flags)
|
||||
: filename(filename), openmode(openmode), flags(flags) {
|
||||
Open();
|
||||
}
|
||||
|
||||
IOFile::~IOFile() {
|
||||
|
@ -902,10 +931,14 @@ IOFile& IOFile::operator=(IOFile&& other) noexcept {
|
|||
void IOFile::Swap(IOFile& other) noexcept {
|
||||
std::swap(m_file, other.m_file);
|
||||
std::swap(m_good, other.m_good);
|
||||
std::swap(filename, other.filename);
|
||||
std::swap(openmode, other.openmode);
|
||||
std::swap(flags, other.flags);
|
||||
}
|
||||
|
||||
bool IOFile::Open(const std::string& filename, const char openmode[], int flags) {
|
||||
bool IOFile::Open() {
|
||||
Close();
|
||||
|
||||
#ifdef _WIN32
|
||||
if (flags != 0) {
|
||||
m_file = _wfsopen(Common::UTF8ToUTF16W(filename).c_str(),
|
||||
|
@ -916,7 +949,7 @@ bool IOFile::Open(const std::string& filename, const char openmode[], int flags)
|
|||
Common::UTF8ToUTF16W(openmode).c_str()) == 0;
|
||||
}
|
||||
#else
|
||||
m_file = std::fopen(filename.c_str(), openmode);
|
||||
m_file = std::fopen(filename.c_str(), openmode.c_str());
|
||||
m_good = m_file != nullptr;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include <boost/serialization/wrapper.hpp>
|
||||
#include "common/common_types.h"
|
||||
#ifdef _MSC_VER
|
||||
#include "common/string_util.h"
|
||||
|
@ -34,10 +37,39 @@ enum class UserPath {
|
|||
RootDir,
|
||||
SDMCDir,
|
||||
ShaderDir,
|
||||
StatesDir,
|
||||
SysDataDir,
|
||||
UserDir,
|
||||
};
|
||||
|
||||
// Replaces install-specific paths with standard placeholders, and back again
|
||||
std::string SerializePath(const std::string& input, bool is_saving);
|
||||
|
||||
// A serializable path string
|
||||
struct Path : public boost::serialization::wrapper_traits<const Path> {
|
||||
std::string& str;
|
||||
|
||||
explicit Path(std::string& _str) : str(_str) {}
|
||||
|
||||
static const Path make(std::string& str) {
|
||||
return Path(str);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void save(Archive& ar, const unsigned int) const {
|
||||
auto s_path = SerializePath(str, true);
|
||||
ar << s_path;
|
||||
}
|
||||
template <class Archive>
|
||||
void load(Archive& ar, const unsigned int) const {
|
||||
ar >> str;
|
||||
str = SerializePath(str, false);
|
||||
}
|
||||
|
||||
BOOST_SERIALIZATION_SPLIT_MEMBER();
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
// FileSystem tree node/
|
||||
struct FSTEntry {
|
||||
bool isDirectory;
|
||||
|
@ -45,6 +77,17 @@ struct FSTEntry {
|
|||
std::string physicalName; // name on disk
|
||||
std::string virtualName; // name in FST names table
|
||||
std::vector<FSTEntry> children;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& isDirectory;
|
||||
ar& size;
|
||||
ar& Path::make(physicalName);
|
||||
ar& Path::make(virtualName);
|
||||
ar& children;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
// Returns true if file filename exists
|
||||
|
@ -137,6 +180,8 @@ bool SetCurrentDir(const std::string& directory);
|
|||
|
||||
void SetUserPath(const std::string& path = "");
|
||||
|
||||
void SetCurrentRomPath(const std::string& path);
|
||||
|
||||
// Returns a pointer to a string with a Citra data dir in the user's home
|
||||
// directory. To be used in "multi-user" mode (that is, installed).
|
||||
const std::string& GetUserPath(UserPath path);
|
||||
|
@ -221,7 +266,6 @@ public:
|
|||
|
||||
void Swap(IOFile& other) noexcept;
|
||||
|
||||
bool Open(const std::string& filename, const char openmode[], int flags = 0);
|
||||
bool Close();
|
||||
|
||||
template <typename T>
|
||||
|
@ -305,8 +349,31 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
bool Open();
|
||||
|
||||
std::FILE* m_file = nullptr;
|
||||
bool m_good = true;
|
||||
|
||||
std::string filename;
|
||||
std::string openmode;
|
||||
u32 flags;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& Path::make(filename);
|
||||
ar& openmode;
|
||||
ar& flags;
|
||||
u64 pos;
|
||||
if (Archive::is_saving::value) {
|
||||
pos = Tell();
|
||||
}
|
||||
ar& pos;
|
||||
if (Archive::is_loading::value) {
|
||||
Open();
|
||||
Seek(pos, SEEK_SET);
|
||||
}
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
} // namespace FileUtil
|
||||
|
|
8
src/common/memory_ref.cpp
Normal file
8
src/common/memory_ref.cpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
// Copyright 2020 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/archives.h"
|
||||
#include "common/memory_ref.h"
|
||||
|
||||
SERIALIZE_EXPORT_IMPL(BufferMem)
|
136
src/common/memory_ref.h
Normal file
136
src/common/memory_ref.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
// Copyright 2020 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <boost/serialization/export.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
/// Abstract host-side memory - for example a static buffer, or local vector
|
||||
class BackingMem {
|
||||
public:
|
||||
virtual ~BackingMem() = default;
|
||||
virtual u8* GetPtr() = 0;
|
||||
virtual const u8* GetPtr() const = 0;
|
||||
virtual std::size_t GetSize() const = 0;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
/// Backing memory implemented by a local buffer
|
||||
class BufferMem : public BackingMem {
|
||||
public:
|
||||
BufferMem() = default;
|
||||
explicit BufferMem(std::size_t size) : data(size) {}
|
||||
|
||||
u8* GetPtr() override {
|
||||
return data.data();
|
||||
}
|
||||
|
||||
const u8* GetPtr() const override {
|
||||
return data.data();
|
||||
}
|
||||
|
||||
std::size_t GetSize() const override {
|
||||
return data.size();
|
||||
}
|
||||
|
||||
std::vector<u8>& Vector() {
|
||||
return data;
|
||||
}
|
||||
|
||||
const std::vector<u8>& Vector() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<u8> data;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& boost::serialization::base_object<BackingMem>(*this);
|
||||
ar& data;
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(BufferMem);
|
||||
|
||||
/// A managed reference to host-side memory. Fast enough to be used everywhere instead of u8*
|
||||
/// Supports serialization.
|
||||
class MemoryRef {
|
||||
public:
|
||||
MemoryRef() = default;
|
||||
MemoryRef(std::nullptr_t) {}
|
||||
MemoryRef(std::shared_ptr<BackingMem> backing_mem_)
|
||||
: backing_mem(std::move(backing_mem_)), offset(0) {
|
||||
Init();
|
||||
}
|
||||
MemoryRef(std::shared_ptr<BackingMem> backing_mem_, u64 offset_)
|
||||
: backing_mem(std::move(backing_mem_)), offset(offset_) {
|
||||
ASSERT(offset < backing_mem->GetSize());
|
||||
Init();
|
||||
}
|
||||
explicit operator bool() const {
|
||||
return cptr != nullptr;
|
||||
}
|
||||
operator u8*() {
|
||||
return cptr;
|
||||
}
|
||||
u8* GetPtr() {
|
||||
return cptr;
|
||||
}
|
||||
operator const u8*() const {
|
||||
return cptr;
|
||||
}
|
||||
const u8* GetPtr() const {
|
||||
return cptr;
|
||||
}
|
||||
std::size_t GetSize() const {
|
||||
return csize;
|
||||
}
|
||||
MemoryRef& operator+=(u32 offset_by) {
|
||||
ASSERT(offset_by < csize);
|
||||
offset += offset_by;
|
||||
Init();
|
||||
return *this;
|
||||
}
|
||||
MemoryRef operator+(u32 offset_by) const {
|
||||
ASSERT(offset_by < csize);
|
||||
return MemoryRef(backing_mem, offset + offset_by);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<BackingMem> backing_mem{};
|
||||
u64 offset{};
|
||||
// Cached values for speed
|
||||
u8* cptr{};
|
||||
std::size_t csize{};
|
||||
|
||||
void Init() {
|
||||
if (backing_mem) {
|
||||
cptr = backing_mem->GetPtr() + offset;
|
||||
csize = static_cast<std::size_t>(backing_mem->GetSize() - offset);
|
||||
} else {
|
||||
cptr = nullptr;
|
||||
csize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& backing_mem;
|
||||
ar& offset;
|
||||
Init();
|
||||
}
|
||||
friend class boost::serialization::access;
|
||||
};
|
29
src/common/serialization/atomic.h
Normal file
29
src/common/serialization/atomic.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2020 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <boost/serialization/split_free.hpp>
|
||||
|
||||
namespace boost::serialization {
|
||||
|
||||
template <class Archive, class T>
|
||||
void serialize(Archive& ar, std::atomic<T>& value, const unsigned int file_version) {
|
||||
boost::serialization::split_free(ar, value, file_version);
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
void save(Archive& ar, const std::atomic<T>& value, const unsigned int file_version) {
|
||||
ar << value.load();
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
void load(Archive& ar, std::atomic<T>& value, const unsigned int file_version) {
|
||||
T tmp;
|
||||
ar >> tmp;
|
||||
value.store(tmp);
|
||||
}
|
||||
|
||||
} // namespace boost::serialization
|
38
src/common/serialization/boost_discrete_interval.hpp
Normal file
38
src/common/serialization/boost_discrete_interval.hpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2020 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/icl/discrete_interval.hpp>
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
|
||||
namespace boost::serialization {
|
||||
|
||||
template <class Archive, class DomainT, ICL_COMPARE Compare>
|
||||
void save(Archive& ar, const boost::icl::discrete_interval<DomainT, Compare>& obj,
|
||||
const unsigned int file_version) {
|
||||
ar << obj.lower();
|
||||
ar << obj.upper();
|
||||
ar << obj.bounds()._bits;
|
||||
}
|
||||
|
||||
template <class Archive, class DomainT, ICL_COMPARE Compare>
|
||||
void load(Archive& ar, boost::icl::discrete_interval<DomainT, Compare>& obj,
|
||||
const unsigned int file_version) {
|
||||
DomainT upper, lower;
|
||||
boost::icl::bound_type bounds;
|
||||
ar >> lower;
|
||||
ar >> upper;
|
||||
ar >> bounds;
|
||||
obj = boost::icl::discrete_interval(lower, upper, boost::icl::interval_bounds(bounds));
|
||||
}
|
||||
|
||||
template <class Archive, class DomainT, ICL_COMPARE Compare>
|
||||
void serialize(Archive& ar, boost::icl::discrete_interval<DomainT, Compare>& obj,
|
||||
const unsigned int file_version) {
|
||||
boost::serialization::split_free(ar, obj, file_version);
|
||||
}
|
||||
|
||||
} // namespace boost::serialization
|
38
src/common/serialization/boost_flat_set.h
Normal file
38
src/common/serialization/boost_flat_set.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2020 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/container/flat_set.hpp>
|
||||
#include <boost/serialization/split_free.hpp>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace boost::serialization {
|
||||
|
||||
template <class Archive, class T>
|
||||
void save(Archive& ar, const boost::container::flat_set<T>& set, const unsigned int file_version) {
|
||||
ar << static_cast<u64>(set.size());
|
||||
for (auto& v : set) {
|
||||
ar << v;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
void load(Archive& ar, boost::container::flat_set<T>& set, const unsigned int file_version) {
|
||||
u64 count{};
|
||||
ar >> count;
|
||||
set.clear();
|
||||
for (u64 i = 0; i < count; i++) {
|
||||
T value{};
|
||||
ar >> value;
|
||||
set.insert(value);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
void serialize(Archive& ar, boost::container::flat_set<T>& set, const unsigned int file_version) {
|
||||
boost::serialization::split_free(ar, set, file_version);
|
||||
}
|
||||
|
||||
} // namespace boost::serialization
|
38
src/common/serialization/boost_interval_set.hpp
Normal file
38
src/common/serialization/boost_interval_set.hpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2020 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/icl/interval_set.hpp>
|
||||
#include <boost/serialization/split_free.hpp>
|
||||
#include "common/serialization/boost_discrete_interval.hpp"
|
||||
|
||||
namespace boost::serialization {
|
||||
|
||||
template <class Archive, class T>
|
||||
void save(Archive& ar, const boost::icl::interval_set<T>& set, const unsigned int file_version) {
|
||||
ar << static_cast<u64>(set.iterative_size());
|
||||
for (auto& v : set) {
|
||||
ar << v;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
void load(Archive& ar, boost::icl::interval_set<T>& set, const unsigned int file_version) {
|
||||
u64 count{};
|
||||
ar >> count;
|
||||
set.clear();
|
||||
for (u64 i = 0; i < count; i++) {
|
||||
typename boost::icl::interval_set<T>::interval_type value{};
|
||||
ar >> value;
|
||||
set += value;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
void serialize(Archive& ar, boost::icl::interval_set<T>& set, const unsigned int file_version) {
|
||||
boost::serialization::split_free(ar, set, file_version);
|
||||
}
|
||||
|
||||
} // namespace boost::serialization
|
144
src/common/serialization/boost_small_vector.hpp
Normal file
144
src/common/serialization/boost_small_vector.hpp
Normal file
|
@ -0,0 +1,144 @@
|
|||
#ifndef BOOST_SERIALIZATION_BOOST_SMALL_VECTOR_HPP
|
||||
#define BOOST_SERIALIZATION_BOOST_SMALL_VECTOR_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// boost_vector.hpp: serialization for boost vector templates
|
||||
|
||||
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
// fast array serialization (C) Copyright 2005 Matthias Troyer
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#include <boost/container/small_vector.hpp>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#include <boost/archive/detail/basic_iarchive.hpp>
|
||||
#include <boost/serialization/access.hpp>
|
||||
#include <boost/serialization/collection_size_type.hpp>
|
||||
#include <boost/serialization/item_version_type.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
|
||||
#include <boost/mpl/bool_fwd.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/serialization/array_wrapper.hpp>
|
||||
#include <boost/serialization/collections_load_imp.hpp>
|
||||
#include <boost/serialization/collections_save_imp.hpp>
|
||||
#include <boost/serialization/split_free.hpp>
|
||||
|
||||
// default is being compatible with version 1.34.1 files, not 1.35 files
|
||||
#ifndef BOOST_SERIALIZATION_VECTOR_VERSIONED
|
||||
#define BOOST_SERIALIZATION_VECTOR_VERSIONED(V) (V == 4 || V == 5)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// vector< T >
|
||||
|
||||
// the default versions
|
||||
|
||||
template <class Archive, class U, std::size_t N>
|
||||
inline void save(Archive& ar, const boost::container::small_vector<U, N>& t,
|
||||
const unsigned int /* file_version */, mpl::false_) {
|
||||
boost::serialization::stl::save_collection<Archive, boost::container::small_vector<U, N>>(ar,
|
||||
t);
|
||||
}
|
||||
|
||||
template <class Archive, class U, std::size_t N>
|
||||
inline void load(Archive& ar, boost::container::small_vector<U, N>& t,
|
||||
const unsigned int /* file_version */, mpl::false_) {
|
||||
const boost::archive::library_version_type library_version(ar.get_library_version());
|
||||
// retrieve number of elements
|
||||
item_version_type item_version(0);
|
||||
collection_size_type count;
|
||||
ar >> BOOST_SERIALIZATION_NVP(count);
|
||||
if (boost::archive::library_version_type(3) < library_version) {
|
||||
ar >> BOOST_SERIALIZATION_NVP(item_version);
|
||||
}
|
||||
t.reserve(count);
|
||||
stl::collection_load_impl(ar, t, count, item_version);
|
||||
}
|
||||
|
||||
// the optimized versions
|
||||
|
||||
template <class Archive, class U, std::size_t N>
|
||||
inline void save(Archive& ar, const boost::container::small_vector<U, N>& t,
|
||||
const unsigned int /* file_version */, mpl::true_) {
|
||||
const collection_size_type count(t.size());
|
||||
ar << BOOST_SERIALIZATION_NVP(count);
|
||||
if (!t.empty())
|
||||
// explict template arguments to pass intel C++ compiler
|
||||
ar << serialization::make_array<const U, collection_size_type>(static_cast<const U*>(&t[0]),
|
||||
count);
|
||||
}
|
||||
|
||||
template <class Archive, class U, std::size_t N>
|
||||
inline void load(Archive& ar, boost::container::small_vector<U, N>& t,
|
||||
const unsigned int /* file_version */, mpl::true_) {
|
||||
collection_size_type count(t.size());
|
||||
ar >> BOOST_SERIALIZATION_NVP(count);
|
||||
t.resize(count);
|
||||
unsigned int item_version = 0;
|
||||
if (BOOST_SERIALIZATION_VECTOR_VERSIONED(ar.get_library_version())) {
|
||||
ar >> BOOST_SERIALIZATION_NVP(item_version);
|
||||
}
|
||||
if (!t.empty())
|
||||
// explict template arguments to pass intel C++ compiler
|
||||
ar >> serialization::make_array<U, collection_size_type>(static_cast<U*>(&t[0]), count);
|
||||
}
|
||||
|
||||
// dispatch to either default or optimized versions
|
||||
|
||||
template <class Archive, class U, std::size_t N>
|
||||
inline void save(Archive& ar, const boost::container::small_vector<U, N>& t,
|
||||
const unsigned int file_version) {
|
||||
typedef typename boost::serialization::use_array_optimization<Archive>::template apply<
|
||||
typename remove_const<U>::type>::type use_optimized;
|
||||
save(ar, t, file_version, use_optimized());
|
||||
}
|
||||
|
||||
template <class Archive, class U, std::size_t N>
|
||||
inline void load(Archive& ar, boost::container::small_vector<U, N>& t,
|
||||
const unsigned int file_version) {
|
||||
#ifdef BOOST_SERIALIZATION_VECTOR_135_HPP
|
||||
if (ar.get_library_version() == boost::archive::library_version_type(5)) {
|
||||
load(ar, t, file_version, boost::is_arithmetic<U>());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
typedef typename boost::serialization::use_array_optimization<Archive>::template apply<
|
||||
typename remove_const<U>::type>::type use_optimized;
|
||||
load(ar, t, file_version, use_optimized());
|
||||
}
|
||||
|
||||
// split non-intrusive serialization function member into separate
|
||||
// non intrusive save/load member functions
|
||||
template <class Archive, class U, std::size_t N>
|
||||
inline void serialize(Archive& ar, boost::container::small_vector<U, N>& t,
|
||||
const unsigned int file_version) {
|
||||
boost::serialization::split_free(ar, t, file_version);
|
||||
}
|
||||
|
||||
// split non-intrusive serialization function member into separate
|
||||
// non intrusive save/load member functions
|
||||
template <class Archive, std::size_t N>
|
||||
inline void serialize(Archive& ar, boost::container::small_vector<bool, N>& t,
|
||||
const unsigned int file_version) {
|
||||
boost::serialization::split_free(ar, t, file_version);
|
||||
}
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_SERIALIZATION_BOOST_SMALL_VECTOR_HPP
|
149
src/common/serialization/boost_vector.hpp
Normal file
149
src/common/serialization/boost_vector.hpp
Normal file
|
@ -0,0 +1,149 @@
|
|||
#ifndef BOOST_SERIALIZATION_BOOST_VECTOR_HPP
|
||||
#define BOOST_SERIALIZATION_BOOST_VECTOR_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// boost_vector.hpp: serialization for boost vector templates
|
||||
|
||||
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
// fast array serialization (C) Copyright 2005 Matthias Troyer
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#include <boost/container/vector.hpp>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#include <boost/archive/detail/basic_iarchive.hpp>
|
||||
#include <boost/serialization/access.hpp>
|
||||
#include <boost/serialization/collection_size_type.hpp>
|
||||
#include <boost/serialization/item_version_type.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
|
||||
#include <boost/mpl/bool_fwd.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/serialization/array_wrapper.hpp>
|
||||
#include <boost/serialization/collections_load_imp.hpp>
|
||||
#include <boost/serialization/collections_save_imp.hpp>
|
||||
#include <boost/serialization/split_free.hpp>
|
||||
|
||||
// default is being compatible with version 1.34.1 files, not 1.35 files
|
||||
#ifndef BOOST_SERIALIZATION_VECTOR_VERSIONED
|
||||
#define BOOST_SERIALIZATION_VECTOR_VERSIONED(V) (V == 4 || V == 5)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// vector< T >
|
||||
|
||||
// the default versions
|
||||
|
||||
template <class Archive, class U, class Allocator, class Options>
|
||||
inline void save(Archive& ar, const boost::container::vector<U, Allocator, Options>& t,
|
||||
const unsigned int /* file_version */, mpl::false_) {
|
||||
boost::serialization::stl::save_collection<Archive,
|
||||
boost::container::vector<U, Allocator, Options>>(ar,
|
||||
t);
|
||||
}
|
||||
|
||||
template <class Archive, class U, class Allocator, class Options>
|
||||
inline void load(Archive& ar, boost::container::vector<U, Allocator, Options>& t,
|
||||
const unsigned int /* file_version */, mpl::false_) {
|
||||
const boost::archive::library_version_type library_version(ar.get_library_version());
|
||||
// retrieve number of elements
|
||||
item_version_type item_version(0);
|
||||
collection_size_type count;
|
||||
ar >> BOOST_SERIALIZATION_NVP(count);
|
||||
if (boost::archive::library_version_type(3) < library_version) {
|
||||
ar >> BOOST_SERIALIZATION_NVP(item_version);
|
||||
}
|
||||
t.reserve(count);
|
||||
stl::collection_load_impl(ar, t, count, item_version);
|
||||
}
|
||||
|
||||
// the optimized versions
|
||||
|
||||
template <class Archive, class U, class Allocator, class Options>
|
||||
inline void save(Archive& ar, const boost::container::vector<U, Allocator, Options>& t,
|
||||
const unsigned int /* file_version */, mpl::true_) {
|
||||
const collection_size_type count(t.size());
|
||||
ar << BOOST_SERIALIZATION_NVP(count);
|
||||
if (!t.empty())
|
||||
// explict template arguments to pass intel C++ compiler
|
||||
ar << serialization::make_array<const U, collection_size_type>(static_cast<const U*>(&t[0]),
|
||||
count);
|
||||
}
|
||||
|
||||
template <class Archive, class U, class Allocator, class Options>
|
||||
inline void load(Archive& ar, boost::container::vector<U, Allocator, Options>& t,
|
||||
const unsigned int /* file_version */, mpl::true_) {
|
||||
collection_size_type count(t.size());
|
||||
ar >> BOOST_SERIALIZATION_NVP(count);
|
||||
t.resize(count);
|
||||
unsigned int item_version = 0;
|
||||
if (BOOST_SERIALIZATION_VECTOR_VERSIONED(ar.get_library_version())) {
|
||||
ar >> BOOST_SERIALIZATION_NVP(item_version);
|
||||
}
|
||||
if (!t.empty())
|
||||
// explict template arguments to pass intel C++ compiler
|
||||
ar >> serialization::make_array<U, collection_size_type>(static_cast<U*>(&t[0]), count);
|
||||
}
|
||||
|
||||
// dispatch to either default or optimized versions
|
||||
|
||||
template <class Archive, class U, class Allocator, class Options>
|
||||
inline void save(Archive& ar, const boost::container::vector<U, Allocator, Options>& t,
|
||||
const unsigned int file_version) {
|
||||
typedef typename boost::serialization::use_array_optimization<Archive>::template apply<
|
||||
typename remove_const<U>::type>::type use_optimized;
|
||||
save(ar, t, file_version, use_optimized());
|
||||
}
|
||||
|
||||
template <class Archive, class U, class Allocator, class Options>
|
||||
inline void load(Archive& ar, boost::container::vector<U, Allocator, Options>& t,
|
||||
const unsigned int file_version) {
|
||||
#ifdef BOOST_SERIALIZATION_VECTOR_135_HPP
|
||||
if (ar.get_library_version() == boost::archive::library_version_type(5)) {
|
||||
load(ar, t, file_version, boost::is_arithmetic<U>());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
typedef typename boost::serialization::use_array_optimization<Archive>::template apply<
|
||||
typename remove_const<U>::type>::type use_optimized;
|
||||
load(ar, t, file_version, use_optimized());
|
||||
}
|
||||
|
||||
// split non-intrusive serialization function member into separate
|
||||
// non intrusive save/load member functions
|
||||
template <class Archive, class U, class Allocator, class Options>
|
||||
inline void serialize(Archive& ar, boost::container::vector<U, Allocator, Options>& t,
|
||||
const unsigned int file_version) {
|
||||
boost::serialization::split_free(ar, t, file_version);
|
||||
}
|
||||
|
||||
// split non-intrusive serialization function member into separate
|
||||
// non intrusive save/load member functions
|
||||
template <class Archive, class Allocator, class Options>
|
||||
inline void serialize(Archive& ar, boost::container::vector<bool, Allocator, Options>& t,
|
||||
const unsigned int file_version) {
|
||||
boost::serialization::split_free(ar, t, file_version);
|
||||
}
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/serialization/collection_traits.hpp>
|
||||
|
||||
BOOST_SERIALIZATION_COLLECTION_TRAITS(boost::container::vector)
|
||||
|
||||
#endif // BOOST_SERIALIZATION_BOOST_VECTOR_HPP
|
|
@ -7,6 +7,9 @@
|
|||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <deque>
|
||||
#include <boost/serialization/deque.hpp>
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
|
@ -157,6 +160,52 @@ private:
|
|||
Queue* first;
|
||||
// The priority level queues of thread ids.
|
||||
std::array<Queue, NUM_QUEUES> queues;
|
||||
|
||||
s64 ToIndex(const Queue* q) const {
|
||||
if (q == nullptr) {
|
||||
return -2;
|
||||
} else if (q == UnlinkedTag()) {
|
||||
return -1;
|
||||
} else {
|
||||
return q - queues.data();
|
||||
}
|
||||
}
|
||||
|
||||
Queue* ToPointer(s64 idx) {
|
||||
if (idx == -1) {
|
||||
return UnlinkedTag();
|
||||
} else if (idx < 0) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return &queues[idx];
|
||||
}
|
||||
}
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void save(Archive& ar, const unsigned int file_version) const {
|
||||
const s64 idx = ToIndex(first);
|
||||
ar << idx;
|
||||
for (std::size_t i = 0; i < NUM_QUEUES; i++) {
|
||||
const s64 idx1 = ToIndex(queues[i].next_nonempty);
|
||||
ar << idx1;
|
||||
ar << queues[i].data;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void load(Archive& ar, const unsigned int file_version) {
|
||||
s64 idx;
|
||||
ar >> idx;
|
||||
first = ToPointer(idx);
|
||||
for (std::size_t i = 0; i < NUM_QUEUES; i++) {
|
||||
ar >> idx;
|
||||
queues[i].next_nonempty = ToPointer(idx);
|
||||
ar >> queues[i].data;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_SERIALIZATION_SPLIT_MEMBER()
|
||||
};
|
||||
|
||||
} // namespace Common
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
#include <boost/serialization/access.hpp>
|
||||
|
||||
namespace Common {
|
||||
|
||||
|
@ -44,6 +45,13 @@ class Vec4;
|
|||
|
||||
template <typename T>
|
||||
class Vec2 {
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& x;
|
||||
ar& y;
|
||||
}
|
||||
|
||||
public:
|
||||
T x;
|
||||
T y;
|
||||
|
@ -191,6 +199,14 @@ inline float Vec2<float>::Normalize() {
|
|||
|
||||
template <typename T>
|
||||
class Vec3 {
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& x;
|
||||
ar& y;
|
||||
ar& z;
|
||||
}
|
||||
|
||||
public:
|
||||
T x;
|
||||
T y;
|
||||
|
@ -399,6 +415,15 @@ using Vec3f = Vec3<float>;
|
|||
|
||||
template <typename T>
|
||||
class Vec4 {
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int file_version) {
|
||||
ar& x;
|
||||
ar& y;
|
||||
ar& z;
|
||||
ar& w;
|
||||
}
|
||||
|
||||
public:
|
||||
T x;
|
||||
T y;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue