454 changes: 316 additions & 138 deletions Source/Core/Core/State.cpp

Large diffs are not rendered by default.

61 changes: 53 additions & 8 deletions Source/Core/Core/State.h
Expand Up @@ -8,6 +8,7 @@
#include <cstddef>
#include <functional>
#include <string>
#include <type_traits>
#include <vector>

#include "Common/CommonTypes.h"
Expand All @@ -17,18 +18,62 @@ namespace State
// number of states
static const u32 NUM_STATES = 10;

struct StateHeader
struct StateHeaderLegacy
{
char gameID[6];
u16 reserved1;
u32 size;
u32 reserved2;
char game_id[6];
char reserved1[2];
u32 lzo_size = 0; // Must be zero for new states. Used to support legacy decompression algorithm.
char reserved2[4];
double time;
};
constexpr size_t STATE_HEADER_SIZE = sizeof(StateHeader);
constexpr size_t STATE_HEADER_SIZE = sizeof(StateHeaderLegacy);
static_assert(STATE_HEADER_SIZE == 24);
static_assert(offsetof(StateHeader, size) == 8);
static_assert(offsetof(StateHeader, time) == 16);
static_assert(offsetof(StateHeaderLegacy, lzo_size) == 8);
static_assert(offsetof(StateHeaderLegacy, time) == 16);
static_assert(std::is_trivially_copyable_v<StateHeaderLegacy>);

struct StateHeaderVersion
{
u32 version_cookie;
u32 version_string_length;
};
static_assert(std::is_trivially_copyable_v<StateHeaderVersion>);

struct StateHeader
{
StateHeaderLegacy legacy_header;
StateHeaderVersion version_header;
std::string version_string;
};

enum CompressionType : u16
{
Uncompressed = 0,
LZ4 = 1,
// Add new compression types after this, as the compression type
// is numerically stored in the state file.
};

struct StateExtendedBaseHeader
{
u16 header_version;
u16 compression_type;
u32 payload_offset;
u64 uncompressed_size;
};
constexpr size_t EXTENDED_BASE_HEADER_SIZE = sizeof(StateExtendedBaseHeader);
static_assert(EXTENDED_BASE_HEADER_SIZE == 16);
static_assert(offsetof(StateExtendedBaseHeader, payload_offset) == 4);
static_assert(offsetof(StateExtendedBaseHeader, uncompressed_size) == 8);
static_assert(std::is_trivially_copyable_v<StateExtendedBaseHeader>);

struct StateExtendedHeader
{
StateExtendedBaseHeader base_header;
// Feel free to add new fields here, adjusting COMPRESSED_DATA_OFFSET accordingly, as well as
// CreateExtendedHeader(). Add the appropriate IOFile read/write calls within LoadFileStateData()
// and WriteHeadersToFile()
};

void Init();

Expand Down
1 change: 1 addition & 0 deletions Source/Core/DolphinLib.vcxproj
Expand Up @@ -46,6 +46,7 @@
<Import Project="$(ExternalsDir)libspng\exports.props" />
<Import Project="$(ExternalsDir)libusb\exports.props" />
<Import Project="$(ExternalsDir)LZO\exports.props" />
<Import Project="$(ExternalsDir)LZ4\exports.props" />
<Import Project="$(ExternalsDir)mbedtls\exports.props" />
<Import Project="$(ExternalsDir)mGBA\exports.props" />
<Import Project="$(ExternalsDir)miniupnpc\exports.props" />
Expand Down
11 changes: 11 additions & 0 deletions Source/dolphin-emu.sln
Expand Up @@ -25,6 +25,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Languages", "..\Languages\L
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LZO", "..\Externals\LZO\LZO.vcxproj", "{AB993F38-C31D-4897-B139-A620C42BC565}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lz4", "..\Externals\LZ4\LZ4.vcxproj", "{9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc", "..\Externals\miniupnpc\miniupnpc.vcxproj", "{31643FDB-1BB8-4965-9DE7-000FC88D35AE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xxhash", "..\Externals\xxhash\xxhash.vcxproj", "{677EA016-1182-440C-9345-DC88D1E98C0C}"
Expand Down Expand Up @@ -173,6 +175,14 @@ Global
{AB993F38-C31D-4897-B139-A620C42BC565}.Release|ARM64.Build.0 = Release|ARM64
{AB993F38-C31D-4897-B139-A620C42BC565}.Release|x64.ActiveCfg = Release|x64
{AB993F38-C31D-4897-B139-A620C42BC565}.Release|x64.Build.0 = Release|x64
{9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Debug|ARM64.ActiveCfg = Debug|x64
{9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Debug|ARM64.Build.0 = Debug|x64
{9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Debug|x64.ActiveCfg = Debug|x64
{9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Debug|x64.Build.0 = Debug|x64
{9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Release|ARM64.ActiveCfg = Release|ARM64
{9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Release|ARM64.Build.0 = Release|ARM64
{9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Release|x64.ActiveCfg = Release|x64
{9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Release|x64.Build.0 = Release|x64
{31643FDB-1BB8-4965-9DE7-000FC88D35AE}.Debug|ARM64.ActiveCfg = Debug|ARM64
{31643FDB-1BB8-4965-9DE7-000FC88D35AE}.Debug|ARM64.Build.0 = Debug|ARM64
{31643FDB-1BB8-4965-9DE7-000FC88D35AE}.Debug|x64.ActiveCfg = Debug|x64
Expand Down Expand Up @@ -436,6 +446,7 @@ Global
GlobalSection(NestedProjects) = preSolution
{8ADA04D7-6DB1-4DA4-AB55-64FB12A0997B} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
{AB993F38-C31D-4897-B139-A620C42BC565} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
{9092C5CC-3E71-41B3-BF68-4A7BDD8A5476} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
{31643FDB-1BB8-4965-9DE7-000FC88D35AE} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
{677EA016-1182-440C-9345-DC88D1E98C0C} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
{F6EA7144-8D64-4EBB-A13E-76DFBD911EAE} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
Expand Down