fix some gcc warnings
[rofl0r-gnuboy.git] / loader.c
blobdc8536bcb239099138b807594be84540bf9d2692
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 #include "save.h"
21 #include "sound.h"
22 #include "sys.h"
24 static int mbc_table[256] =
26 0, 1, 1, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3,
27 3, 3, 3, 3, 0, 0, 0, 0, 0, 5, 5, 5, MBC_RUMBLE, MBC_RUMBLE, MBC_RUMBLE, 0,
28 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29 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,
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,
34 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,
39 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,
44 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MBC_HUC3, MBC_HUC1
47 static int rtc_table[256] =
49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
50 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54 static int batt_table[256] =
56 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0,
57 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
61 static int romsize_table[256] =
63 2, 4, 8, 16, 32, 64, 128, 256, 512,
64 0, 0, 0, 0, 0, 0, 0, 0,
65 0, 0, 0, 0, 0, 0, 0, 0,
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, 128, 128, 128
74 /* 0, 0, 72, 80, 96 -- actual values but bad to use these! */
77 static int ramsize_table[256] =
79 1, 1, 1, 4, 16,
80 4 /* FIXME - what value should this be?! */
84 static char *romfile;
85 static char *sramfile;
86 static char *rtcfile;
87 static char *saveprefix;
89 static char *savename;
90 static char *savedir;
92 static int saveslot;
94 static int forcebatt, nobatt;
95 static int forcedmg, gbamode;
97 static int memfill = -1, memrand = -1;
100 static void initmem(void *mem, int size)
102 char *p = mem;
103 if (memrand >= 0)
105 srand(memrand ? memrand : time(0));
106 while(size--) *(p++) = rand();
108 else if (memfill >= 0)
109 memset(p, memfill, size);
112 static byte *loadfile(FILE *f, int *len)
114 int c, l = 0, p = 0;
115 byte *d = 0, buf[512];
117 for(;;)
119 c = fread(buf, 1, sizeof buf, f);
120 if (c <= 0) break;
121 l += c;
122 d = realloc(d, l);
123 if (!d) return 0;
124 memcpy(d+p, buf, c);
125 p += c;
127 *len = l;
128 return d;
131 static byte *inf_buf;
132 static int inf_pos, inf_len;
134 static void inflate_callback(byte b)
136 if (inf_pos >= inf_len)
138 inf_len += 512;
139 inf_buf = realloc(inf_buf, inf_len);
140 if (!inf_buf) die("out of memory inflating file @ %d bytes\n", inf_pos);
142 inf_buf[inf_pos++] = b;
145 static byte *decompress(byte *data, int *len)
147 unsigned long pos = 0;
148 if (data[0] != 0x1f || data[1] != 0x8b)
149 return data;
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;
159 int rom_load()
161 FILE *f;
162 byte c, *data, *header;
163 int len = 0, rlen;
165 if (strcmp(romfile, "-")) f = fopen(romfile, "rb");
166 else f = stdin;
167 if (!f) die("cannot open rom file: %s\n", romfile);
169 data = loadfile(f, &len);
170 header = data = decompress(data, &len);
172 memcpy(rom.name, header+0x0134, 16);
173 if (rom.name[14] & 0x80) rom.name[14] = 0;
174 if (rom.name[15] & 0x80) rom.name[15] = 0;
175 rom.name[16] = 0;
177 c = header[0x0147];
178 mbc.type = mbc_table[c];
179 mbc.batt = (batt_table[c] && !nobatt) || forcebatt;
180 rtc.batt = rtc_table[c];
181 mbc.romsize = romsize_table[header[0x0148]];
182 mbc.ramsize = ramsize_table[header[0x0149]];
184 if (!mbc.romsize) die("unknown ROM size %02X\n", header[0x0148]);
185 if (!mbc.ramsize) die("unknown SRAM size %02X\n", header[0x0149]);
187 rlen = 16384 * mbc.romsize;
188 rom.bank = realloc(data, rlen);
189 if (rlen > len) memset(rom.bank[0]+len, 0xff, rlen - len);
191 ram.sbank = malloc(8192 * mbc.ramsize);
193 initmem(ram.sbank, 8192 * mbc.ramsize);
194 initmem(ram.ibank, 4096 * 8);
196 mbc.rombank = 1;
197 mbc.rambank = 0;
199 c = header[0x0143];
200 hw.cgb = ((c == 0x80) || (c == 0xc0)) && !forcedmg;
201 hw.gba = (hw.cgb && gbamode);
203 if (strcmp(romfile, "-")) fclose(f);
205 return 0;
208 int sram_load()
210 FILE *f;
212 if (!mbc.batt || !sramfile || !*sramfile) return -1;
214 /* Consider sram loaded at this point, even if file doesn't exist */
215 ram.loaded = 1;
217 f = fopen(sramfile, "rb");
218 if (!f) return -1;
219 fread(ram.sbank, 8192, mbc.ramsize, f);
220 fclose(f);
222 return 0;
226 int sram_save()
228 FILE *f;
230 /* If we crash before we ever loaded sram, DO NOT SAVE! */
231 if (!mbc.batt || !sramfile || !ram.loaded || !mbc.ramsize)
232 return -1;
234 f = fopen(sramfile, "wb");
235 if (!f) return -1;
236 fwrite(ram.sbank, 8192, mbc.ramsize, f);
237 fclose(f);
239 return 0;
243 void state_save(int n)
245 FILE *f;
246 char *name;
248 if (n < 0) n = saveslot;
249 if (n < 0) n = 0;
250 name = malloc(strlen(saveprefix) + 5);
251 sprintf(name, "%s.%03d", saveprefix, n);
253 if ((f = fopen(name, "wb")))
255 savestate(f);
256 fclose(f);
258 free(name);
262 void state_load(int n)
264 FILE *f;
265 char *name;
267 if (n < 0) n = saveslot;
268 if (n < 0) n = 0;
269 name = malloc(strlen(saveprefix) + 5);
270 sprintf(name, "%s.%03d", saveprefix, n);
272 if ((f = fopen(name, "rb")))
274 loadstate(f);
275 fclose(f);
276 vram_dirty();
277 pal_dirty();
278 sound_dirty();
279 mem_updatemap();
281 free(name);
284 void rtc_save()
286 FILE *f;
287 if (!rtc.batt) return;
288 if (!(f = fopen(rtcfile, "wb"))) return;
289 rtc_save_internal(f);
290 fclose(f);
293 void rtc_load()
295 FILE *f;
296 if (!rtc.batt) return;
297 if (!(f = fopen(rtcfile, "r"))) return;
298 rtc_load_internal(f);
299 fclose(f);
303 void loader_unload()
305 sram_save();
306 if (romfile) free(romfile);
307 if (sramfile) free(sramfile);
308 if (saveprefix) free(saveprefix);
309 if (rom.bank) free(rom.bank);
310 if (ram.sbank) free(ram.sbank);
311 romfile = sramfile = saveprefix = 0;
312 rom.bank = 0;
313 ram.sbank = 0;
314 mbc.type = mbc.romsize = mbc.ramsize = mbc.batt = 0;
317 static char *base(char *s)
319 char *p;
320 p = strrchr(s, '/');
321 if (p) return p+1;
322 return s;
325 static char *ldup(char *s)
327 int i;
328 char *n, *p;
329 p = n = malloc(strlen(s));
330 for (i = 0; s[i]; i++) if (isalnum(s[i])) *(p++) = tolower(s[i]);
331 *p = 0;
332 return n;
335 static void cleanup()
337 sram_save();
338 rtc_save();
339 /* IDEA - if error, write emergency savestate..? */
342 void loader_init(char *s)
344 char *name, *p;
346 sys_checkdir(savedir, 1); /* needs to be writable */
348 romfile = s;
349 rom_load();
350 vid_settitle(rom.name);
351 if (savename && *savename)
353 if (savename[0] == '-' && savename[1] == 0)
354 name = ldup(rom.name);
355 else name = strdup(savename);
357 else if (romfile && *base(romfile) && strcmp(romfile, "-"))
359 name = strdup(base(romfile));
360 p = strchr(name, '.');
361 if (p) *p = 0;
363 else name = ldup(rom.name);
365 saveprefix = malloc(strlen(savedir) + strlen(name) + 2);
366 sprintf(saveprefix, "%s/%s", savedir, name);
368 sramfile = malloc(strlen(saveprefix) + 5);
369 strcpy(sramfile, saveprefix);
370 strcat(sramfile, ".sav");
372 rtcfile = malloc(strlen(saveprefix) + 5);
373 strcpy(rtcfile, saveprefix);
374 strcat(rtcfile, ".rtc");
376 sram_load();
377 rtc_load();
379 atexit(cleanup);
382 rcvar_t loader_exports[] =
384 RCV_STRING("savedir", &savedir),
385 RCV_STRING("savename", &savename),
386 RCV_INT("saveslot", &saveslot),
387 RCV_BOOL("forcebatt", &forcebatt),
388 RCV_BOOL("nobatt", &nobatt),
389 RCV_BOOL("forcedmg", &forcedmg),
390 RCV_BOOL("gbamode", &gbamode),
391 RCV_INT("memfill", &memfill),
392 RCV_INT("memrand", &memrand),
393 RCV_END