2 #define _POSIX_C_SOURCE 200809L
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,
76 /* 0, 0, 72, 80, 96 -- actual values but bad to use these! */
79 static int ramsize_table
[256] =
82 4 /* FIXME - what value should this be?! */
86 static char *bootroms
[2];
88 static char *sramfile
;
90 static char *saveprefix
;
92 static char *savename
;
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
)
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
)
118 byte
*d
= 0, buf
[512];
122 c
= fread(buf
, 1, sizeof buf
, f
);
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
)
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
) {
151 inf_pos
= inf_len
= 0;
152 if (unzip(data
, &pos
, inflate_callback
) < 0)
158 static void write_dec(byte
*data
, int len
) {
160 for(i
=0; i
< len
; i
++)
161 inflate_callback(data
[i
]);
164 static int unxz(byte
*data
, int len
) {
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);
182 b
.out_size
= sizeof(out
);
185 ret
= xz_dec_run(s
, &b
);
186 if(b
.out_pos
== sizeof(out
)) {
187 write_dec(out
, sizeof(out
));
191 if(ret
== XZ_OK
) continue;
193 write_dec(out
, b
.out_pos
);
195 if(ret
== XZ_STREAM_END
) {
207 static byte
*do_unxz(byte
*data
, int *len
) {
211 inf_pos
= inf_len
= 0;
212 if (unxz(data
, *len
) < 0)
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
);
227 static FILE* rom_loadfile(char *fn
, byte
** data
, int *len
) {
229 if (strcmp(fn
, "-")) f
= fopen(fn
, "rb");
231 if (!f
) die("cannot open rom file: %s\n", fn
);
232 *data
= loadfile(f
, len
);
233 *data
= decompress(*data
, len
);
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);
255 byte c
, *data
, *header
;
257 f
= rom_loadfile(romfile
, &data
, &len
);
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;
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
;
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);
291 hw
.cgb
= ((c
== 0x80) || (c
== 0xc0)) && !forcedmg
;
292 hw
.gba
= (hw
.cgb
&& gbamode
);
294 if (strcmp(romfile
, "-")) fclose(f
);
299 int rom_load_simple(char *fn
) {
308 if (!mbc
.batt
|| !sramfile
|| !*sramfile
) return -1;
310 /* Consider sram loaded at this point, even if file doesn't exist */
313 f
= fopen(sramfile
, "rb");
315 fread(ram
.sbank
, 8192, mbc
.ramsize
, f
);
326 /* If we crash before we ever loaded sram, DO NOT SAVE! */
327 if (!mbc
.batt
|| !sramfile
|| !ram
.loaded
|| !mbc
.ramsize
)
330 f
= fopen(sramfile
, "wb");
332 fwrite(ram
.sbank
, 8192, mbc
.ramsize
, f
);
339 void state_save(int n
)
344 if (n
< 0) n
= saveslot
;
346 name
= malloc(strlen(saveprefix
) + 5);
347 sprintf(name
, "%s.%03d", saveprefix
, n
);
349 if ((f
= fopen(name
, "wb")))
358 void state_load(int n
)
363 if (n
< 0) n
= saveslot
;
365 name
= malloc(strlen(saveprefix
) + 5);
366 sprintf(name
, "%s.%03d", saveprefix
, n
);
368 if ((f
= fopen(name
, "rb")))
383 if (!rtc
.batt
) return;
384 if (!(f
= fopen(rtcfile
, "wb"))) return;
385 rtc_save_internal(f
);
392 if (!rtc
.batt
) return;
393 if (!(f
= fopen(rtcfile
, "r"))) return;
394 rtc_load_internal(f
);
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;
410 mbc
.type
= mbc
.romsize
= mbc
.ramsize
= mbc
.batt
= 0;
413 static char *base(char *s
)
421 static char *ldup(char *s
)
425 p
= n
= malloc(strlen(s
));
426 for (i
= 0; s
[i
]; i
++) if (isalnum(s
[i
])) *(p
++) = tolower(s
[i
]);
431 static void cleanup()
435 /* IDEA - if error, write emergency savestate..? */
438 void loader_init(char *s
)
442 sys_checkdir(savedir
, 1); /* needs to be writable */
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
, '.');
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");
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
, ""),