loader: fix ub accessing data w/ pointer from before realloc
[rofl0r-gnuboy.git] / loader.c
blob319e0a16a2f2ef96034ba06b001671c936211d82
1 #undef _POSIX_C_SOURCE
2 #define _POSIX_C_SOURCE 200809L
3 #undef _GNU_SOURCE
4 #define _GNU_SOURCE
5 #include <string.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <ctype.h>
10 #include <time.h>
12 #include "defs.h"
13 #include "regs.h"
14 #include "mem.h"
15 #include "hw.h"
16 #include "rtc.h"
17 #include "rc.h"
18 #include "lcd.h"
19 #include "inflate.h"
20 #define XZ_USE_CRC64
21 #include "xz/xz.h"
22 #include "save.h"
23 #include "sound.h"
24 #include "sys.h"
26 static int mbc_table[256] =
28 0, 1, 1, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3,
29 3, 3, 3, 3, 0, 0, 0, 0, 0, 5, 5, 5, MBC_RUMBLE, MBC_RUMBLE, MBC_RUMBLE, 0,
30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
38 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
41 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
43 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
44 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
46 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MBC_HUC3, MBC_HUC1
49 static int rtc_table[256] =
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
52 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56 static int batt_table[256] =
58 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0,
59 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
63 static int romsize_table[256] =
65 2, 4, 8, 16, 32, 64, 128, 256, 512,
66 0, 0, 0, 0, 0, 0, 0, 0,
67 0, 0, 0, 0, 0, 0, 0, 0,
68 0, 0, 0, 0, 0, 0, 0, 0,
69 0, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0,
72 0, 0, 0, 0, 0, 0, 0, 0,
73 0, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 128, 128, 128
76 /* 0, 0, 72, 80, 96 -- actual values but bad to use these! */
79 static int ramsize_table[256] =
81 1, 1, 1, 4, 16,
82 4 /* FIXME - what value should this be?! */
86 static char *bootroms[2];
87 static char *romfile;
88 static char *sramfile;
89 static char *rtcfile;
90 static char *saveprefix;
92 static char *savename;
93 static char *savedir;
95 static int saveslot;
97 static int forcebatt, nobatt;
98 static int forcedmg, gbamode;
100 static int memfill = -1, memrand = -1;
103 static void initmem(void *mem, int size)
105 char *p = mem;
106 if (memrand >= 0)
108 srand(memrand ? memrand : time(0));
109 while(size--) *(p++) = rand();
111 else if (memfill >= 0)
112 memset(p, memfill, size);
115 static byte *loadfile(FILE *f, int *len)
117 int c, l = 0, p = 0;
118 byte *d = 0, buf[512];
120 for(;;)
122 c = fread(buf, 1, sizeof buf, f);
123 if (c <= 0) break;
124 l += c;
125 d = realloc(d, l);
126 if (!d) return 0;
127 memcpy(d+p, buf, c);
128 p += c;
130 *len = l;
131 return d;
134 static byte *inf_buf;
135 static int inf_pos, inf_len;
137 static void inflate_callback(byte b)
139 if (inf_pos >= inf_len)
141 inf_len += 512;
142 inf_buf = realloc(inf_buf, inf_len);
143 if (!inf_buf) die("out of memory inflating file @ %d bytes\n", inf_pos);
145 inf_buf[inf_pos++] = b;
148 static byte *gunzip(byte *data, int *len) {
149 long pos = 0;
150 inf_buf = 0;
151 inf_pos = inf_len = 0;
152 if (unzip(data, &pos, inflate_callback) < 0)
153 return data;
154 *len = inf_pos;
155 return inf_buf;
158 static void write_dec(byte *data, int len) {
159 int i;
160 for(i=0; i < len; i++)
161 inflate_callback(data[i]);
164 static int unxz(byte *data, int len) {
165 struct xz_buf b;
166 struct xz_dec *s;
167 enum xz_ret ret;
168 unsigned char out[4096];
171 * Support up to 64 MiB dictionary. The actually needed memory
172 * is allocated once the headers have been parsed.
174 s = xz_dec_init(XZ_DYNALLOC, 1 << 26);
175 if(!s) goto err;
177 b.in = data;
178 b.in_pos = 0;
179 b.in_size = len;
180 b.out = out;
181 b.out_pos = 0;
182 b.out_size = sizeof(out);
184 while (1) {
185 ret = xz_dec_run(s, &b);
186 if(b.out_pos == sizeof(out)) {
187 write_dec(out, sizeof(out));
188 b.out_pos = 0;
191 if(ret == XZ_OK) continue;
193 write_dec(out, b.out_pos);
195 if(ret == XZ_STREAM_END) {
196 xz_dec_end(s);
197 return 0;
199 goto err;
202 err:
203 xz_dec_end(s);
204 return -1;
207 static byte *do_unxz(byte *data, int *len) {
208 xz_crc32_init();
209 xz_crc64_init();
210 inf_buf = 0;
211 inf_pos = inf_len = 0;
212 if (unxz(data, *len) < 0)
213 return data;
214 *len = inf_pos;
215 return inf_buf;
218 static byte *decompress(byte *data, int *len)
220 if (data[0] == 0x1f && data[1] == 0x8b)
221 return gunzip(data, len);
222 if(data[0] == 0xFD && !memcmp(data+1, "7zXZ", 4))
223 return do_unxz(data, len);
224 return data;
227 static FILE* rom_loadfile(char *fn, byte** data, int *len) {
228 FILE *f;
229 if (strcmp(fn, "-")) f = fopen(fn, "rb");
230 else f = stdin;
231 if (!f) die("cannot open rom file: %s\n", fn);
232 *data = loadfile(f, len);
233 *data = decompress(*data, len);
234 return f;
237 int bootrom_load() {
238 byte *data;
239 int len;
240 FILE *f;
241 REG(RI_BOOT) = 0xff;
242 if (!bootroms[hw.cgb] || !bootroms[hw.cgb][0]) return 0;
243 f = rom_loadfile(bootroms[hw.cgb], &data, &len);
244 bootrom.bank = realloc(data, 16384);
245 memset(bootrom.bank[0]+len, 0xff, 16384-len);
246 memcpy(bootrom.bank[0]+0x100, rom.bank[0]+0x100, 0x100);
247 fclose(f);
248 REG(RI_BOOT) = 0xfe;
249 return 0;
252 int rom_load()
254 FILE *f;
255 byte c, *data, *header;
256 int len = 0, rlen;
257 f = rom_loadfile(romfile, &data, &len);
258 header = data;
260 memcpy(rom.name, header+0x0134, 16);
261 if (rom.name[14] & 0x80) rom.name[14] = 0;
262 if (rom.name[15] & 0x80) rom.name[15] = 0;
263 rom.name[16] = 0;
265 c = header[0x0147];
266 mbc.type = mbc_table[c];
267 mbc.batt = (batt_table[c] && !nobatt) || forcebatt;
268 rtc.batt = rtc_table[c];
269 mbc.romsize = romsize_table[header[0x0148]];
270 mbc.ramsize = ramsize_table[header[0x0149]];
272 if (!mbc.romsize) die("unknown ROM size %02X\n", header[0x0148]);
273 if (!mbc.ramsize) die("unknown SRAM size %02X\n", header[0x0149]);
275 rlen = 16384 * mbc.romsize;
277 c = header[0x0143];
279 /* from this point on, we may no longer access data and header */
280 rom.bank = realloc(data, rlen);
281 if (rlen > len) memset(rom.bank[0]+len, 0xff, rlen - len);
283 ram.sbank = malloc(8192 * mbc.ramsize);
285 initmem(ram.sbank, 8192 * mbc.ramsize);
286 initmem(ram.ibank, 4096 * 8);
288 mbc.rombank = 1;
289 mbc.rambank = 0;
291 hw.cgb = ((c == 0x80) || (c == 0xc0)) && !forcedmg;
292 hw.gba = (hw.cgb && gbamode);
294 if (strcmp(romfile, "-")) fclose(f);
296 return 0;
299 int rom_load_simple(char *fn) {
300 romfile = fn;
301 return rom_load();
304 int sram_load()
306 FILE *f;
308 if (!mbc.batt || !sramfile || !*sramfile) return -1;
310 /* Consider sram loaded at this point, even if file doesn't exist */
311 ram.loaded = 1;
313 f = fopen(sramfile, "rb");
314 if (!f) return -1;
315 fread(ram.sbank, 8192, mbc.ramsize, f);
316 fclose(f);
318 return 0;
322 int sram_save()
324 FILE *f;
326 /* If we crash before we ever loaded sram, DO NOT SAVE! */
327 if (!mbc.batt || !sramfile || !ram.loaded || !mbc.ramsize)
328 return -1;
330 f = fopen(sramfile, "wb");
331 if (!f) return -1;
332 fwrite(ram.sbank, 8192, mbc.ramsize, f);
333 fclose(f);
335 return 0;
339 void state_save(int n)
341 FILE *f;
342 char *name;
344 if (n < 0) n = saveslot;
345 if (n < 0) n = 0;
346 name = malloc(strlen(saveprefix) + 5);
347 sprintf(name, "%s.%03d", saveprefix, n);
349 if ((f = fopen(name, "wb")))
351 savestate(f);
352 fclose(f);
354 free(name);
358 void state_load(int n)
360 FILE *f;
361 char *name;
363 if (n < 0) n = saveslot;
364 if (n < 0) n = 0;
365 name = malloc(strlen(saveprefix) + 5);
366 sprintf(name, "%s.%03d", saveprefix, n);
368 if ((f = fopen(name, "rb")))
370 loadstate(f);
371 fclose(f);
372 vram_dirty();
373 pal_dirty();
374 sound_dirty();
375 mem_updatemap();
377 free(name);
380 void rtc_save()
382 FILE *f;
383 if (!rtc.batt) return;
384 if (!(f = fopen(rtcfile, "wb"))) return;
385 rtc_save_internal(f);
386 fclose(f);
389 void rtc_load()
391 FILE *f;
392 if (!rtc.batt) return;
393 if (!(f = fopen(rtcfile, "r"))) return;
394 rtc_load_internal(f);
395 fclose(f);
399 void loader_unload()
401 sram_save();
402 if (romfile) free(romfile);
403 if (sramfile) free(sramfile);
404 if (saveprefix) free(saveprefix);
405 if (rom.bank) free(rom.bank);
406 if (ram.sbank) free(ram.sbank);
407 romfile = sramfile = saveprefix = 0;
408 rom.bank = 0;
409 ram.sbank = 0;
410 mbc.type = mbc.romsize = mbc.ramsize = mbc.batt = 0;
413 static char *base(char *s)
415 char *p;
416 p = strrchr(s, '/');
417 if (p) return p+1;
418 return s;
421 static char *ldup(char *s)
423 int i;
424 char *n, *p;
425 p = n = malloc(strlen(s));
426 for (i = 0; s[i]; i++) if (isalnum(s[i])) *(p++) = tolower(s[i]);
427 *p = 0;
428 return n;
431 static void cleanup()
433 sram_save();
434 rtc_save();
435 /* IDEA - if error, write emergency savestate..? */
438 void loader_init(char *s)
440 char *name, *p;
442 sys_checkdir(savedir, 1); /* needs to be writable */
444 romfile = s;
445 rom_load();
446 bootrom_load();
447 vid_settitle(rom.name);
448 if (savename && *savename)
450 if (savename[0] == '-' && savename[1] == 0)
451 name = ldup(rom.name);
452 else name = strdup(savename);
454 else if (romfile && *base(romfile) && strcmp(romfile, "-"))
456 name = strdup(base(romfile));
457 p = strchr(name, '.');
458 if (p) *p = 0;
460 else name = ldup(rom.name);
462 saveprefix = malloc(strlen(savedir) + strlen(name) + 2);
463 sprintf(saveprefix, "%s/%s", savedir, name);
465 sramfile = malloc(strlen(saveprefix) + 5);
466 strcpy(sramfile, saveprefix);
467 strcat(sramfile, ".sav");
469 rtcfile = malloc(strlen(saveprefix) + 5);
470 strcpy(rtcfile, saveprefix);
471 strcat(rtcfile, ".rtc");
473 sram_load();
474 rtc_load();
476 atexit(cleanup);
479 rcvar_t loader_exports[] =
481 RCV_STRING("bootrom_dmg", &bootroms[0], "bootrom for DMG games"),
482 RCV_STRING("bootrom_cgb", &bootroms[1], "bootrom for CGB games"),
483 RCV_STRING("savedir", &savedir, "save directory"),
484 RCV_STRING("savename", &savename, "base filename for saves"),
485 RCV_INT("saveslot", &saveslot, "which savestate slot to use"),
486 RCV_BOOL("forcebatt", &forcebatt, "save SRAM even on carts w/o battery"),
487 RCV_BOOL("nobatt", &nobatt, "never save SRAM"),
488 RCV_BOOL("forcedmg", &forcedmg, "force DMG mode for CGB carts"),
489 RCV_BOOL("gbamode", &gbamode, "simulate cart being used on a GBA"),
490 RCV_INT("memfill", &memfill, ""),
491 RCV_INT("memrand", &memrand, ""),
492 RCV_END