2 #define _POSIX_C_SOURCE 200809L
29 static int mbc_table
[256] =
31 0, 1, 1, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3,
32 3, 3, 3, 3, 0, 0, 0, 0, 0, 5, 5, 5, MBC_RUMBLE
, MBC_RUMBLE
, MBC_RUMBLE
, 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, 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, 0, 0,
49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MBC_HUC3
, MBC_HUC1
52 static int rtc_table
[256] =
54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
55 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59 static int batt_table
[256] =
61 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0,
62 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
66 static int romsize_table
[256] =
68 2, 4, 8, 16, 32, 64, 128, 256, 512,
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, 0, 0, 0, 0, 0, 0,
79 /* 0, 0, 72, 80, 96 -- actual values but bad to use these! */
82 static int ramsize_table
[256] =
85 4 /* FIXME - what value should this be?! */
89 static char *bootroms
[2];
91 static char *sramfile
;
93 static char *saveprefix
;
95 static char *savename
;
100 static int forcebatt
, nobatt
;
101 static int forcedmg
, gbamode
;
103 static int memfill
= -1, memrand
= -1;
106 static void initmem(void *mem
, int size
)
111 srand(memrand
? memrand
: time(0));
112 while(size
--) *(p
++) = rand();
114 else if (memfill
>= 0)
115 memset(p
, memfill
, size
);
118 static byte
*loadfile(FILE *f
, int *len
)
121 byte
*d
= 0, buf
[4096];
125 c
= fread(buf
, 1, sizeof buf
, f
);
137 static byte
*inf_buf
;
138 static int inf_pos
, inf_len
;
139 static char* loader_error
;
141 char* loader_get_error(void)
146 void loader_set_error(char *fmt
, ...)
151 vsnprintf(buf
, sizeof buf
, fmt
, ap
);
153 loader_error
= strdup(buf
);
156 static int inflate_callback(byte b
)
158 if (inf_pos
>= inf_len
)
161 inf_buf
= realloc(inf_buf
, inf_len
);
163 loader_set_error("out of memory inflating file @ %d bytes\n", inf_pos
);
167 inf_buf
[inf_pos
++] = b
;
171 typedef int (*unzip_or_inflate_func
) (const unsigned char *data
, long *p
, int (* callback
) (unsigned char d
));
173 static byte
*gunzip_or_inflate(byte
*data
, int *len
, unsigned offset
,
174 unzip_or_inflate_func func
)
178 inf_pos
= inf_len
= 0;
179 if (func(data
+offset
, &pos
, inflate_callback
) < 0)
186 static byte
*gunzip(byte
*data
, int *len
) {
187 return gunzip_or_inflate(data
, len
, 0, unzip
);
190 /* primitive pkzip decompressor. it can only decompress the first
191 file in a zip archive. */
192 static byte
*pkunzip(byte
*data
, int *len
) {
193 unsigned short fnl
, el
, comp
;
198 if (*len
< 128) return data
;
199 memcpy(&comp
, data
+8, 2);
201 if(comp
!= 0 && comp
!= 8) return data
;
202 memcpy(&fnl
, data
+26, 2);
203 memcpy(&el
, data
+28, 2);
207 if(*len
< st
) return data
;
209 inf_buf
= realloc(NULL
, *len
- st
);
210 memcpy(inf_buf
, data
+st
, *len
- st
);
212 inf_len
= *len
= *len
- st
;
217 new = tinfl_decompress_mem_to_heap(data
+st
, *len
, &newlen
, 0);
227 static int write_dec(byte
*data
, int len
) {
229 for(i
=0; i
< len
; i
++)
230 if(inflate_callback(data
[i
])) return -1;
234 static int unxz(byte
*data
, int len
) {
238 unsigned char out
[4096];
241 * Support up to 64 MiB dictionary. The actually needed memory
242 * is allocated once the headers have been parsed.
244 s
= xz_dec_init(XZ_DYNALLOC
, 1 << 26);
252 b
.out_size
= sizeof(out
);
255 ret
= xz_dec_run(s
, &b
);
256 if(b
.out_pos
== sizeof(out
)) {
257 if(write_dec(out
, sizeof(out
))) goto err
;
261 if(ret
== XZ_OK
) continue;
263 if(write_dec(out
, b
.out_pos
)) goto err
;
265 if(ret
== XZ_STREAM_END
) {
277 static byte
*do_unxz(byte
*data
, int *len
) {
281 inf_pos
= inf_len
= 0;
282 if (unxz(data
, *len
) < 0)
289 static byte
*decompress(byte
*data
, int *len
)
291 if (data
[0] == 0x1f && data
[1] == 0x8b)
292 return gunzip(data
, len
);
293 if (data
[0] == 0xFD && !memcmp(data
+1, "7zXZ", 4))
294 return do_unxz(data
, len
);
295 if (data
[0] == 'P' && !memcmp(data
+1, "K\03\04", 3))
296 return pkunzip(data
, len
);
300 static FILE* rom_loadfile(char *fn
, byte
** data
, int *len
) {
302 if (strcmp(fn
, "-")) f
= fopen(fn
, "rb");
306 loader_set_error("cannot open rom file: %s\n", fn
);
309 *data
= loadfile(f
, len
);
315 *data
= decompress(*data
, len
);
324 if (!bootroms
[hw
.cgb
] || !bootroms
[hw
.cgb
][0]) return 0;
325 f
= rom_loadfile(bootroms
[hw
.cgb
], &data
, &len
);
327 bootrom
.bank
= realloc(data
, 16384);
328 memset(bootrom
.bank
[0]+len
, 0xff, 16384-len
);
329 memcpy(bootrom
.bank
[0]+0x100, rom
.bank
[0]+0x100, 0x100);
335 /* memory allocation breakdown:
336 loadfile returns local buffer retrieved via realloc()
337 it's called only by rom_loadfile.
338 rom_loadfile is called by bootrom_load and rom_load.
339 bootrom_load is called once per romfile load via loader_init from
340 load_rom_and_rc, and mem ends up in bootrom.bank, loader_unload() frees it.
341 rom_load is called by rom_load_simple and loader_init().
342 rom_load_simple is only called by rominfo in main.c, which we can ignore.
343 the mem allocated by loadfile thru loader_init/rom_load ends up in
344 rom.bank, which is freed in loader_unload(), just like the malloc'd
346 where it gets complicated is when rom_loadfile uncompresses data.
347 the allocation returned by loadfile is passed to decompress().
348 if it fails, it returns the original loadfile allocation, on success
349 it returns a pointer to inf_buf which contains the uncompressed data.
355 byte c
, *data
, *header
;
357 f
= rom_loadfile(romfile
, &data
, &len
);
361 memcpy(rom
.name
, header
+0x0134, 16);
362 if (rom
.name
[14] & 0x80) rom
.name
[14] = 0;
363 if (rom
.name
[15] & 0x80) rom
.name
[15] = 0;
367 mbc
.type
= mbc_table
[c
];
368 mbc
.batt
= (batt_table
[c
] && !nobatt
) || forcebatt
;
369 rtc
.batt
= rtc_table
[c
];
370 mbc
.romsize
= romsize_table
[header
[0x0148]];
371 mbc
.ramsize
= ramsize_table
[header
[0x0149]];
374 loader_set_error("unknown ROM size %02X\n", header
[0x0148]);
378 loader_set_error("unknown SRAM size %02X\n", header
[0x0149]);
382 rlen
= 16384 * mbc
.romsize
;
386 /* from this point on, we may no longer access data and header */
387 rom
.bank
= realloc(data
, rlen
);
388 if (rlen
> len
) memset(rom
.bank
[0]+len
, 0xff, rlen
- len
);
390 ram
.sbank
= malloc(8192 * mbc
.ramsize
);
392 initmem(ram
.sbank
, 8192 * mbc
.ramsize
);
393 initmem(ram
.ibank
, 4096 * 8);
398 hw
.cgb
= ((c
== 0x80) || (c
== 0xc0)) && !forcedmg
;
399 hw
.gba
= (hw
.cgb
&& gbamode
);
401 if (strcmp(romfile
, "-")) fclose(f
);
406 int rom_load_simple(char *fn
) {
415 if (!mbc
.batt
|| !sramfile
|| !*sramfile
) return -1;
417 /* Consider sram loaded at this point, even if file doesn't exist */
420 f
= fopen(sramfile
, "rb");
422 fread(ram
.sbank
, 8192, mbc
.ramsize
, f
);
433 /* If we crash before we ever loaded sram, DO NOT SAVE! */
434 if (!mbc
.batt
|| !sramfile
|| !ram
.loaded
|| !mbc
.ramsize
)
437 f
= fopen(sramfile
, "wb");
439 fwrite(ram
.sbank
, 8192, mbc
.ramsize
, f
);
446 void state_save(int n
)
451 if (n
< 0) n
= saveslot
;
453 name
= malloc(strlen(saveprefix
) + 5);
454 sprintf(name
, "%s.%03d", saveprefix
, n
);
456 if ((f
= fopen(name
, "wb")))
465 void state_load(int n
)
470 if (n
< 0) n
= saveslot
;
472 name
= malloc(strlen(saveprefix
) + 5);
473 sprintf(name
, "%s.%03d", saveprefix
, n
);
475 if ((f
= fopen(name
, "rb")))
490 if (!rtc
.batt
) return;
491 if (!(f
= fopen(rtcfile
, "wb"))) return;
492 rtc_save_internal(f
);
499 if (!rtc
.batt
) return;
500 if (!(f
= fopen(rtcfile
, "r"))) return;
501 rtc_load_internal(f
);
505 #define FREENULL(X) do { free(X); X = 0; } while(0)
509 if (romfile
) FREENULL(romfile
);
510 if (sramfile
) FREENULL(sramfile
);
511 if (saveprefix
) FREENULL(saveprefix
);
512 if (rom
.bank
) FREENULL(rom
.bank
);
513 if (ram
.sbank
) FREENULL(ram
.sbank
);
514 if (bootrom
.bank
) FREENULL(bootrom
.bank
);
515 mbc
.type
= mbc
.romsize
= mbc
.ramsize
= mbc
.batt
= 0;
518 static char *base(char *s
)
526 static char *ldup(char *s
)
530 p
= n
= malloc(strlen(s
));
531 for (i
= 0; s
[i
]; i
++) if (isalnum(s
[i
])) *(p
++) = tolower(s
[i
]);
536 static void cleanup()
540 /* IDEA - if error, write emergency savestate..? */
543 int loader_init(char *s
)
547 sys_checkdir(savedir
, 1); /* needs to be writable */
550 if(rom_load()) return -1;
552 vid_settitle(rom
.name
);
553 if (savename
&& *savename
)
555 if (savename
[0] == '-' && savename
[1] == 0)
556 name
= ldup(rom
.name
);
557 else name
= strdup(savename
);
559 else if (romfile
&& *base(romfile
) && strcmp(romfile
, "-"))
561 name
= strdup(base(romfile
));
562 p
= strchr(name
, '.');
565 else name
= ldup(rom
.name
);
567 saveprefix
= malloc(strlen(savedir
) + strlen(name
) + 2);
568 sprintf(saveprefix
, "%s/%s", savedir
, name
);
570 sramfile
= malloc(strlen(saveprefix
) + 5);
571 strcpy(sramfile
, saveprefix
);
572 strcat(sramfile
, ".sav");
574 rtcfile
= malloc(strlen(saveprefix
) + 5);
575 strcpy(rtcfile
, saveprefix
);
576 strcat(rtcfile
, ".rtc");
585 rcvar_t loader_exports
[] =
587 RCV_STRING("bootrom_dmg", &bootroms
[0], "bootrom for DMG games"),
588 RCV_STRING("bootrom_cgb", &bootroms
[1], "bootrom for CGB games"),
589 RCV_STRING("savedir", &savedir
, "save directory"),
590 RCV_STRING("savename", &savename
, "base filename for saves"),
591 RCV_INT("saveslot", &saveslot
, "which savestate slot to use"),
592 RCV_BOOL("forcebatt", &forcebatt
, "save SRAM even on carts w/o battery"),
593 RCV_BOOL("nobatt", &nobatt
, "never save SRAM"),
594 RCV_BOOL("forcedmg", &forcedmg
, "force DMG mode for CGB carts"),
595 RCV_BOOL("gbamode", &gbamode
, "simulate cart being used on a GBA"),
596 RCV_INT("memfill", &memfill
, ""),
597 RCV_INT("memrand", &memrand
, ""),