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
;
276 rom
.bank
= realloc(data
, rlen
);
277 if (rlen
> len
) memset(rom
.bank
[0]+len
, 0xff, rlen
- len
);
279 ram
.sbank
= malloc(8192 * mbc
.ramsize
);
281 initmem(ram
.sbank
, 8192 * mbc
.ramsize
);
282 initmem(ram
.ibank
, 4096 * 8);
288 hw
.cgb
= ((c
== 0x80) || (c
== 0xc0)) && !forcedmg
;
289 hw
.gba
= (hw
.cgb
&& gbamode
);
291 if (strcmp(romfile
, "-")) fclose(f
);
296 int rom_load_simple(char *fn
) {
305 if (!mbc
.batt
|| !sramfile
|| !*sramfile
) return -1;
307 /* Consider sram loaded at this point, even if file doesn't exist */
310 f
= fopen(sramfile
, "rb");
312 fread(ram
.sbank
, 8192, mbc
.ramsize
, f
);
323 /* If we crash before we ever loaded sram, DO NOT SAVE! */
324 if (!mbc
.batt
|| !sramfile
|| !ram
.loaded
|| !mbc
.ramsize
)
327 f
= fopen(sramfile
, "wb");
329 fwrite(ram
.sbank
, 8192, mbc
.ramsize
, f
);
336 void state_save(int n
)
341 if (n
< 0) n
= saveslot
;
343 name
= malloc(strlen(saveprefix
) + 5);
344 sprintf(name
, "%s.%03d", saveprefix
, n
);
346 if ((f
= fopen(name
, "wb")))
355 void state_load(int n
)
360 if (n
< 0) n
= saveslot
;
362 name
= malloc(strlen(saveprefix
) + 5);
363 sprintf(name
, "%s.%03d", saveprefix
, n
);
365 if ((f
= fopen(name
, "rb")))
380 if (!rtc
.batt
) return;
381 if (!(f
= fopen(rtcfile
, "wb"))) return;
382 rtc_save_internal(f
);
389 if (!rtc
.batt
) return;
390 if (!(f
= fopen(rtcfile
, "r"))) return;
391 rtc_load_internal(f
);
399 if (romfile
) free(romfile
);
400 if (sramfile
) free(sramfile
);
401 if (saveprefix
) free(saveprefix
);
402 if (rom
.bank
) free(rom
.bank
);
403 if (ram
.sbank
) free(ram
.sbank
);
404 romfile
= sramfile
= saveprefix
= 0;
407 mbc
.type
= mbc
.romsize
= mbc
.ramsize
= mbc
.batt
= 0;
410 static char *base(char *s
)
418 static char *ldup(char *s
)
422 p
= n
= malloc(strlen(s
));
423 for (i
= 0; s
[i
]; i
++) if (isalnum(s
[i
])) *(p
++) = tolower(s
[i
]);
428 static void cleanup()
432 /* IDEA - if error, write emergency savestate..? */
435 void loader_init(char *s
)
439 sys_checkdir(savedir
, 1); /* needs to be writable */
444 vid_settitle(rom
.name
);
445 if (savename
&& *savename
)
447 if (savename
[0] == '-' && savename
[1] == 0)
448 name
= ldup(rom
.name
);
449 else name
= strdup(savename
);
451 else if (romfile
&& *base(romfile
) && strcmp(romfile
, "-"))
453 name
= strdup(base(romfile
));
454 p
= strchr(name
, '.');
457 else name
= ldup(rom
.name
);
459 saveprefix
= malloc(strlen(savedir
) + strlen(name
) + 2);
460 sprintf(saveprefix
, "%s/%s", savedir
, name
);
462 sramfile
= malloc(strlen(saveprefix
) + 5);
463 strcpy(sramfile
, saveprefix
);
464 strcat(sramfile
, ".sav");
466 rtcfile
= malloc(strlen(saveprefix
) + 5);
467 strcpy(rtcfile
, saveprefix
);
468 strcat(rtcfile
, ".rtc");
476 rcvar_t loader_exports
[] =
478 RCV_STRING("bootrom_dmg", &bootroms
[0], "bootrom for DMG games"),
479 RCV_STRING("bootrom_cgb", &bootroms
[1], "bootrom for CGB games"),
480 RCV_STRING("savedir", &savedir
, "save directory"),
481 RCV_STRING("savename", &savename
, "base filename for saves"),
482 RCV_INT("saveslot", &saveslot
, "which savestate slot to use"),
483 RCV_BOOL("forcebatt", &forcebatt
, "save SRAM even on carts w/o battery"),
484 RCV_BOOL("nobatt", &nobatt
, "never save SRAM"),
485 RCV_BOOL("forcedmg", &forcedmg
, "force DMG mode for CGB carts"),
486 RCV_BOOL("gbamode", &gbamode
, "simulate cart being used on a GBA"),
487 RCV_INT("memfill", &memfill
, ""),
488 RCV_INT("memrand", &memrand
, ""),