2 #define _POSIX_C_SOURCE 200809L
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,
78 /* 0, 0, 72, 80, 96 -- actual values but bad to use these! */
81 static int ramsize_table
[256] =
84 4 /* FIXME - what value should this be?! */
88 static char *bootroms
[2];
90 static char *sramfile
;
92 static char *saveprefix
;
94 static char *savename
;
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
)
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
)
120 byte
*d
= 0, buf
[4096];
124 c
= fread(buf
, 1, sizeof buf
, f
);
136 static byte
*inf_buf
;
137 static int inf_pos
, inf_len
;
138 static char* loader_error
;
140 char* loader_get_error(void)
145 void loader_set_error(char *fmt
, ...)
150 vsnprintf(buf
, sizeof buf
, fmt
, ap
);
152 loader_error
= strdup(buf
);
155 static int inflate_callback(byte b
)
157 if (inf_pos
>= inf_len
)
160 inf_buf
= realloc(inf_buf
, inf_len
);
162 loader_set_error("out of memory inflating file @ %d bytes\n", inf_pos
);
166 inf_buf
[inf_pos
++] = b
;
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
)
177 inf_pos
= inf_len
= 0;
178 if (func(data
+offset
, &pos
, inflate_callback
) < 0)
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
;
194 if (*len
< 128) return data
;
195 memcpy(&comp
, data
+8, 2);
197 if(comp
!= 0 && comp
!= 8) return data
;
198 memcpy(&fnl
, data
+26, 2);
199 memcpy(&el
, data
+28, 2);
203 if(*len
< st
) return data
;
205 inf_buf
= realloc(NULL
, *len
- st
);
206 memcpy(inf_buf
, data
+st
, *len
- st
);
208 inf_len
= *len
= *len
- st
;
212 return gunzip_or_inflate(data
, len
, st
, inflate
);
215 static int write_dec(byte
*data
, int len
) {
217 for(i
=0; i
< len
; i
++)
218 if(inflate_callback(data
[i
])) return -1;
222 static int unxz(byte
*data
, int len
) {
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);
240 b
.out_size
= sizeof(out
);
243 ret
= xz_dec_run(s
, &b
);
244 if(b
.out_pos
== sizeof(out
)) {
245 if(write_dec(out
, sizeof(out
))) goto err
;
249 if(ret
== XZ_OK
) continue;
251 if(write_dec(out
, b
.out_pos
)) goto err
;
253 if(ret
== XZ_STREAM_END
) {
265 static byte
*do_unxz(byte
*data
, int *len
) {
269 inf_pos
= inf_len
= 0;
270 if (unxz(data
, *len
) < 0)
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
);
288 static FILE* rom_loadfile(char *fn
, byte
** data
, int *len
) {
290 if (strcmp(fn
, "-")) f
= fopen(fn
, "rb");
294 loader_set_error("cannot open rom file: %s\n", fn
);
297 *data
= loadfile(f
, len
);
303 *data
= decompress(*data
, len
);
312 if (!bootroms
[hw
.cgb
] || !bootroms
[hw
.cgb
][0]) return 0;
313 f
= rom_loadfile(bootroms
[hw
.cgb
], &data
, &len
);
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);
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
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.
343 byte c
, *data
, *header
;
345 f
= rom_loadfile(romfile
, &data
, &len
);
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;
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]];
362 loader_set_error("unknown ROM size %02X\n", header
[0x0148]);
366 loader_set_error("unknown SRAM size %02X\n", header
[0x0149]);
370 rlen
= 16384 * mbc
.romsize
;
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);
386 hw
.cgb
= ((c
== 0x80) || (c
== 0xc0)) && !forcedmg
;
387 hw
.gba
= (hw
.cgb
&& gbamode
);
389 if (strcmp(romfile
, "-")) fclose(f
);
394 int rom_load_simple(char *fn
) {
403 if (!mbc
.batt
|| !sramfile
|| !*sramfile
) return -1;
405 /* Consider sram loaded at this point, even if file doesn't exist */
408 f
= fopen(sramfile
, "rb");
410 fread(ram
.sbank
, 8192, mbc
.ramsize
, f
);
421 /* If we crash before we ever loaded sram, DO NOT SAVE! */
422 if (!mbc
.batt
|| !sramfile
|| !ram
.loaded
|| !mbc
.ramsize
)
425 f
= fopen(sramfile
, "wb");
427 fwrite(ram
.sbank
, 8192, mbc
.ramsize
, f
);
434 void state_save(int n
)
439 if (n
< 0) n
= saveslot
;
441 name
= malloc(strlen(saveprefix
) + 5);
442 sprintf(name
, "%s.%03d", saveprefix
, n
);
444 if ((f
= fopen(name
, "wb")))
453 void state_load(int n
)
458 if (n
< 0) n
= saveslot
;
460 name
= malloc(strlen(saveprefix
) + 5);
461 sprintf(name
, "%s.%03d", saveprefix
, n
);
463 if ((f
= fopen(name
, "rb")))
478 if (!rtc
.batt
) return;
479 if (!(f
= fopen(rtcfile
, "wb"))) return;
480 rtc_save_internal(f
);
487 if (!rtc
.batt
) return;
488 if (!(f
= fopen(rtcfile
, "r"))) return;
489 rtc_load_internal(f
);
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;
506 mbc
.type
= mbc
.romsize
= mbc
.ramsize
= mbc
.batt
= 0;
509 static char *base(char *s
)
517 static char *ldup(char *s
)
521 p
= n
= malloc(strlen(s
));
522 for (i
= 0; s
[i
]; i
++) if (isalnum(s
[i
])) *(p
++) = tolower(s
[i
]);
527 static void cleanup()
531 /* IDEA - if error, write emergency savestate..? */
534 int loader_init(char *s
)
538 sys_checkdir(savedir
, 1); /* needs to be writable */
541 if(rom_load()) return -1;
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
, '.');
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");
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
, ""),