1 #include "stdafx.h"
2 #include <algorithm>
3 #include "Snapshotable.h"
4 #include "SaveStateManager.h"
5
StreamStartBlock()6 void Snapshotable::StreamStartBlock()
7 {
8 if(_inBlock) {
9 throw new std::runtime_error("Cannot start a new block before ending the last block");
10 }
11
12 if(!_saving) {
13 InternalStream(_blockSize);
14 _blockSize = std::min(_blockSize, (uint32_t)0xFFFFF);
15 _blockBuffer = new uint8_t[_blockSize];
16 ArrayInfo<uint8_t> arrayInfo = { _blockBuffer, _blockSize };
17 InternalStream(arrayInfo);
18 } else {
19 _blockSize = 0x100;
20 _blockBuffer = new uint8_t[_blockSize];
21 }
22 _blockPosition = 0;
23 _inBlock = true;
24 }
25
StreamEndBlock()26 void Snapshotable::StreamEndBlock()
27 {
28 _inBlock = false;
29 if(_saving) {
30 InternalStream(_blockPosition);
31 ArrayInfo<uint8_t> arrayInfo = { _blockBuffer, _blockPosition };
32 InternalStream(arrayInfo);
33 }
34
35 delete[] _blockBuffer;
36 _blockBuffer = nullptr;
37 }
38
Stream(Snapshotable * snapshotable)39 void Snapshotable::Stream(Snapshotable* snapshotable)
40 {
41 stringstream stream;
42 if(_saving) {
43 snapshotable->SaveSnapshot(&stream);
44 uint32_t size = (uint32_t)stream.tellp();
45 stream.seekg(0, ios::beg);
46 stream.seekp(0, ios::beg);
47
48 uint8_t *buffer = new uint8_t[size];
49 stream.read((char*)buffer, size);
50 InternalStream(size);
51 ArrayInfo<uint8_t> arrayInfo = { buffer, size };
52 InternalStream(arrayInfo);
53 delete[] buffer;
54 } else {
55 uint32_t size = 0;
56 InternalStream(size);
57
58 uint8_t *buffer = new uint8_t[size];
59 ArrayInfo<uint8_t> arrayInfo = { buffer, size };
60 InternalStream(arrayInfo);
61
62 stream.write((char*)buffer, size);
63 stream.seekg(0, ios::beg);
64 stream.seekp(0, ios::beg);
65 snapshotable->LoadSnapshot(&stream, _stateVersion);
66 delete[] buffer;
67 }
68 }
69
SaveSnapshot(ostream * file)70 void Snapshotable::SaveSnapshot(ostream* file)
71 {
72 _stateVersion = SaveStateManager::FileFormatVersion;
73
74 _streamSize = 0x1000;
75 _stream = new uint8_t[_streamSize];
76 _position = 0;
77 _saving = true;
78
79 StreamState(_saving);
80 file->write((char*)&_position, sizeof(_position));
81 file->write((char*)_stream, _position);
82
83 delete[] _stream;
84
85 if(_blockBuffer) {
86 throw new std::runtime_error("A call to StreamEndBlock is missing.");
87 }
88 }
89
LoadSnapshot(istream * file,uint32_t stateVersion)90 void Snapshotable::LoadSnapshot(istream* file, uint32_t stateVersion)
91 {
92 _stateVersion = stateVersion;
93
94 _position = 0;
95 _saving = false;
96
97 file->read((char*)&_streamSize, sizeof(_streamSize));
98 _stream = new uint8_t[_streamSize];
99 file->read((char*)_stream, _streamSize);
100 StreamState(_saving);
101
102 delete[] _stream;
103
104 if(_blockBuffer) {
105 throw new std::runtime_error("A call to StreamEndBlock is missing.");
106 }
107 }
108
WriteEmptyBlock(ostream * file)109 void Snapshotable::WriteEmptyBlock(ostream* file)
110 {
111 int blockSize = 0;
112 file->write((char*)&blockSize, sizeof(blockSize));
113 }
114
SkipBlock(istream * file)115 void Snapshotable::SkipBlock(istream* file)
116 {
117 int blockSize = 0;
118 file->read((char*)&blockSize, sizeof(blockSize));
119 file->seekg(blockSize, ios::cur);
120 }