comparison serialize.c @ 1427:4e5797b3935a

WIP - New savestate format
author Michael Pavone <pavone@retrodev.com>
date Sun, 06 Aug 2017 00:06:36 -0700
parents
children 2540c05520f2
comparison
equal deleted inserted replaced
1426:957325c990d5 1427:4e5797b3935a
1 #include <string.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include "serialize.h"
5 #include "util.h"
6
7 #ifndef SERIALIZE_DEFAULT_SIZE
8 #define SERIALIZE_DEFAULT_SIZE (256*1024) //default to enough for a Genesis save state
9 #endif
10
11
12 void init_serialize(serialize_buffer *buf)
13 {
14 buf->storage = SERIALIZE_DEFAULT_SIZE;
15 buf->size = 0;
16 buf->current_section_start = 0;
17 buf->data = malloc(SERIALIZE_DEFAULT_SIZE);
18 }
19
20 static void reserve(serialize_buffer *buf, size_t amount)
21 {
22 if (amount > (buf->storage - buf->size)) {
23 buf->storage *= 2;
24 buf = realloc(buf, buf->storage + sizeof(*buf));
25 }
26 }
27
28 void save_int32(serialize_buffer *buf, uint32_t val)
29 {
30 reserve(buf, sizeof(val));
31 buf->data[buf->size++] = val >> 24;
32 buf->data[buf->size++] = val >> 16;
33 buf->data[buf->size++] = val >> 8;
34 buf->data[buf->size++] = val;
35 }
36
37 void save_int16(serialize_buffer *buf, uint16_t val)
38 {
39 reserve(buf, sizeof(val));
40 buf->data[buf->size++] = val >> 8;
41 buf->data[buf->size++] = val;
42 }
43
44 void save_int8(serialize_buffer *buf, uint8_t val)
45 {
46 reserve(buf, sizeof(val));
47 buf->data[buf->size++] = val;
48 }
49
50 void save_string(serialize_buffer *buf, char *val)
51 {
52 size_t len = strlen(val);
53 save_buffer8(buf, val, len);
54 }
55
56 void save_buffer8(serialize_buffer *buf, void *val, size_t len)
57 {
58 reserve(buf, len);
59 memcpy(&buf->data[buf->size], val, len);
60 buf->size += len;
61 }
62
63 void save_buffer16(serialize_buffer *buf, uint16_t *val, size_t len)
64 {
65 reserve(buf, len * sizeof(*val));
66 for(; len != 0; len--, val++) {
67 buf->data[buf->size++] = *val >> 8;
68 buf->data[buf->size++] = *val;
69 }
70 }
71
72 void save_buffer32(serialize_buffer *buf, uint32_t *val, size_t len)
73 {
74 reserve(buf, len * sizeof(*val));
75 for(; len != 0; len--, val++) {
76 buf->data[buf->size++] = *val >> 24;
77 buf->data[buf->size++] = *val >> 16;
78 buf->data[buf->size++] = *val >> 8;
79 buf->data[buf->size++] = *val;
80 }
81 }
82
83 void start_section(serialize_buffer *buf, uint16_t section_id)
84 {
85 save_int16(buf, section_id);
86 //reserve some space for size once we end this section
87 reserve(buf, sizeof(uint32_t));
88 buf->size += sizeof(uint32_t);
89 //save start point for use in end_device
90 buf->current_section_start = buf->size;
91 }
92
93 void end_section(serialize_buffer *buf)
94 {
95 size_t section_size = buf->size - buf->current_section_start;
96 if (section_size > 0xFFFFFFFFU) {
97 fatal_error("Sections larger than 4GB are not supported");
98 }
99 uint32_t size = section_size;
100 uint8_t *field = buf->data + buf->current_section_start - sizeof(uint32_t);
101 *(field++) = size >> 24;
102 *(field++) = size >> 16;
103 *(field++) = size >> 8;
104 *(field++) = size;
105 buf->current_section_start = 0;
106 }
107
108 void register_section_handler(deserialize_buffer *buf, section_handler handler, uint16_t section_id)
109 {
110 if (section_id > buf->max_handler) {
111 uint16_t old_max = buf->max_handler;
112 if (buf->max_handler < 0x8000) {
113 buf->max_handler *= 2;
114 } else {
115 buf->max_handler = 0xFFFF;
116 }
117 buf->handlers = realloc(buf->handlers, (buf->max_handler+1) * sizeof(handler));
118 memset(buf->handlers + old_max + 1, 0, (buf->max_handler - old_max) * sizeof(handler));
119 }
120 if (!buf->handlers) {
121 buf->handlers = calloc(buf->max_handler + 1, sizeof(handler));
122 }
123 buf->handlers[section_id] = handler;
124 }
125
126 void init_deserialize(deserialize_buffer *buf, uint8_t *data, size_t size)
127 {
128 buf->size = size;
129 buf->cur_pos = 0;
130 buf->data = data;
131 buf->handlers = NULL;
132 buf->max_handler = 8;
133 }
134
135 uint32_t load_int32(deserialize_buffer *buf)
136 {
137 uint32_t val;
138 if ((buf->size - buf->cur_pos) < sizeof(val)) {
139 fatal_error("Failed to load required int32 field");
140 }
141 val = buf->data[buf->cur_pos++] << 24;
142 val |= buf->data[buf->cur_pos++] << 16;
143 val |= buf->data[buf->cur_pos++] << 8;
144 val |= buf->data[buf->cur_pos++];
145 return val;
146 }
147
148 uint16_t load_int16(deserialize_buffer *buf)
149 {
150 uint16_t val;
151 if ((buf->size - buf->cur_pos) < sizeof(val)) {
152 fatal_error("Failed to load required int16 field");
153 }
154 val = buf->data[buf->cur_pos++] << 8;
155 val |= buf->data[buf->cur_pos++];
156 return val;
157 }
158
159 uint8_t load_int8(deserialize_buffer *buf)
160 {
161 uint8_t val;
162 if ((buf->size - buf->cur_pos) < sizeof(val)) {
163 fatal_error("Failed to load required int8 field");
164 }
165 val = buf->data[buf->cur_pos++];
166 return val;
167 }
168
169 void load_buffer8(deserialize_buffer *buf, void *dst, size_t len)
170 {
171 if ((buf->size - buf->cur_pos) < len) {
172 fatal_error("Failed to load required buffer of size %d", len);
173 }
174 memcpy(dst, buf->data + buf->cur_pos, len);
175 buf->cur_pos += len;
176 }
177
178 void load_buffer16(deserialize_buffer *buf, uint16_t *dst, size_t len)
179 {
180 if ((buf->size - buf->cur_pos) < len * sizeof(uint16_t)) {
181 fatal_error("Failed to load required buffer of size %d\n", len);
182 }
183 for(; len != 0; len--, dst++) {
184 uint16_t value = buf->data[buf->cur_pos++] << 8;
185 value |= buf->data[buf->cur_pos++];
186 *dst = value;
187 }
188 }
189 void load_buffer32(deserialize_buffer *buf, uint32_t *dst, size_t len)
190 {
191 if ((buf->size - buf->cur_pos) < len * sizeof(uint32_t)) {
192 fatal_error("Failed to load required buffer of size %d\n", len);
193 }
194 for(; len != 0; len--, dst++) {
195 uint32_t value = buf->data[buf->cur_pos++] << 24;
196 value |= buf->data[buf->cur_pos++] << 16;
197 value |= buf->data[buf->cur_pos++] << 8;
198 value |= buf->data[buf->cur_pos++];
199 *dst = value;
200 }
201 }
202
203 void load_section(deserialize_buffer *buf)
204 {
205 if (!buf->handlers) {
206 fatal_error("load_section called on a deserialize_buffer with no handlers registered\n");
207 }
208 uint16_t section_id = load_int16(buf);
209 uint32_t size = load_int32(buf);
210 if (size > (buf->size - buf->cur_pos)) {
211 fatal_error("Section is bigger than remaining space in file");
212 }
213 if (section_id > buf->max_handler || !buf->handlers[section_id].fun) {
214 warning("No handler for section ID %d, save state may be from a newer version\n", section_id);
215 buf->cur_pos += size;
216 return;
217 }
218 deserialize_buffer section;
219 init_deserialize(&section, buf->data + buf->cur_pos, size);
220 buf->handlers[section_id].fun(&section, buf->handlers[section_id].data);
221 buf->cur_pos += size;
222 }
223
224 static const char sz_ident[] = "BLSTSZ\x01\x07";
225
226 uint8_t save_to_file(serialize_buffer *buf, char *path)
227 {
228 FILE *f = fopen(path, "wb");
229 if (!f) {
230 return 0;
231 }
232 if (fwrite(sz_ident, 1, sizeof(sz_ident)-1, f) != sizeof(sz_ident)-1) {
233 fclose(f);
234 return 0;
235 }
236 if (fwrite(buf->data, 1, buf->size, f) != buf->size) {
237 fclose(f);
238 return 0;
239 }
240 fclose(f);
241 return 1;
242 }
243
244 uint8_t load_from_file(deserialize_buffer *buf, char *path)
245 {
246 FILE *f = fopen(path, "rb");
247 if (!f) {
248 return 0;
249 }
250 char ident[sizeof(sz_ident)-1];
251 long size = file_size(f);
252 if (size < sizeof(ident)) {
253 fclose(f);
254 return 0;
255 }
256 if (fread(ident, 1, sizeof(ident), f) != sizeof(ident)) {
257 fclose(f);
258 return 0;
259 }
260 fclose(f);
261 if (memcmp(ident, sz_ident, sizeof(ident))) {
262 return 0;
263 }
264 buf->size = size - sizeof(ident);
265 buf->cur_pos = 0;
266 buf->data = malloc(buf->size);
267 buf->handlers = NULL;
268 buf->max_handler = 8;
269 if (fread(buf->data, 1, buf->size, f) != buf->size) {
270 free(buf->data);
271 buf->data = NULL;
272 buf->size = 0;
273 return 0;
274 }
275 return 1;
276 }