loader: don't crash on zero-length files
[rofl0r-gnuboy.git] / loader.c
blob5ef042d8267f1038ba1798824244aaaa2921f5cc
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 <stdarg.h>
10 #include <ctype.h>
11 #include <time.h>
13 #include "defs.h"
14 #include "loader.h"
15 #include "regs.h"
16 #include "mem.h"
17 #include "hw.h"
18 #include "rtc.h"
19 #include "rc.h"
20 #include "lcd.h"
21 #include "inflate.h"
22 #define XZ_USE_CRC64
23 #include "xz/xz.h"
24 #include "save.h"
25 #include "sound.h"
26 #include "sys.h"
28 static int mbc_table[256] =
30 0, 1, 1, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3,
31 3, 3, 3, 3, 0, 0, 0, 0, 0, 5, 5, 5, MBC_RUMBLE, MBC_RUMBLE, MBC_RUMBLE, 0,
32 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,
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,
37 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,
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,
42 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,
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, 0, 0,
47 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
48 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MBC_HUC3, MBC_HUC1
51 static int rtc_table[256] =
53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
54 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
58 static int batt_table[256] =
60 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0,
61 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
65 static int romsize_table[256] =
67 2, 4, 8, 16, 32, 64, 128, 256, 512,
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, 0, 0, 0, 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0, 0,
77 0, 0, 128, 128, 128
78 /* 0, 0, 72, 80, 96 -- actual values but bad to use these! */
81 static int ramsize_table[256] =
83 1, 1, 1, 4, 16,
84 4 /* FIXME - what value should this be?! */
88 static char *bootroms[2];
89 static char *romfile;
90 static char *sramfile;
91 static char *rtcfile;
92 static char *saveprefix;
94 static char *savename;
95 static char *savedir;
97 static int saveslot;
99 static int forcebatt, nobatt;
100 static int forcedmg, gbamode;
102 static int memfill = -1, memrand = -1;
105 static void initmem(void *mem, int size)
107 char *p = mem;
108 if (memrand >= 0)
110 srand(memrand ? memrand : time(0));
111 while(size--) *(p++) = rand();
113 else if (memfill >= 0)
114 memset(p, memfill, size);
117 static byte *loadfile(FILE *f, int *len)
119 int c, l = 0, p = 0;
120 byte *d = 0, buf[4096];
122 for(;;)
124 c = fread(buf, 1, sizeof buf, f);
125 if (c <= 0) break;
126 l += c;
127 d = realloc(d, l);
128 if (!d) return 0;
129 memcpy(d+p, buf, c);
130 p += c;
132 *len = l;
133 return d;
136 static byte *inf_buf;
137 static int inf_pos, inf_len;
138 static char* loader_error;
140 char* loader_get_error(void)
142 return loader_error;
145 void loader_set_error(char *fmt, ...)
147 char buf[1024];
148 va_list ap;
149 va_start(ap, fmt);
150 vsnprintf(buf, sizeof buf, fmt, ap);
151 va_end(ap);
152 loader_error = strdup(buf);
155 static int inflate_callback(byte b)
157 if (inf_pos >= inf_len)
159 inf_len += 512;
160 inf_buf = realloc(inf_buf, inf_len);
161 if (!inf_buf) {
162 loader_set_error("out of memory inflating file @ %d bytes\n", inf_pos);
163 return -1;
166 inf_buf[inf_pos++] = b;
167 return 0;
170 typedef int (*unzip_or_inflate_func) (const unsigned char *data, long *p, int (* callback) (unsigned char d));
172 static byte *gunzip_or_inflate(byte *data, int *len, unsigned offset,
173 unzip_or_inflate_func func)
175 long pos = 0;
176 inf_buf = 0;
177 inf_pos = inf_len = 0;
178 if (func(data+offset, &pos, inflate_callback) < 0)
179 return data;
180 free(data);
181 *len = inf_pos;
182 return inf_buf;
185 static byte *gunzip(byte *data, int *len) {
186 return gunzip_or_inflate(data, len, 0, unzip);
189 /* primitive pkzip decompressor. it can only decompress the first
190 file in a zip archive. */
191 static byte *pkunzip(byte *data, int *len) {
192 unsigned short fnl, el, comp;
193 unsigned int st;
194 if (*len < 128) return data;
195 memcpy(&comp, data+8, 2);
196 comp = LIL(comp);
197 if(comp != 0 && comp != 8) return data;
198 memcpy(&fnl, data+26, 2);
199 memcpy(&el, data+28, 2);
200 fnl = LIL(fnl);
201 el = LIL(el);
202 st = 30 + fnl + el;
203 if(*len < st) return data;
204 if(comp == 0) {
205 inf_buf = realloc(NULL, *len - st);
206 memcpy(inf_buf, data+st, *len - st);
207 free(data);
208 inf_len = *len = *len - st;
209 return inf_buf;
211 *len -= st;
212 return gunzip_or_inflate(data, len, st, inflate);
215 static int write_dec(byte *data, int len) {
216 int i;
217 for(i=0; i < len; i++)
218 if(inflate_callback(data[i])) return -1;
219 return 0;
222 static int unxz(byte *data, int len) {
223 struct xz_buf b;
224 struct xz_dec *s;
225 enum xz_ret ret;
226 unsigned char out[4096];
229 * Support up to 64 MiB dictionary. The actually needed memory
230 * is allocated once the headers have been parsed.
232 s = xz_dec_init(XZ_DYNALLOC, 1 << 26);
233 if(!s) goto err;
235 b.in = data;
236 b.in_pos = 0;
237 b.in_size = len;
238 b.out = out;
239 b.out_pos = 0;
240 b.out_size = sizeof(out);
242 while (1) {
243 ret = xz_dec_run(s, &b);
244 if(b.out_pos == sizeof(out)) {
245 if(write_dec(out, sizeof(out))) goto err;
246 b.out_pos = 0;
249 if(ret == XZ_OK) continue;
251 if(write_dec(out, b.out_pos)) goto err;
253 if(ret == XZ_STREAM_END) {
254 xz_dec_end(s);
255 return 0;
257 goto err;
260 err:
261 xz_dec_end(s);
262 return -1;
265 static byte *do_unxz(byte *data, int *len) {
266 xz_crc32_init();
267 xz_crc64_init();
268 inf_buf = 0;
269 inf_pos = inf_len = 0;
270 if (unxz(data, *len) < 0)
271 return data;
272 free(data);
273 *len = inf_pos;
274 return inf_buf;
277 static byte *decompress(byte *data, int *len)
279 if (data[0] == 0x1f && data[1] == 0x8b)
280 return gunzip(data, len);
281 if (data[0] == 0xFD && !memcmp(data+1, "7zXZ", 4))
282 return do_unxz(data, len);
283 if (data[0] == 'P' && !memcmp(data+1, "K\03\04", 3))
284 return pkunzip(data, len);
285 return data;
288 static FILE* rom_loadfile(char *fn, byte** data, int *len) {
289 FILE *f;
290 if (strcmp(fn, "-")) f = fopen(fn, "rb");
291 else f = stdin;
292 if (!f) {
293 err:
294 loader_set_error("cannot open rom file: %s\n", fn);
295 return f;
297 *data = loadfile(f, len);
298 if (!*data) {
299 fclose(f);
300 f = 0;
301 goto err;
303 *data = decompress(*data, len);
304 return f;
307 int bootrom_load() {
308 byte *data;
309 int len;
310 FILE *f;
311 REG(RI_BOOT) = 0xff;
312 if (!bootroms[hw.cgb] || !bootroms[hw.cgb][0]) return 0;
313 f = rom_loadfile(bootroms[hw.cgb], &data, &len);
314 if(!f) return -1;
315 bootrom.bank = realloc(data, 16384);
316 memset(bootrom.bank[0]+len, 0xff, 16384-len);
317 memcpy(bootrom.bank[0]+0x100, rom.bank[0]+0x100, 0x100);
318 fclose(f);
319 REG(RI_BOOT) = 0xfe;
320 return 0;
323 /* memory allocation breakdown:
324 loadfile returns local buffer retrieved via realloc()
325 it's called only by rom_loadfile.
326 rom_loadfile is called by bootrom_load and rom_load.
327 bootrom_load is called once per romfile load via loader_init from
328 load_rom_and_rc, and mem ends up in bootrom.bank, loader_unload() frees it.
329 rom_load is called by rom_load_simple and loader_init().
330 rom_load_simple is only called by rominfo in main.c, which we can ignore.
331 the mem allocated by loadfile thru loader_init/rom_load ends up in
332 rom.bank, which is freed in loader_unload(), just like the malloc'd
333 rom.sbank.
334 where it gets complicated is when rom_loadfile uncompresses data.
335 the allocation returned by loadfile is passed to decompress().
336 if it fails, it returns the original loadfile allocation, on success
337 it returns a pointer to inf_buf which contains the uncompressed data.
340 int rom_load()
342 FILE *f;
343 byte c, *data, *header;
344 int len = 0, rlen;
345 f = rom_loadfile(romfile, &data, &len);
346 if(!f) return -1;
347 header = data;
349 memcpy(rom.name, header+0x0134, 16);
350 if (rom.name[14] & 0x80) rom.name[14] = 0;
351 if (rom.name[15] & 0x80) rom.name[15] = 0;
352 rom.name[16] = 0;
354 c = header[0x0147];
355 mbc.type = mbc_table[c];
356 mbc.batt = (batt_table[c] && !nobatt) || forcebatt;
357 rtc.batt = rtc_table[c];
358 mbc.romsize = romsize_table[header[0x0148]];
359 mbc.ramsize = ramsize_table[header[0x0149]];
361 if (!mbc.romsize) {
362 loader_set_error("unknown ROM size %02X\n", header[0x0148]);
363 return -1;
365 if (!mbc.ramsize) {
366 loader_set_error("unknown SRAM size %02X\n", header[0x0149]);
367 return -1;
370 rlen = 16384 * mbc.romsize;
372 c = header[0x0143];
374 /* from this point on, we may no longer access data and header */
375 rom.bank = realloc(data, rlen);
376 if (rlen > len) memset(rom.bank[0]+len, 0xff, rlen - len);
378 ram.sbank = malloc(8192 * mbc.ramsize);
380 initmem(ram.sbank, 8192 * mbc.ramsize);
381 initmem(ram.ibank, 4096 * 8);
383 mbc.rombank = 1;
384 mbc.rambank = 0;
386 hw.cgb = ((c == 0x80) || (c == 0xc0)) && !forcedmg;
387 hw.gba = (hw.cgb && gbamode);
389 if (strcmp(romfile, "-")) fclose(f);
391 return 0;
394 int rom_load_simple(char *fn) {
395 romfile = fn;
396 return rom_load();
399 int sram_load()
401 FILE *f;
403 if (!mbc.batt || !sramfile || !*sramfile) return -1;
405 /* Consider sram loaded at this point, even if file doesn't exist */
406 ram.loaded = 1;
408 f = fopen(sramfile, "rb");
409 if (!f) return -1;
410 fread(ram.sbank, 8192, mbc.ramsize, f);
411 fclose(f);
413 return 0;
417 int sram_save()
419 FILE *f;
421 /* If we crash before we ever loaded sram, DO NOT SAVE! */
422 if (!mbc.batt || !sramfile || !ram.loaded || !mbc.ramsize)
423 return -1;
425 f = fopen(sramfile, "wb");
426 if (!f) return -1;
427 fwrite(ram.sbank, 8192, mbc.ramsize, f);
428 fclose(f);
430 return 0;
434 void state_save(int n)
436 FILE *f;
437 char *name;
439 if (n < 0) n = saveslot;
440 if (n < 0) n = 0;
441 name = malloc(strlen(saveprefix) + 5);
442 sprintf(name, "%s.%03d", saveprefix, n);
444 if ((f = fopen(name, "wb")))
446 savestate(f);
447 fclose(f);
449 free(name);
453 void state_load(int n)
455 FILE *f;
456 char *name;
458 if (n < 0) n = saveslot;
459 if (n < 0) n = 0;
460 name = malloc(strlen(saveprefix) + 5);
461 sprintf(name, "%s.%03d", saveprefix, n);
463 if ((f = fopen(name, "rb")))
465 loadstate(f);
466 fclose(f);
467 vram_dirty();
468 pal_dirty();
469 sound_dirty();
470 mem_updatemap();
472 free(name);
475 void rtc_save()
477 FILE *f;
478 if (!rtc.batt) return;
479 if (!(f = fopen(rtcfile, "wb"))) return;
480 rtc_save_internal(f);
481 fclose(f);
484 void rtc_load()
486 FILE *f;
487 if (!rtc.batt) return;
488 if (!(f = fopen(rtcfile, "r"))) return;
489 rtc_load_internal(f);
490 fclose(f);
494 void loader_unload()
496 sram_save();
497 if (romfile) free(romfile);
498 if (sramfile) free(sramfile);
499 if (saveprefix) free(saveprefix);
500 if (rom.bank) free(rom.bank);
501 if (ram.sbank) free(ram.sbank);
502 if (bootrom.bank) free(bootrom.bank);
503 romfile = sramfile = saveprefix = 0;
504 rom.bank = 0;
505 ram.sbank = 0;
506 mbc.type = mbc.romsize = mbc.ramsize = mbc.batt = 0;
509 static char *base(char *s)
511 char *p;
512 p = strrchr(s, '/');
513 if (p) return p+1;
514 return s;
517 static char *ldup(char *s)
519 int i;
520 char *n, *p;
521 p = n = malloc(strlen(s));
522 for (i = 0; s[i]; i++) if (isalnum(s[i])) *(p++) = tolower(s[i]);
523 *p = 0;
524 return n;
527 static void cleanup()
529 sram_save();
530 rtc_save();
531 /* IDEA - if error, write emergency savestate..? */
534 int loader_init(char *s)
536 char *name, *p;
538 sys_checkdir(savedir, 1); /* needs to be writable */
540 romfile = s;
541 if(rom_load()) return -1;
542 bootrom_load();
543 vid_settitle(rom.name);
544 if (savename && *savename)
546 if (savename[0] == '-' && savename[1] == 0)
547 name = ldup(rom.name);
548 else name = strdup(savename);
550 else if (romfile && *base(romfile) && strcmp(romfile, "-"))
552 name = strdup(base(romfile));
553 p = strchr(name, '.');
554 if (p) *p = 0;
556 else name = ldup(rom.name);
558 saveprefix = malloc(strlen(savedir) + strlen(name) + 2);
559 sprintf(saveprefix, "%s/%s", savedir, name);
561 sramfile = malloc(strlen(saveprefix) + 5);
562 strcpy(sramfile, saveprefix);
563 strcat(sramfile, ".sav");
565 rtcfile = malloc(strlen(saveprefix) + 5);
566 strcpy(rtcfile, saveprefix);
567 strcat(rtcfile, ".rtc");
569 sram_load();
570 rtc_load();
572 atexit(cleanup);
573 return 0;
576 rcvar_t loader_exports[] =
578 RCV_STRING("bootrom_dmg", &bootroms[0], "bootrom for DMG games"),
579 RCV_STRING("bootrom_cgb", &bootroms[1], "bootrom for CGB games"),
580 RCV_STRING("savedir", &savedir, "save directory"),
581 RCV_STRING("savename", &savename, "base filename for saves"),
582 RCV_INT("saveslot", &saveslot, "which savestate slot to use"),
583 RCV_BOOL("forcebatt", &forcebatt, "save SRAM even on carts w/o battery"),
584 RCV_BOOL("nobatt", &nobatt, "never save SRAM"),
585 RCV_BOOL("forcedmg", &forcedmg, "force DMG mode for CGB carts"),
586 RCV_BOOL("gbamode", &gbamode, "simulate cart being used on a GBA"),
587 RCV_INT("memfill", &memfill, ""),
588 RCV_INT("memrand", &memrand, ""),
589 RCV_END