main serialize.c
  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
 12void 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
 20static 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
 28void 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
 37void 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
 44void save_int8(serialize_buffer *buf, uint8_t val)
 45{
 46	reserve(buf, sizeof(val));
 47	buf->data[buf->size++] = val;
 48}
 49
 50void save_string(serialize_buffer *buf, char *val)
 51{
 52	size_t len = strlen(val);
 53	save_buffer8(buf, val, len);
 54}
 55
 56void 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
 63void 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
 72void 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
 83void 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
 93void 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
108void 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
126void 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
135uint32_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
148uint16_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
159uint8_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
169void 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
178void 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}
189void 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
203void 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
224static const char sz_ident[] = "BLSTSZ\x01\x07";
225
226uint8_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
244uint8_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	if (memcmp(ident, sz_ident, sizeof(ident))) {
261		return 0;
262	}
263	buf->size = size - sizeof(ident);
264	buf->cur_pos = 0;
265	buf->data = malloc(buf->size);
266	buf->handlers = NULL;
267	buf->max_handler = 8;
268	if (fread(buf->data, 1, buf->size, f) != buf->size) {
269		fclose(f);
270		free(buf->data);
271		buf->data = NULL;
272		buf->size = 0;
273		return 0;
274	}
275	fclose(f);
276	return 1;
277}