ScummVM API documentation
saveload.h
1/* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#ifndef TSAGE_SAVELOAD_H
23#define TSAGE_SAVELOAD_H
24
25#include "common/scummsys.h"
26#include "common/list.h"
27#include "common/memstream.h"
28#include "common/savefile.h"
29#include "common/serializer.h"
30
31namespace TsAGE {
32
33typedef void (*SaveNotifierFn)(bool postFlag);
34
35#define TSAGE_SAVEGAME_VERSION 15
36
37class SavedObject;
38
40 uint8 _version;
41 Common::String _saveName;
42 Graphics::Surface *_thumbnail;
43 int _saveYear, _saveMonth, _saveDay;
44 int _saveHour, _saveMinutes;
45 int _totalFrames;
46};
47
48/*--------------------------------------------------------------------------*/
49
50// FIXME: workaround to suppress spurious strict-alias warnings on older GCC
51// versions. this should be resolved with the savegame rewrite
52#define SYNC_POINTER(x) do { \
53 SavedObject **y = (SavedObject **)((void *)&x); \
54 s.syncPointer(y); \
55} while (false)
56
57#define SYNC_ENUM(FIELD, TYPE) int v_##FIELD = (int)FIELD; s.syncAsUint16LE(v_##FIELD); \
58 if (s.isLoading()) FIELD = (TYPE)v_##FIELD;
59
64public:
66
67 // HACK: TSAGE saved games contain a single byte for the savegame version,
68 // thus the normal syncVersion() Serializer member won't work here. In order
69 // to maintain compatibility with older game saves, this method is provided
70 // in order to set the savegame version from a byte
71 void setSaveVersion(byte version) { _version = version; }
72
73 void syncPointer(SavedObject **ptr, Common::Serializer::Version minVersion = 0,
74 Common::Serializer::Version maxVersion = kLastVersion);
75 void validate(const Common::String &s, Common::Serializer::Version minVersion = 0,
76 Common::Serializer::Version maxVersion = kLastVersion);
77 void validate(int v, Common::Serializer::Version minVersion = 0,
78 Common::Serializer::Version maxVersion = kLastVersion);
79 void syncAsDouble(double &v);
80};
81
82/*--------------------------------------------------------------------------*/
83
85public:
86 virtual ~Serialisable() {}
87 virtual void synchronize(Serializer &s) = 0;
88};
89
91public:
92 virtual ~SaveListener() {}
93 virtual void listenerSynchronize(Serializer &s) = 0;
94};
95
96/*--------------------------------------------------------------------------*/
97
98class SavedObject : public Serialisable {
99public:
100 SavedObject();
101 ~SavedObject() override;
102
103 virtual Common::String getClassName() { return "SavedObject"; }
104 void synchronize(Serializer &s) override {}
105
106 static SavedObject *createInstance(const Common::String &className);
107};
108
109/*--------------------------------------------------------------------------*/
110
114template<typename T>
116public:
117 void synchronize(Serializer &s) {
118 int entryCount = 0;
119
120 if (s.isLoading()) {
121 this->clear();
122 s.syncAsUint32LE(entryCount);
123
124 for (int idx = 0; idx < entryCount; ++idx) {
125 this->push_back(static_cast<T>((T)NULL));
126 T &obj = Common::List<T>::back();
127 s.syncPointer((SavedObject **)&obj);
128 }
129 } else {
130 // Get the list size
131 entryCount = this->size();
132
133 // Write out list
134 s.syncAsUint32LE(entryCount);
135 for (typename Common::List<T>::iterator i = this->begin(); i != this->end(); ++i) {
136 s.syncPointer((SavedObject **)&*i);
137 }
138 }
139 }
140
141 void addBefore(T existingItem, T newItem) {
142 typename SynchronizedList<T>::iterator i = this->begin();
143 while ((i != this->end()) && (*i != existingItem)) ++i;
144 this->insert(i, newItem);
145 }
146 void addAfter(T existingItem, T newItem) {
147 typename SynchronizedList<T>::iterator i = this->begin();
148 while ((i != this->end()) && (*i != existingItem)) ++i;
149 if (i != this->end()) ++i;
150 this->insert(i, newItem);
151 }
152
153 bool contains(T item) {
154 typename SynchronizedList<T>::iterator i = this->begin();
155 for (; i != this->end(); ++i) {
156 if (*i == item)
157 return true;
158 }
159
160 return false;
161 }
162};
163
171template<typename T>
172inline bool contains(const Common::List<T> &l, const T &v) {
173 return (Common::find(l.begin(), l.end(), v) != l.end());
174}
175
179template<typename T>
180class FunctionList : public Common::List<void (*)(T)> {
181public:
182 void notify(T v) {
183 for (typename Common::List<void (*)(T)>::iterator i = this->begin(); i != this->end(); ++i) {
184 (*i)(v);
185 }
186 }
187};
188
189/*--------------------------------------------------------------------------*/
190
192public:
193 SavedObject **_savedObject;
194 int _objIndex;
195
196 SavedObjectRef() : _savedObject(NULL), _objIndex(-1) {}
197 SavedObjectRef(SavedObject **so, int objIndex) : _savedObject(so), _objIndex(objIndex) {}
198};
199
200typedef SavedObject *(*SavedObjectFactory)(const Common::String &className);
201
202class Saver {
204private:
206 FunctionList<bool> _saveNotifiers;
207 FunctionList<bool> _loadNotifiers;
209
210 Common::List<SavedObjectRef> _unresolvedPtrs;
211 SavedObjectFactory _factoryPtr;
212
213 bool _macroSaveFlag;
214 bool _macroRestoreFlag;
215
216 void resolveLoadPointers(DynObjects &dynObjects);
217public:
218 Saver();
219 ~Saver();
220
221 Common::Error save(int slot, const Common::String &saveName);
222 Common::Error restore(int slot);
223 WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, tSageSavegameHeader &header, bool skipThumbnail = true);
224 static void writeSavegameHeader(Common::OutSaveFile *out, tSageSavegameHeader &header);
225
226 void addListener(SaveListener *obj);
227 void addSaveNotifier(SaveNotifierFn fn);
228 void addLoadNotifier(SaveNotifierFn fn);
229 void addObject(SavedObject *obj);
230 void removeObject(SavedObject *obj);
231 void addFactory(SavedObjectFactory fn) { _factoryPtr = fn; }
232 void addSavedObjectPtr(SavedObject **ptr, int objIndex) {
233 _unresolvedPtrs.push_back(SavedObjectRef(ptr, objIndex));
234 }
235
236 bool savegamesExist() const;
237 bool getMacroSaveFlag() const { return _macroSaveFlag; }
238 bool getMacroRestoreFlag() const { return _macroRestoreFlag; }
239 int blockIndexOf(SavedObject *p);
240 int getObjectCount() const;
241 void listObjects();
242};
243
244extern Saver *g_saver;
245
246} // End of namespace TsAGE
247
248#endif
Definition: error.h:81
Definition: list.h:44
iterator begin()
Definition: list.h:266
size_type size() const
Definition: list.h:237
ListInternal::Iterator< void(*)(T) > iterator
Definition: list.h:52
void clear()
Definition: list.h:245
iterator insert(iterator pos, const T &element)
Definition: list.h:86
t_T & back()
Definition: list.h:206
void push_back(const T &element)
Definition: list.h:174
iterator end()
Definition: list.h:279
Definition: savefile.h:54
Definition: stream.h:745
Definition: serializer.h:80
Definition: str.h:59
Definition: stream.h:77
Definition: saveload.h:180
Definition: saveload.h:90
Definition: saveload.h:98
Definition: saveload.h:191
Definition: saveload.h:202
Definition: saveload.h:84
Definition: saveload.h:63
Definition: saveload.h:115
In find(In first, In last, const T &v)
Definition: algorithm.h:225
bool skipThumbnail(Common::SeekableReadStream &in)
Definition: list_intern.h:54
Definition: surface.h:67
Definition: saveload.h:39