aboutsummaryrefslogtreecommitdiff
path: root/scumm/saveload.h
blob: 914d6b93463497f1607f6eff9e7e5518c12b4f71 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2002 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header$
 *
 */

#ifndef SAVELOAD_H
#define SAVELOAD_H

// To work around a warning in GCC 3.2 (and 3.1 ?) regarding non-POD types,
// we use a small trick: instead of 0 we use 42. Why? Well, it seems newer GCC
// versions hae a heuristic built in to detect "offset-of" patterns - which is exactly
// what our OFFS macro does. Now, for non-POD types this is not really legal, because
// member need not be at a fixed offset relative to the variable, even if they are in
// current reality (many of our complex structs are non-POD; for an explanation of 
// what POD means refer to http://www-cpd.fnal.gov/personal/wb/boost/ISOcxx/doc/POD.html)

#define OFFS(type,item) (((int)(&((type*)42)->type::item))-42)
#define SIZE(type,item) sizeof(((type*)42)->type::item)
#define MKLINE(type,item,saveas) {OFFS(type,item),saveas,SIZE(type,item)}
#define MKARRAY(type,item,saveas,num) {OFFS(type,item),128|saveas,SIZE(type,item)}, {num,0,0}
#define MKEND() {0xFFFF,0xFF,0xFF}

#define MKREF(type,item,refid) {OFFS(type,item),refid,0xFF}

enum {
	sleByte = 1,
	sleUint8 = 1,
	sleInt8 = 1,
	sleInt16 = 2,
	sleUint16 = 3,
	sleInt32 = 4,
	sleUint32 = 5
};

struct SaveLoadEntry {
	uint32 offs;
	uint8 type;
	uint8 size;
};

struct SerializerStream {
#ifdef NONSTANDARD_SAVE
	void *context;

	bool fopen(const char *filename, const char *mode);
	void fclose();
	int fread(void *buf, int size, int cnt);
	int fwrite(void *buf, int size, int cnt);
#else
	FILE *out;

	FILE *fopen(const char *filename, const char *mode) {
		return out = ::fopen(filename, mode);
	}
	void fclose() {
		::fclose(out);
	}
	int fread(void *buf, int size, int cnt) {
		return ::fread(buf, size, cnt, out);
	}
	int fwrite(void *buf, int size, int cnt) {
		return ::fwrite(buf, size, cnt, out);
	}
#endif
};

typedef int SerializerSaveReference(void *me, byte type, void *ref);
typedef void *SerializerLoadReference(void *me, byte type, int ref);

struct Serializer {
	SerializerStream _saveLoadStream;

	union {
		SerializerSaveReference *_save_ref;
		SerializerLoadReference *_load_ref;
		void *_saveload_ref;
	};
	void *_ref_me;

	bool _saveOrLoad;

	void saveBytes(void *b, int len);
	void loadBytes(void *b, int len);
	
	void saveLoadArrayOf(void *b, int len, int datasize, byte filetype);
	void saveLoadEntries(void *d, const SaveLoadEntry *sle);
	void saveLoadArrayOf(void *b, int num, int datasize, const SaveLoadEntry *sle);

	void saveUint32(uint32 d);
	void saveWord(uint16 d);
	void saveByte(byte b);

	byte loadByte();
	uint16 loadWord();
	uint32 loadUint32();

	bool isSaving() { return _saveOrLoad; }

	bool checkEOFLoadStream();

};

#endif