1 #include <stdio.h>
2 #include <stdbool.h>
3 #include <stdlib.h>
4 #include <stddef.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <stdarg.h>
8 #ifndef _WIN32
9 #include <sys/select.h>
10 #include <unistd.h>
11 #endif
12 #include "random.h"
13 #include "gb.h"
14
15
16 #ifdef GB_DISABLE_REWIND
17 #define GB_rewind_free(...)
18 #define GB_rewind_push(...)
19 #endif
20
21
GB_attributed_logv(GB_gameboy_t * gb,GB_log_attributes attributes,const char * fmt,va_list args)22 void GB_attributed_logv(GB_gameboy_t *gb, GB_log_attributes attributes, const char *fmt, va_list args)
23 {
24 char *string = NULL;
25 vasprintf(&string, fmt, args);
26 if (string) {
27 if (gb->log_callback) {
28 gb->log_callback(gb, string, attributes);
29 }
30 else {
31 /* Todo: Add ANSI escape sequences for attributed text */
32 printf("%s", string);
33 }
34 }
35 free(string);
36 }
37
GB_attributed_log(GB_gameboy_t * gb,GB_log_attributes attributes,const char * fmt,...)38 void GB_attributed_log(GB_gameboy_t *gb, GB_log_attributes attributes, const char *fmt, ...)
39 {
40 va_list args;
41 va_start(args, fmt);
42 GB_attributed_logv(gb, attributes, fmt, args);
43 va_end(args);
44 }
45
GB_log(GB_gameboy_t * gb,const char * fmt,...)46 void GB_log(GB_gameboy_t *gb, const char *fmt, ...)
47 {
48 va_list args;
49 va_start(args, fmt);
50 GB_attributed_logv(gb, 0, fmt, args);
51 va_end(args);
52 }
53
54 #ifndef GB_DISABLE_DEBUGGER
default_input_callback(GB_gameboy_t * gb)55 static char *default_input_callback(GB_gameboy_t *gb)
56 {
57 char *expression = NULL;
58 size_t size = 0;
59 if (gb->debug_stopped) {
60 printf(">");
61 }
62
63 if (getline(&expression, &size, stdin) == -1) {
64 /* The user doesn't have STDIN or used ^D. We make sure the program keeps running. */
65 GB_set_async_input_callback(gb, NULL); /* Disable async input */
66 return strdup("c");
67 }
68
69 if (!expression) {
70 return strdup("");
71 }
72
73 size_t length = strlen(expression);
74 if (expression[length - 1] == '\n') {
75 expression[length - 1] = 0;
76 }
77
78 if (expression[0] == '\x03') {
79 gb->debug_stopped = true;
80 free(expression);
81 return strdup("");
82 }
83 return expression;
84 }
85
default_async_input_callback(GB_gameboy_t * gb)86 static char *default_async_input_callback(GB_gameboy_t *gb)
87 {
88 #ifndef _WIN32
89 fd_set set;
90 FD_ZERO(&set);
91 FD_SET(STDIN_FILENO, &set);
92 struct timeval time = {0,};
93 if (select(1, &set, NULL, NULL, &time) == 1) {
94 if (feof(stdin)) {
95 GB_set_async_input_callback(gb, NULL); /* Disable async input */
96 return NULL;
97 }
98 return default_input_callback(gb);
99 }
100 #endif
101 return NULL;
102 }
103 #endif
104
load_default_border(GB_gameboy_t * gb)105 static void load_default_border(GB_gameboy_t *gb)
106 {
107 if (gb->has_sgb_border) return;
108
109 #define LOAD_BORDER() do { \
110 memcpy(gb->borrowed_border.map, tilemap, sizeof(tilemap));\
111 memcpy(gb->borrowed_border.palette, palette, sizeof(palette));\
112 memcpy(gb->borrowed_border.tiles, tiles, sizeof(tiles));\
113 } while (false);
114
115 #ifdef GB_BIG_ENDIAN
116 for (unsigned i = 0; i < sizeof(gb->borrowed_border.map) / 2; i++) {
117 gb->borrowed_border.map[i] = LE16(gb->borrowed_border.map[i]);
118 }
119 for (unsigned i = 0; i < sizeof(gb->borrowed_border.palette) / 2; i++) {
120 gb->borrowed_border.palette[i] = LE16(gb->borrowed_border.palette[i]);
121 }
122 #endif
123
124 if (gb->model == GB_MODEL_AGB) {
125 #include "graphics/agb_border.inc"
126 LOAD_BORDER();
127 }
128 else if (GB_is_cgb(gb)) {
129 #include "graphics/cgb_border.inc"
130 LOAD_BORDER();
131 }
132 else {
133 #include "graphics/dmg_border.inc"
134 LOAD_BORDER();
135 }
136 }
137
GB_init(GB_gameboy_t * gb,GB_model_t model)138 void GB_init(GB_gameboy_t *gb, GB_model_t model)
139 {
140 memset(gb, 0, sizeof(*gb));
141 gb->model = model;
142 if (GB_is_cgb(gb)) {
143 gb->ram = malloc(gb->ram_size = 0x1000 * 8);
144 gb->vram = malloc(gb->vram_size = 0x2000 * 2);
145 }
146 else {
147 gb->ram = malloc(gb->ram_size = 0x2000);
148 gb->vram = malloc(gb->vram_size = 0x2000);
149 }
150
151 #ifndef GB_DISABLE_DEBUGGER
152 gb->input_callback = default_input_callback;
153 gb->async_input_callback = default_async_input_callback;
154 #endif
155 gb->cartridge_type = &GB_cart_defs[0]; // Default cartridge type
156 gb->clock_multiplier = 1.0;
157
158 if (model & GB_MODEL_NO_SFC_BIT) {
159 /* Disable time syncing. Timing should be done by the SFC emulator. */
160 gb->turbo = true;
161 }
162
163 GB_reset(gb);
164 load_default_border(gb);
165 }
166
GB_get_model(GB_gameboy_t * gb)167 GB_model_t GB_get_model(GB_gameboy_t *gb)
168 {
169 return gb->model;
170 }
171
GB_free(GB_gameboy_t * gb)172 void GB_free(GB_gameboy_t *gb)
173 {
174 gb->magic = 0;
175 if (gb->ram) {
176 free(gb->ram);
177 }
178 if (gb->vram) {
179 free(gb->vram);
180 }
181 if (gb->mbc_ram) {
182 free(gb->mbc_ram);
183 }
184 if (gb->rom) {
185 free(gb->rom);
186 }
187 if (gb->breakpoints) {
188 free(gb->breakpoints);
189 }
190 if (gb->sgb) {
191 free(gb->sgb);
192 }
193 if (gb->nontrivial_jump_state) {
194 free(gb->nontrivial_jump_state);
195 }
196 if (gb->undo_state) {
197 free(gb->undo_state);
198 }
199 #ifndef GB_DISABLE_DEBUGGER
200 GB_debugger_clear_symbols(gb);
201 #endif
202 GB_rewind_free(gb);
203 #ifndef GB_DISABLE_CHEATS
204 while (gb->cheats) {
205 GB_remove_cheat(gb, gb->cheats[0]);
206 }
207 #endif
208 memset(gb, 0, sizeof(*gb));
209 }
210
GB_load_boot_rom(GB_gameboy_t * gb,const char * path)211 int GB_load_boot_rom(GB_gameboy_t *gb, const char *path)
212 {
213 FILE *f = fopen(path, "rb");
214 if (!f) {
215 GB_log(gb, "Could not open boot ROM: %s.\n", strerror(errno));
216 return errno;
217 }
218 fread(gb->boot_rom, sizeof(gb->boot_rom), 1, f);
219 fclose(f);
220 return 0;
221 }
222
GB_load_boot_rom_from_buffer(GB_gameboy_t * gb,const unsigned char * buffer,size_t size)223 void GB_load_boot_rom_from_buffer(GB_gameboy_t *gb, const unsigned char *buffer, size_t size)
224 {
225 if (size > sizeof(gb->boot_rom)) {
226 size = sizeof(gb->boot_rom);
227 }
228 memset(gb->boot_rom, 0xFF, sizeof(gb->boot_rom));
229 memcpy(gb->boot_rom, buffer, size);
230 }
231
GB_borrow_sgb_border(GB_gameboy_t * gb)232 void GB_borrow_sgb_border(GB_gameboy_t *gb)
233 {
234 if (GB_is_sgb(gb)) return;
235 if (gb->border_mode != GB_BORDER_ALWAYS) return;
236 if (gb->tried_loading_sgb_border) return;
237 gb->tried_loading_sgb_border = true;
238 if (gb->rom && gb->rom[0x146] != 3) return; // Not an SGB game, nothing to borrow
239 if (!gb->boot_rom_load_callback) return; // Can't borrow a border without this callback
240 GB_gameboy_t sgb;
241 GB_init(&sgb, GB_MODEL_SGB);
242 sgb.cartridge_type = gb->cartridge_type;
243 sgb.rom = gb->rom;
244 sgb.rom_size = gb->rom_size;
245 sgb.turbo = true;
246 sgb.turbo_dont_skip = true;
247 // sgb.disable_rendering = true;
248
249 /* Load the boot ROM using the existing gb object */
250 typeof(gb->boot_rom) boot_rom_backup;
251 memcpy(boot_rom_backup, gb->boot_rom, sizeof(gb->boot_rom));
252 gb->boot_rom_load_callback(gb, GB_BOOT_ROM_SGB);
253 memcpy(sgb.boot_rom, gb->boot_rom, sizeof(gb->boot_rom));
254 memcpy(gb->boot_rom, boot_rom_backup, sizeof(gb->boot_rom));
255 sgb.sgb->intro_animation = -1;
256
257 for (unsigned i = 600; i--;) {
258 GB_run_frame(&sgb);
259 if (sgb.sgb->border_animation) {
260 gb->has_sgb_border = true;
261 memcpy(&gb->borrowed_border, &sgb.sgb->pending_border, sizeof(gb->borrowed_border));
262 gb->borrowed_border.palette[0] = sgb.sgb->effective_palettes[0];
263 break;
264 }
265 }
266
267 sgb.rom = NULL;
268 sgb.rom_size = 0;
269 GB_free(&sgb);
270 }
271
GB_load_rom(GB_gameboy_t * gb,const char * path)272 int GB_load_rom(GB_gameboy_t *gb, const char *path)
273 {
274 FILE *f = fopen(path, "rb");
275 if (!f) {
276 GB_log(gb, "Could not open ROM: %s.\n", strerror(errno));
277 return errno;
278 }
279 fseek(f, 0, SEEK_END);
280 gb->rom_size = (ftell(f) + 0x3FFF) & ~0x3FFF; /* Round to bank */
281 /* And then round to a power of two */
282 while (gb->rom_size & (gb->rom_size - 1)) {
283 /* I promise this works. */
284 gb->rom_size |= gb->rom_size >> 1;
285 gb->rom_size++;
286 }
287 if (gb->rom_size < 0x8000) {
288 gb->rom_size = 0x8000;
289 }
290 fseek(f, 0, SEEK_SET);
291 if (gb->rom) {
292 free(gb->rom);
293 }
294 gb->rom = malloc(gb->rom_size);
295 memset(gb->rom, 0xFF, gb->rom_size); /* Pad with 0xFFs */
296 fread(gb->rom, 1, gb->rom_size, f);
297 fclose(f);
298 GB_configure_cart(gb);
299 gb->tried_loading_sgb_border = false;
300 gb->has_sgb_border = false;
301 load_default_border(gb);
302 return 0;
303 }
304
305 #define GBS_ENTRY 0x61
306 #define GBS_ENTRY_SIZE 13
307
generate_gbs_entry(GB_gameboy_t * gb,uint8_t * data)308 static void generate_gbs_entry(GB_gameboy_t *gb, uint8_t *data)
309 {
310 memcpy(data, (uint8_t[]) {
311 0xCD, // Call $XXXX
312 LE16(gb->gbs_header.init_address),
313 LE16(gb->gbs_header.init_address) >> 8,
314 0x76, // HALT
315 0x00, // NOP
316 0xAF, // XOR a
317 0xE0, // LDH [$FFXX], a
318 GB_IO_IF,
319 0xCD, // Call $XXXX
320 LE16(gb->gbs_header.play_address),
321 LE16(gb->gbs_header.play_address) >> 8,
322 0x18, // JR pc ± $XX
323 -10 // To HALT
324 }, GBS_ENTRY_SIZE);
325 }
326
GB_gbs_switch_track(GB_gameboy_t * gb,uint8_t track)327 void GB_gbs_switch_track(GB_gameboy_t *gb, uint8_t track)
328 {
329 GB_reset(gb);
330 GB_write_memory(gb, 0xFF00 + GB_IO_LCDC, 0x80);
331 GB_write_memory(gb, 0xFF00 + GB_IO_TAC, gb->gbs_header.TAC);
332 GB_write_memory(gb, 0xFF00 + GB_IO_TMA, gb->gbs_header.TMA);
333 GB_write_memory(gb, 0xFF00 + GB_IO_NR52, 0x80);
334 GB_write_memory(gb, 0xFF00 + GB_IO_NR51, 0xFF);
335 GB_write_memory(gb, 0xFF00 + GB_IO_NR50, 0x77);
336 memset(gb->ram, 0, gb->ram_size);
337 memset(gb->hram, 0, sizeof(gb->hram));
338 memset(gb->oam, 0, sizeof(gb->oam));
339 if (gb->gbs_header.TAC || gb->gbs_header.TMA) {
340 GB_write_memory(gb, 0xFFFF, 0x04);
341 }
342 else {
343 GB_write_memory(gb, 0xFFFF, 0x01);
344 }
345 if (gb->gbs_header.TAC & 0x80) {
346 gb->cgb_double_speed = true; // Might mean double speed mode on a DMG
347 }
348 if (gb->gbs_header.load_address) {
349 gb->sp = LE16(gb->gbs_header.sp);
350 gb->pc = GBS_ENTRY;
351 }
352 else {
353 gb->pc = gb->sp = LE16(gb->gbs_header.sp - GBS_ENTRY_SIZE);
354 uint8_t entry[GBS_ENTRY_SIZE];
355 generate_gbs_entry(gb, entry);
356 for (unsigned i = 0; i < sizeof(entry); i++) {
357 GB_write_memory(gb, gb->pc + i, entry[i]);
358 }
359 }
360
361 gb->boot_rom_finished = true;
362 gb->a = track;
363 if (gb->sgb) {
364 gb->sgb->intro_animation = GB_SGB_INTRO_ANIMATION_LENGTH;
365 gb->sgb->disable_commands = true;
366 }
367 if (gb->gbs_header.TAC & 0x40) {
368 gb->interrupt_enable = true;
369 }
370 }
371
GB_load_gbs_from_buffer(GB_gameboy_t * gb,const uint8_t * buffer,size_t size,GB_gbs_info_t * info)372 int GB_load_gbs_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t size, GB_gbs_info_t *info)
373 {
374 if (size < sizeof(gb->gbs_header)) {
375 GB_log(gb, "Not a valid GBS file.\n");
376 return -1;
377 }
378
379 memcpy(&gb->gbs_header, buffer, sizeof(gb->gbs_header));
380
381 if (gb->gbs_header.magic != BE32('GBS\x01') ||
382 ((LE16(gb->gbs_header.load_address) < GBS_ENTRY + GBS_ENTRY_SIZE ||
383 LE16(gb->gbs_header.load_address) >= 0x8000) &&
384 LE16(gb->gbs_header.load_address) != 0)) {
385 GB_log(gb, "Not a valid GBS file.\n");
386 return -1;
387 }
388
389 size_t data_size = size - sizeof(gb->gbs_header);
390
391 gb->rom_size = (data_size + LE16(gb->gbs_header.load_address) + 0x3FFF) & ~0x3FFF; /* Round to bank */
392 /* And then round to a power of two */
393 while (gb->rom_size & (gb->rom_size - 1)) {
394 /* I promise this works. */
395 gb->rom_size |= gb->rom_size >> 1;
396 gb->rom_size++;
397 }
398
399 if (gb->rom_size < 0x8000) {
400 gb->rom_size = 0x8000;
401 }
402
403 if (gb->rom) {
404 free(gb->rom);
405 }
406
407 gb->rom = malloc(gb->rom_size);
408 memset(gb->rom, 0xFF, gb->rom_size); /* Pad with 0xFFs */
409 memcpy(gb->rom + LE16(gb->gbs_header.load_address), buffer + sizeof(gb->gbs_header), data_size);
410
411 gb->cartridge_type = &GB_cart_defs[0x11];
412 if (gb->mbc_ram) {
413 free(gb->mbc_ram);
414 gb->mbc_ram = NULL;
415 gb->mbc_ram_size = 0;
416 }
417
418 if (gb->cartridge_type->has_ram) {
419 gb->mbc_ram_size = 0x2000;
420 gb->mbc_ram = malloc(gb->mbc_ram_size);
421 memset(gb->mbc_ram, 0xFF, gb->mbc_ram_size);
422 }
423
424 bool has_interrupts = gb->gbs_header.TAC & 0x40;
425
426 if (gb->gbs_header.load_address) {
427 // Generate interrupt handlers
428 for (unsigned i = 0; i <= (has_interrupts? 0x50 : 0x38); i += 8) {
429 gb->rom[i] = 0xc3; // jp $XXXX
430 gb->rom[i + 1] = (LE16(gb->gbs_header.load_address) + i);
431 gb->rom[i + 2] = (LE16(gb->gbs_header.load_address) + i) >> 8;
432 }
433 for (unsigned i = has_interrupts? 0x58 : 0x40; i <= 0x60; i += 8) {
434 gb->rom[i] = 0xc9; // ret
435 }
436
437 // Generate entry
438 generate_gbs_entry(gb, gb->rom + GBS_ENTRY);
439 }
440
441
442 GB_gbs_switch_track(gb, gb->gbs_header.first_track - 1);
443 if (info) {
444 memset(info, 0, sizeof(*info));
445 info->first_track = gb->gbs_header.first_track - 1;
446 info->track_count = gb->gbs_header.track_count;
447 memcpy(info->title, gb->gbs_header.title, sizeof(gb->gbs_header.title));
448 memcpy(info->author, gb->gbs_header.author, sizeof(gb->gbs_header.author));
449 memcpy(info->copyright, gb->gbs_header.copyright, sizeof(gb->gbs_header.copyright));
450 }
451
452 gb->tried_loading_sgb_border = true; // Don't even attempt on GBS files
453 gb->has_sgb_border = false;
454 load_default_border(gb);
455 return 0;
456 }
457
GB_load_gbs(GB_gameboy_t * gb,const char * path,GB_gbs_info_t * info)458 int GB_load_gbs(GB_gameboy_t *gb, const char *path, GB_gbs_info_t *info)
459 {
460 FILE *f = fopen(path, "rb");
461 if (!f) {
462 GB_log(gb, "Could not open GBS: %s.\n", strerror(errno));
463 return errno;
464 }
465 fseek(f, 0, SEEK_END);
466 size_t file_size = MIN(ftell(f), sizeof(GB_gbs_header_t) + 0x4000 * 0x100); // Cap with the maximum MBC3 ROM size + GBS header
467 fseek(f, 0, SEEK_SET);
468 uint8_t *file_data = malloc(file_size);
469 fread(file_data, 1, file_size, f);
470 fclose(f);
471
472 int r = GB_load_gbs_from_buffer(gb, file_data, file_size, info);
473 free(file_data);
474 return r;
475 }
476
GB_load_isx(GB_gameboy_t * gb,const char * path)477 int GB_load_isx(GB_gameboy_t *gb, const char *path)
478 {
479 FILE *f = fopen(path, "rb");
480 if (!f) {
481 GB_log(gb, "Could not open ISX file: %s.\n", strerror(errno));
482 return errno;
483 }
484 char magic[4];
485 #define READ(x) if (fread(&x, sizeof(x), 1, f) != 1) goto error
486 fread(magic, 1, sizeof(magic), f);
487
488 #ifdef GB_BIG_ENDIAN
489 bool extended = *(uint32_t *)&magic == 'ISX ';
490 #else
491 bool extended = *(uint32_t *)&magic == __builtin_bswap32('ISX ');
492 #endif
493
494 fseek(f, extended? 0x20 : 0, SEEK_SET);
495
496
497 uint8_t *old_rom = gb->rom;
498 uint32_t old_size = gb->rom_size;
499 gb->rom = NULL;
500 gb->rom_size = 0;
501
502 while (true) {
503 uint8_t record_type = 0;
504 if (fread(&record_type, sizeof(record_type), 1, f) != 1) break;
505 switch (record_type) {
506 case 0x01: { // Binary
507 uint16_t bank;
508 uint16_t address;
509 uint16_t length;
510 uint8_t byte;
511 READ(byte);
512 bank = byte;
513 if (byte >= 0x80) {
514 READ(byte);
515 bank |= byte << 8;
516 }
517
518 READ(address);
519 #ifdef GB_BIG_ENDIAN
520 address = __builtin_bswap16(address);
521 #endif
522 address &= 0x3FFF;
523
524 READ(length);
525 #ifdef GB_BIG_ENDIAN
526 length = __builtin_bswap16(length);
527 #endif
528
529 size_t needed_size = bank * 0x4000 + address + length;
530 if (needed_size > 1024 * 1024 * 32) goto error;
531
532 if (gb->rom_size < needed_size) {
533 gb->rom = realloc(gb->rom, needed_size);
534 memset(gb->rom + gb->rom_size, 0, needed_size - gb->rom_size);
535 gb->rom_size = needed_size;
536 }
537
538 if (fread(gb->rom + (bank * 0x4000 + address), length, 1, f) != 1) goto error;
539
540 break;
541 }
542
543 case 0x11: { // Extended Binary
544 uint32_t address;
545 uint32_t length;
546
547 READ(address);
548 #ifdef GB_BIG_ENDIAN
549 address = __builtin_bswap32(address);
550 #endif
551
552 READ(length);
553 #ifdef GB_BIG_ENDIAN
554 length = __builtin_bswap32(length);
555 #endif
556 size_t needed_size = address + length;
557 if (needed_size > 1024 * 1024 * 32) goto error;
558
559 if (gb->rom_size < needed_size) {
560 gb->rom = realloc(gb->rom, needed_size);
561 memset(gb->rom + gb->rom_size, 0, needed_size - gb->rom_size);
562 gb->rom_size = needed_size;
563 }
564
565 if (fread(gb->rom + address, length, 1, f) != 1) goto error;
566
567 break;
568 }
569
570 case 0x04: { // Symbol
571 uint16_t count;
572 uint8_t length;
573 char name[257];
574 uint8_t flag;
575 uint16_t bank;
576 uint16_t address;
577 uint8_t byte;
578 READ(count);
579 #ifdef GB_BIG_ENDIAN
580 count = __builtin_bswap16(count);
581 #endif
582 while (count--) {
583 READ(length);
584 if (fread(name, length, 1, f) != 1) goto error;
585 name[length] = 0;
586 READ(flag); // unused
587
588 READ(byte);
589 bank = byte;
590 if (byte >= 0x80) {
591 READ(byte);
592 bank |= byte << 8;
593 }
594
595 READ(address);
596 #ifdef GB_BIG_ENDIAN
597 address = __builtin_bswap16(address);
598 #endif
599 GB_debugger_add_symbol(gb, bank, address, name);
600 }
601 break;
602 }
603
604 case 0x14: { // Extended Binary
605 uint16_t count;
606 uint8_t length;
607 char name[257];
608 uint8_t flag;
609 uint32_t address;
610 READ(count);
611 #ifdef GB_BIG_ENDIAN
612 count = __builtin_bswap16(count);
613 #endif
614 while (count--) {
615 READ(length);
616 if (fread(name, length + 1, 1, f) != 1) goto error;
617 name[length] = 0;
618 READ(flag); // unused
619
620 READ(address);
621 #ifdef GB_BIG_ENDIAN
622 address = __builtin_bswap32(address);
623 #endif
624 // TODO: How to convert 32-bit addresses to Bank:Address? Needs to tell RAM and ROM apart
625 }
626 break;
627 }
628
629 default:
630 goto done;
631 }
632 }
633 done:;
634 #undef READ
635 if (gb->rom_size == 0) goto error;
636
637 size_t needed_size = (gb->rom_size + 0x3FFF) & ~0x3FFF; /* Round to bank */
638
639 /* And then round to a power of two */
640 while (needed_size & (needed_size - 1)) {
641 /* I promise this works. */
642 needed_size |= needed_size >> 1;
643 needed_size++;
644 }
645
646 if (needed_size < 0x8000) {
647 needed_size = 0x8000;
648 }
649
650 if (gb->rom_size < needed_size) {
651 gb->rom = realloc(gb->rom, needed_size);
652 memset(gb->rom + gb->rom_size, 0, needed_size - gb->rom_size);
653 gb->rom_size = needed_size;
654 }
655
656 GB_configure_cart(gb);
657
658 // Fix a common wrong MBC error
659 if (gb->rom[0x147] == 3) { // MBC1 + RAM + Battery
660 bool needs_fix = false;
661 if (gb->rom_size >= 0x21 * 0x4000) {
662 for (unsigned i = 0x20 * 0x4000; i < 0x21 * 0x4000; i++) {
663 if (gb->rom[i]) {
664 needs_fix = true;
665 break;
666 }
667 }
668 }
669 if (!needs_fix && gb->rom_size >= 0x41 * 0x4000) {
670 for (unsigned i = 0x40 * 0x4000; i < 0x41 * 0x4000; i++) {
671 if (gb->rom[i]) {
672 needs_fix = true;
673 break;
674 }
675 }
676 }
677 if (!needs_fix && gb->rom_size >= 0x61 * 0x4000) {
678 for (unsigned i = 0x60 * 0x4000; i < 0x61 * 0x4000; i++) {
679 if (gb->rom[i]) {
680 needs_fix = true;
681 break;
682 }
683 }
684 }
685 if (needs_fix) {
686 gb->rom[0x147] = 0x10; // MBC3 + RTC + RAM + Battery
687 GB_configure_cart(gb);
688 gb->rom[0x147] = 0x3;
689 GB_log(gb, "ROM claims to use MBC1 but appears to require MBC3 or 5, assuming MBC3.\n");
690 }
691 }
692
693 if (old_rom) {
694 free(old_rom);
695 }
696
697 return 0;
698 error:
699 GB_log(gb, "Invalid or unsupported ISX file.\n");
700 if (gb->rom) {
701 free(gb->rom);
702 gb->rom = old_rom;
703 gb->rom_size = old_size;
704 }
705 fclose(f);
706 gb->tried_loading_sgb_border = false;
707 gb->has_sgb_border = false;
708 load_default_border(gb);
709 return -1;
710 }
711
GB_load_rom_from_buffer(GB_gameboy_t * gb,const uint8_t * buffer,size_t size)712 void GB_load_rom_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t size)
713 {
714 gb->rom_size = (size + 0x3fff) & ~0x3fff;
715 while (gb->rom_size & (gb->rom_size - 1)) {
716 gb->rom_size |= gb->rom_size >> 1;
717 gb->rom_size++;
718 }
719 if (gb->rom_size == 0) {
720 gb->rom_size = 0x8000;
721 }
722 if (gb->rom) {
723 free(gb->rom);
724 }
725 gb->rom = malloc(gb->rom_size);
726 memset(gb->rom, 0xff, gb->rom_size);
727 memcpy(gb->rom, buffer, size);
728 GB_configure_cart(gb);
729 gb->tried_loading_sgb_border = false;
730 gb->has_sgb_border = false;
731 load_default_border(gb);
732 }
733
734 typedef struct {
735 uint8_t seconds;
736 uint8_t padding1[3];
737 uint8_t minutes;
738 uint8_t padding2[3];
739 uint8_t hours;
740 uint8_t padding3[3];
741 uint8_t days;
742 uint8_t padding4[3];
743 uint8_t high;
744 uint8_t padding5[3];
745 } GB_vba_rtc_time_t;
746
747 typedef struct __attribute__((packed)) {
748 uint32_t magic;
749 uint16_t version;
750 uint8_t mr4;
751 uint8_t reserved;
752 uint64_t last_rtc_second;
753 uint8_t rtc_data[4];
754 } GB_tpp1_rtc_save_t;
755
756 typedef union {
757 struct __attribute__((packed)) {
758 GB_rtc_time_t rtc_real;
759 time_t last_rtc_second; /* Platform specific endianess and size */
760 } sameboy_legacy;
761 struct {
762 /* Used by VBA versions with 32-bit timestamp*/
763 GB_vba_rtc_time_t rtc_real, rtc_latched;
764 uint32_t last_rtc_second; /* Always little endian */
765 } vba32;
766 struct {
767 /* Used by BGB and VBA versions with 64-bit timestamp*/
768 GB_vba_rtc_time_t rtc_real, rtc_latched;
769 uint64_t last_rtc_second; /* Always little endian */
770 } vba64;
771 } GB_rtc_save_t;
772
GB_fill_tpp1_save_data(GB_gameboy_t * gb,GB_tpp1_rtc_save_t * data)773 static void GB_fill_tpp1_save_data(GB_gameboy_t *gb, GB_tpp1_rtc_save_t *data)
774 {
775 data->magic = BE32('TPP1');
776 data->version = BE16(0x100);
777 data->mr4 = gb->tpp1_mr4;
778 data->reserved = 0;
779 data->last_rtc_second = LE64(time(NULL));
780 unrolled for (unsigned i = 4; i--;) {
781 data->rtc_data[i] = gb->rtc_real.data[i ^ 3];
782 }
783 }
784
GB_save_battery_size(GB_gameboy_t * gb)785 int GB_save_battery_size(GB_gameboy_t *gb)
786 {
787 if (!gb->cartridge_type->has_battery) return 0; // Nothing to save.
788 if (gb->cartridge_type->mbc_type == GB_TPP1 && !(gb->rom[0x153] & 8)) return 0; // Nothing to save.
789
790 if (gb->mbc_ram_size == 0 && !gb->cartridge_type->has_rtc) return 0; /* Claims to have battery, but has no RAM or RTC */
791
792 if (gb->cartridge_type->mbc_type == GB_HUC3) {
793 return gb->mbc_ram_size + sizeof(GB_huc3_rtc_time_t);
794 }
795
796 if (gb->cartridge_type->mbc_type == GB_TPP1) {
797 return gb->mbc_ram_size + sizeof(GB_tpp1_rtc_save_t);
798 }
799
800 GB_rtc_save_t rtc_save_size;
801 return gb->mbc_ram_size + (gb->cartridge_type->has_rtc ? sizeof(rtc_save_size.vba64) : 0);
802 }
803
GB_save_battery_to_buffer(GB_gameboy_t * gb,uint8_t * buffer,size_t size)804 int GB_save_battery_to_buffer(GB_gameboy_t *gb, uint8_t *buffer, size_t size)
805 {
806 if (!gb->cartridge_type->has_battery) return 0; // Nothing to save.
807 if (gb->cartridge_type->mbc_type == GB_TPP1 && !(gb->rom[0x153] & 8)) return 0; // Nothing to save.
808 if (gb->mbc_ram_size == 0 && !gb->cartridge_type->has_rtc) return 0; /* Claims to have battery, but has no RAM or RTC */
809
810 if (size < GB_save_battery_size(gb)) return EIO;
811
812 memcpy(buffer, gb->mbc_ram, gb->mbc_ram_size);
813
814 if (gb->cartridge_type->mbc_type == GB_TPP1) {
815 buffer += gb->mbc_ram_size;
816 GB_tpp1_rtc_save_t rtc_save;
817 GB_fill_tpp1_save_data(gb, &rtc_save);
818 memcpy(buffer, &rtc_save, sizeof(rtc_save));
819 }
820 else if (gb->cartridge_type->mbc_type == GB_HUC3) {
821 buffer += gb->mbc_ram_size;
822
823 #ifdef GB_BIG_ENDIAN
824 GB_huc3_rtc_time_t rtc_save = {
825 __builtin_bswap64(gb->last_rtc_second),
826 __builtin_bswap16(gb->huc3_minutes),
827 __builtin_bswap16(gb->huc3_days),
828 __builtin_bswap16(gb->huc3_alarm_minutes),
829 __builtin_bswap16(gb->huc3_alarm_days),
830 gb->huc3_alarm_enabled,
831 };
832 #else
833 GB_huc3_rtc_time_t rtc_save = {
834 gb->last_rtc_second,
835 gb->huc3_minutes,
836 gb->huc3_days,
837 gb->huc3_alarm_minutes,
838 gb->huc3_alarm_days,
839 gb->huc3_alarm_enabled,
840 };
841 #endif
842 memcpy(buffer, &rtc_save, sizeof(rtc_save));
843 }
844 else if (gb->cartridge_type->has_rtc) {
845 GB_rtc_save_t rtc_save = {{{{0,}},},};
846 rtc_save.vba64.rtc_real.seconds = gb->rtc_real.seconds;
847 rtc_save.vba64.rtc_real.minutes = gb->rtc_real.minutes;
848 rtc_save.vba64.rtc_real.hours = gb->rtc_real.hours;
849 rtc_save.vba64.rtc_real.days = gb->rtc_real.days;
850 rtc_save.vba64.rtc_real.high = gb->rtc_real.high;
851 rtc_save.vba64.rtc_latched.seconds = gb->rtc_latched.seconds;
852 rtc_save.vba64.rtc_latched.minutes = gb->rtc_latched.minutes;
853 rtc_save.vba64.rtc_latched.hours = gb->rtc_latched.hours;
854 rtc_save.vba64.rtc_latched.days = gb->rtc_latched.days;
855 rtc_save.vba64.rtc_latched.high = gb->rtc_latched.high;
856 #ifdef GB_BIG_ENDIAN
857 rtc_save.vba64.last_rtc_second = __builtin_bswap64(time(NULL));
858 #else
859 rtc_save.vba64.last_rtc_second = time(NULL);
860 #endif
861 memcpy(buffer + gb->mbc_ram_size, &rtc_save.vba64, sizeof(rtc_save.vba64));
862 }
863
864 errno = 0;
865 return errno;
866 }
867
GB_save_battery(GB_gameboy_t * gb,const char * path)868 int GB_save_battery(GB_gameboy_t *gb, const char *path)
869 {
870 if (!gb->cartridge_type->has_battery) return 0; // Nothing to save.
871 if (gb->cartridge_type->mbc_type == GB_TPP1 && !(gb->rom[0x153] & 8)) return 0; // Nothing to save.
872 if (gb->mbc_ram_size == 0 && !gb->cartridge_type->has_rtc) return 0; /* Claims to have battery, but has no RAM or RTC */
873 FILE *f = fopen(path, "wb");
874 if (!f) {
875 GB_log(gb, "Could not open battery save: %s.\n", strerror(errno));
876 return errno;
877 }
878
879 if (fwrite(gb->mbc_ram, 1, gb->mbc_ram_size, f) != gb->mbc_ram_size) {
880 fclose(f);
881 return EIO;
882 }
883 if (gb->cartridge_type->mbc_type == GB_TPP1) {
884 GB_tpp1_rtc_save_t rtc_save;
885 GB_fill_tpp1_save_data(gb, &rtc_save);
886
887 if (fwrite(&rtc_save, sizeof(rtc_save), 1, f) != 1) {
888 fclose(f);
889 return EIO;
890 }
891 }
892 else if (gb->cartridge_type->mbc_type == GB_HUC3) {
893 #ifdef GB_BIG_ENDIAN
894 GB_huc3_rtc_time_t rtc_save = {
895 __builtin_bswap64(gb->last_rtc_second),
896 __builtin_bswap16(gb->huc3_minutes),
897 __builtin_bswap16(gb->huc3_days),
898 __builtin_bswap16(gb->huc3_alarm_minutes),
899 __builtin_bswap16(gb->huc3_alarm_days),
900 gb->huc3_alarm_enabled,
901 };
902 #else
903 GB_huc3_rtc_time_t rtc_save = {
904 gb->last_rtc_second,
905 gb->huc3_minutes,
906 gb->huc3_days,
907 gb->huc3_alarm_minutes,
908 gb->huc3_alarm_days,
909 gb->huc3_alarm_enabled,
910 };
911 #endif
912
913 if (fwrite(&rtc_save, sizeof(rtc_save), 1, f) != 1) {
914 fclose(f);
915 return EIO;
916 }
917 }
918 else if (gb->cartridge_type->has_rtc) {
919 GB_rtc_save_t rtc_save = {{{{0,}},},};
920 rtc_save.vba64.rtc_real.seconds = gb->rtc_real.seconds;
921 rtc_save.vba64.rtc_real.minutes = gb->rtc_real.minutes;
922 rtc_save.vba64.rtc_real.hours = gb->rtc_real.hours;
923 rtc_save.vba64.rtc_real.days = gb->rtc_real.days;
924 rtc_save.vba64.rtc_real.high = gb->rtc_real.high;
925 rtc_save.vba64.rtc_latched.seconds = gb->rtc_latched.seconds;
926 rtc_save.vba64.rtc_latched.minutes = gb->rtc_latched.minutes;
927 rtc_save.vba64.rtc_latched.hours = gb->rtc_latched.hours;
928 rtc_save.vba64.rtc_latched.days = gb->rtc_latched.days;
929 rtc_save.vba64.rtc_latched.high = gb->rtc_latched.high;
930 #ifdef GB_BIG_ENDIAN
931 rtc_save.vba64.last_rtc_second = __builtin_bswap64(time(NULL));
932 #else
933 rtc_save.vba64.last_rtc_second = time(NULL);
934 #endif
935 if (fwrite(&rtc_save.vba64, 1, sizeof(rtc_save.vba64), f) != sizeof(rtc_save.vba64)) {
936 fclose(f);
937 return EIO;
938 }
939
940 }
941
942 errno = 0;
943 fclose(f);
944 return errno;
945 }
946
GB_load_tpp1_save_data(GB_gameboy_t * gb,const GB_tpp1_rtc_save_t * data)947 static void GB_load_tpp1_save_data(GB_gameboy_t *gb, const GB_tpp1_rtc_save_t *data)
948 {
949 gb->last_rtc_second = LE64(data->last_rtc_second);
950 unrolled for (unsigned i = 4; i--;) {
951 gb->rtc_real.data[i ^ 3] = data->rtc_data[i];
952 }
953 }
954
GB_load_battery_from_buffer(GB_gameboy_t * gb,const uint8_t * buffer,size_t size)955 void GB_load_battery_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t size)
956 {
957 memcpy(gb->mbc_ram, buffer, MIN(gb->mbc_ram_size, size));
958 if (size <= gb->mbc_ram_size) {
959 goto reset_rtc;
960 }
961
962 if (gb->cartridge_type->mbc_type == GB_TPP1) {
963 GB_tpp1_rtc_save_t rtc_save;
964 if (size - gb->mbc_ram_size < sizeof(rtc_save)) {
965 goto reset_rtc;
966 }
967 memcpy(&rtc_save, buffer + gb->mbc_ram_size, sizeof(rtc_save));
968
969 GB_load_tpp1_save_data(gb, &rtc_save);
970
971 if (gb->last_rtc_second > time(NULL)) {
972 /* We must reset RTC here, or it will not advance. */
973 goto reset_rtc;
974 }
975 return;
976 }
977
978 if (gb->cartridge_type->mbc_type == GB_HUC3) {
979 GB_huc3_rtc_time_t rtc_save;
980 if (size - gb->mbc_ram_size < sizeof(rtc_save)) {
981 goto reset_rtc;
982 }
983 memcpy(&rtc_save, buffer + gb->mbc_ram_size, sizeof(rtc_save));
984 #ifdef GB_BIG_ENDIAN
985 gb->last_rtc_second = __builtin_bswap64(rtc_save.last_rtc_second);
986 gb->huc3_minutes = __builtin_bswap16(rtc_save.minutes);
987 gb->huc3_days = __builtin_bswap16(rtc_save.days);
988 gb->huc3_alarm_minutes = __builtin_bswap16(rtc_save.alarm_minutes);
989 gb->huc3_alarm_days = __builtin_bswap16(rtc_save.alarm_days);
990 gb->huc3_alarm_enabled = rtc_save.alarm_enabled;
991 #else
992 gb->last_rtc_second = rtc_save.last_rtc_second;
993 gb->huc3_minutes = rtc_save.minutes;
994 gb->huc3_days = rtc_save.days;
995 gb->huc3_alarm_minutes = rtc_save.alarm_minutes;
996 gb->huc3_alarm_days = rtc_save.alarm_days;
997 gb->huc3_alarm_enabled = rtc_save.alarm_enabled;
998 #endif
999 if (gb->last_rtc_second > time(NULL)) {
1000 /* We must reset RTC here, or it will not advance. */
1001 goto reset_rtc;
1002 }
1003 return;
1004 }
1005
1006 GB_rtc_save_t rtc_save;
1007 memcpy(&rtc_save, buffer + gb->mbc_ram_size, MIN(sizeof(rtc_save), size));
1008 switch (size - gb->mbc_ram_size) {
1009 case sizeof(rtc_save.sameboy_legacy):
1010 memcpy(&gb->rtc_real, &rtc_save.sameboy_legacy.rtc_real, sizeof(gb->rtc_real));
1011 memcpy(&gb->rtc_latched, &rtc_save.sameboy_legacy.rtc_real, sizeof(gb->rtc_real));
1012 gb->last_rtc_second = rtc_save.sameboy_legacy.last_rtc_second;
1013 break;
1014
1015 case sizeof(rtc_save.vba32):
1016 gb->rtc_real.seconds = rtc_save.vba32.rtc_real.seconds;
1017 gb->rtc_real.minutes = rtc_save.vba32.rtc_real.minutes;
1018 gb->rtc_real.hours = rtc_save.vba32.rtc_real.hours;
1019 gb->rtc_real.days = rtc_save.vba32.rtc_real.days;
1020 gb->rtc_real.high = rtc_save.vba32.rtc_real.high;
1021 gb->rtc_latched.seconds = rtc_save.vba32.rtc_latched.seconds;
1022 gb->rtc_latched.minutes = rtc_save.vba32.rtc_latched.minutes;
1023 gb->rtc_latched.hours = rtc_save.vba32.rtc_latched.hours;
1024 gb->rtc_latched.days = rtc_save.vba32.rtc_latched.days;
1025 gb->rtc_latched.high = rtc_save.vba32.rtc_latched.high;
1026 #ifdef GB_BIG_ENDIAN
1027 gb->last_rtc_second = __builtin_bswap32(rtc_save.vba32.last_rtc_second);
1028 #else
1029 gb->last_rtc_second = rtc_save.vba32.last_rtc_second;
1030 #endif
1031 break;
1032
1033 case sizeof(rtc_save.vba64):
1034 gb->rtc_real.seconds = rtc_save.vba64.rtc_real.seconds;
1035 gb->rtc_real.minutes = rtc_save.vba64.rtc_real.minutes;
1036 gb->rtc_real.hours = rtc_save.vba64.rtc_real.hours;
1037 gb->rtc_real.days = rtc_save.vba64.rtc_real.days;
1038 gb->rtc_real.high = rtc_save.vba64.rtc_real.high;
1039 gb->rtc_latched.seconds = rtc_save.vba64.rtc_latched.seconds;
1040 gb->rtc_latched.minutes = rtc_save.vba64.rtc_latched.minutes;
1041 gb->rtc_latched.hours = rtc_save.vba64.rtc_latched.hours;
1042 gb->rtc_latched.days = rtc_save.vba64.rtc_latched.days;
1043 gb->rtc_latched.high = rtc_save.vba64.rtc_latched.high;
1044 #ifdef GB_BIG_ENDIAN
1045 gb->last_rtc_second = __builtin_bswap64(rtc_save.vba64.last_rtc_second);
1046 #else
1047 gb->last_rtc_second = rtc_save.vba64.last_rtc_second;
1048 #endif
1049 break;
1050
1051 default:
1052 goto reset_rtc;
1053 }
1054 if (gb->last_rtc_second > time(NULL)) {
1055 /* We must reset RTC here, or it will not advance. */
1056 goto reset_rtc;
1057 }
1058
1059 if (gb->last_rtc_second < 852076800) { /* 1/1/97. There weren't any RTC games that time,
1060 so if the value we read is lower it means it wasn't
1061 really RTC data. */
1062 goto reset_rtc;
1063 }
1064 goto exit;
1065 reset_rtc:
1066 gb->last_rtc_second = time(NULL);
1067 gb->rtc_real.high |= 0x80; /* This gives the game a hint that the clock should be reset. */
1068 gb->huc3_days = 0xFFFF;
1069 gb->huc3_minutes = 0xFFF;
1070 gb->huc3_alarm_enabled = false;
1071 exit:
1072 return;
1073 }
1074
1075 /* Loading will silently stop if the format is incomplete */
GB_load_battery(GB_gameboy_t * gb,const char * path)1076 void GB_load_battery(GB_gameboy_t *gb, const char *path)
1077 {
1078 FILE *f = fopen(path, "rb");
1079 if (!f) {
1080 return;
1081 }
1082
1083 if (fread(gb->mbc_ram, 1, gb->mbc_ram_size, f) != gb->mbc_ram_size) {
1084 goto reset_rtc;
1085 }
1086
1087 if (gb->cartridge_type->mbc_type == GB_TPP1) {
1088 GB_tpp1_rtc_save_t rtc_save;
1089 if (fread(&rtc_save, sizeof(rtc_save), 1, f) != 1) {
1090 goto reset_rtc;
1091 }
1092
1093 GB_load_tpp1_save_data(gb, &rtc_save);
1094
1095 if (gb->last_rtc_second > time(NULL)) {
1096 /* We must reset RTC here, or it will not advance. */
1097 goto reset_rtc;
1098 }
1099 return;
1100 }
1101
1102 if (gb->cartridge_type->mbc_type == GB_HUC3) {
1103 GB_huc3_rtc_time_t rtc_save;
1104 if (fread(&rtc_save, sizeof(rtc_save), 1, f) != 1) {
1105 goto reset_rtc;
1106 }
1107 #ifdef GB_BIG_ENDIAN
1108 gb->last_rtc_second = __builtin_bswap64(rtc_save.last_rtc_second);
1109 gb->huc3_minutes = __builtin_bswap16(rtc_save.minutes);
1110 gb->huc3_days = __builtin_bswap16(rtc_save.days);
1111 gb->huc3_alarm_minutes = __builtin_bswap16(rtc_save.alarm_minutes);
1112 gb->huc3_alarm_days = __builtin_bswap16(rtc_save.alarm_days);
1113 gb->huc3_alarm_enabled = rtc_save.alarm_enabled;
1114 #else
1115 gb->last_rtc_second = rtc_save.last_rtc_second;
1116 gb->huc3_minutes = rtc_save.minutes;
1117 gb->huc3_days = rtc_save.days;
1118 gb->huc3_alarm_minutes = rtc_save.alarm_minutes;
1119 gb->huc3_alarm_days = rtc_save.alarm_days;
1120 gb->huc3_alarm_enabled = rtc_save.alarm_enabled;
1121 #endif
1122 if (gb->last_rtc_second > time(NULL)) {
1123 /* We must reset RTC here, or it will not advance. */
1124 goto reset_rtc;
1125 }
1126 return;
1127 }
1128
1129 GB_rtc_save_t rtc_save;
1130 switch (fread(&rtc_save, 1, sizeof(rtc_save), f)) {
1131 case sizeof(rtc_save.sameboy_legacy):
1132 memcpy(&gb->rtc_real, &rtc_save.sameboy_legacy.rtc_real, sizeof(gb->rtc_real));
1133 memcpy(&gb->rtc_latched, &rtc_save.sameboy_legacy.rtc_real, sizeof(gb->rtc_real));
1134 gb->last_rtc_second = rtc_save.sameboy_legacy.last_rtc_second;
1135 break;
1136
1137 case sizeof(rtc_save.vba32):
1138 gb->rtc_real.seconds = rtc_save.vba32.rtc_real.seconds;
1139 gb->rtc_real.minutes = rtc_save.vba32.rtc_real.minutes;
1140 gb->rtc_real.hours = rtc_save.vba32.rtc_real.hours;
1141 gb->rtc_real.days = rtc_save.vba32.rtc_real.days;
1142 gb->rtc_real.high = rtc_save.vba32.rtc_real.high;
1143 gb->rtc_latched.seconds = rtc_save.vba32.rtc_latched.seconds;
1144 gb->rtc_latched.minutes = rtc_save.vba32.rtc_latched.minutes;
1145 gb->rtc_latched.hours = rtc_save.vba32.rtc_latched.hours;
1146 gb->rtc_latched.days = rtc_save.vba32.rtc_latched.days;
1147 gb->rtc_latched.high = rtc_save.vba32.rtc_latched.high;
1148 #ifdef GB_BIG_ENDIAN
1149 gb->last_rtc_second = __builtin_bswap32(rtc_save.vba32.last_rtc_second);
1150 #else
1151 gb->last_rtc_second = rtc_save.vba32.last_rtc_second;
1152 #endif
1153 break;
1154
1155 case sizeof(rtc_save.vba64):
1156 gb->rtc_real.seconds = rtc_save.vba64.rtc_real.seconds;
1157 gb->rtc_real.minutes = rtc_save.vba64.rtc_real.minutes;
1158 gb->rtc_real.hours = rtc_save.vba64.rtc_real.hours;
1159 gb->rtc_real.days = rtc_save.vba64.rtc_real.days;
1160 gb->rtc_real.high = rtc_save.vba64.rtc_real.high;
1161 gb->rtc_latched.seconds = rtc_save.vba64.rtc_latched.seconds;
1162 gb->rtc_latched.minutes = rtc_save.vba64.rtc_latched.minutes;
1163 gb->rtc_latched.hours = rtc_save.vba64.rtc_latched.hours;
1164 gb->rtc_latched.days = rtc_save.vba64.rtc_latched.days;
1165 gb->rtc_latched.high = rtc_save.vba64.rtc_latched.high;
1166 #ifdef GB_BIG_ENDIAN
1167 gb->last_rtc_second = __builtin_bswap64(rtc_save.vba64.last_rtc_second);
1168 #else
1169 gb->last_rtc_second = rtc_save.vba64.last_rtc_second;
1170 #endif
1171 break;
1172
1173 default:
1174 goto reset_rtc;
1175 }
1176 if (gb->last_rtc_second > time(NULL)) {
1177 /* We must reset RTC here, or it will not advance. */
1178 goto reset_rtc;
1179 }
1180
1181 if (gb->last_rtc_second < 852076800) { /* 1/1/97. There weren't any RTC games that time,
1182 so if the value we read is lower it means it wasn't
1183 really RTC data. */
1184 goto reset_rtc;
1185 }
1186 goto exit;
1187 reset_rtc:
1188 gb->last_rtc_second = time(NULL);
1189 gb->rtc_real.high |= 0x80; /* This gives the game a hint that the clock should be reset. */
1190 gb->huc3_days = 0xFFFF;
1191 gb->huc3_minutes = 0xFFF;
1192 gb->huc3_alarm_enabled = false;
1193 exit:
1194 fclose(f);
1195 return;
1196 }
1197
GB_run(GB_gameboy_t * gb)1198 uint8_t GB_run(GB_gameboy_t *gb)
1199 {
1200 gb->vblank_just_occured = false;
1201
1202 if (gb->sgb && gb->sgb->intro_animation < 96) {
1203 /* On the SGB, the GB is halted after finishing the boot ROM.
1204 Then, after the boot animation is almost done, it's reset.
1205 Since the SGB HLE does not perform any header validity checks,
1206 we just halt the CPU (with hacky code) until the correct time.
1207 This ensures the Nintendo logo doesn't flash on screen, and
1208 the game does "run in background" while the animation is playing. */
1209 GB_display_run(gb, 228);
1210 gb->cycles_since_last_sync += 228;
1211 return 228;
1212 }
1213
1214 GB_debugger_run(gb);
1215 gb->cycles_since_run = 0;
1216 GB_cpu_run(gb);
1217 if (gb->vblank_just_occured) {
1218 GB_debugger_handle_async_commands(gb);
1219 GB_rewind_push(gb);
1220 }
1221 return gb->cycles_since_run;
1222 }
1223
GB_run_frame(GB_gameboy_t * gb)1224 uint64_t GB_run_frame(GB_gameboy_t *gb)
1225 {
1226 /* Configure turbo temporarily, the user wants to handle FPS capping manually. */
1227 bool old_turbo = gb->turbo;
1228 bool old_dont_skip = gb->turbo_dont_skip;
1229 gb->turbo = true;
1230 gb->turbo_dont_skip = true;
1231
1232 gb->cycles_since_last_sync = 0;
1233 while (true) {
1234 GB_run(gb);
1235 if (gb->vblank_just_occured) {
1236 break;
1237 }
1238 }
1239 gb->turbo = old_turbo;
1240 gb->turbo_dont_skip = old_dont_skip;
1241 return gb->cycles_since_last_sync * 1000000000LL / 2 / GB_get_clock_rate(gb); /* / 2 because we use 8MHz units */
1242 }
1243
GB_set_pixels_output(GB_gameboy_t * gb,uint32_t * output)1244 void GB_set_pixels_output(GB_gameboy_t *gb, uint32_t *output)
1245 {
1246 gb->screen = output;
1247 }
1248
GB_set_vblank_callback(GB_gameboy_t * gb,GB_vblank_callback_t callback)1249 void GB_set_vblank_callback(GB_gameboy_t *gb, GB_vblank_callback_t callback)
1250 {
1251 gb->vblank_callback = callback;
1252 }
1253
GB_set_log_callback(GB_gameboy_t * gb,GB_log_callback_t callback)1254 void GB_set_log_callback(GB_gameboy_t *gb, GB_log_callback_t callback)
1255 {
1256 gb->log_callback = callback;
1257 }
1258
GB_set_input_callback(GB_gameboy_t * gb,GB_input_callback_t callback)1259 void GB_set_input_callback(GB_gameboy_t *gb, GB_input_callback_t callback)
1260 {
1261 #ifndef GB_DISABLE_DEBUGGER
1262 if (gb->input_callback == default_input_callback) {
1263 gb->async_input_callback = NULL;
1264 }
1265 gb->input_callback = callback;
1266 #endif
1267 }
1268
GB_set_async_input_callback(GB_gameboy_t * gb,GB_input_callback_t callback)1269 void GB_set_async_input_callback(GB_gameboy_t *gb, GB_input_callback_t callback)
1270 {
1271 #ifndef GB_DISABLE_DEBUGGER
1272 gb->async_input_callback = callback;
1273 #endif
1274 }
1275
1276 const GB_palette_t GB_PALETTE_GREY = {{{0x00, 0x00, 0x00}, {0x55, 0x55, 0x55}, {0xaa, 0xaa, 0xaa}, {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}}};
1277 const GB_palette_t GB_PALETTE_DMG = {{{0x08, 0x18, 0x10}, {0x39, 0x61, 0x39}, {0x84, 0xa5, 0x63}, {0xc6, 0xde, 0x8c}, {0xd2, 0xe6, 0xa6}}};
1278 const GB_palette_t GB_PALETTE_MGB = {{{0x07, 0x10, 0x0e}, {0x3a, 0x4c, 0x3a}, {0x81, 0x8d, 0x66}, {0xc2, 0xce, 0x93}, {0xcf, 0xda, 0xac}}};
1279 const GB_palette_t GB_PALETTE_GBL = {{{0x0a, 0x1c, 0x15}, {0x35, 0x78, 0x62}, {0x56, 0xb4, 0x95}, {0x7f, 0xe2, 0xc3}, {0x91, 0xea, 0xd0}}};
1280
update_dmg_palette(GB_gameboy_t * gb)1281 static void update_dmg_palette(GB_gameboy_t *gb)
1282 {
1283 const GB_palette_t *palette = gb->dmg_palette ?: &GB_PALETTE_GREY;
1284 if (gb->rgb_encode_callback && !GB_is_cgb(gb)) {
1285 gb->sprite_palettes_rgb[4] = gb->sprite_palettes_rgb[0] = gb->background_palettes_rgb[0] =
1286 gb->rgb_encode_callback(gb, palette->colors[3].r, palette->colors[3].g, palette->colors[3].b);
1287 gb->sprite_palettes_rgb[5] = gb->sprite_palettes_rgb[1] = gb->background_palettes_rgb[1] =
1288 gb->rgb_encode_callback(gb, palette->colors[2].r, palette->colors[2].g, palette->colors[2].b);
1289 gb->sprite_palettes_rgb[6] = gb->sprite_palettes_rgb[2] = gb->background_palettes_rgb[2] =
1290 gb->rgb_encode_callback(gb, palette->colors[1].r, palette->colors[1].g, palette->colors[1].b);
1291 gb->sprite_palettes_rgb[7] = gb->sprite_palettes_rgb[3] = gb->background_palettes_rgb[3] =
1292 gb->rgb_encode_callback(gb, palette->colors[0].r, palette->colors[0].g, palette->colors[0].b);
1293
1294 // LCD off color
1295 gb->background_palettes_rgb[4] =
1296 gb->rgb_encode_callback(gb, palette->colors[4].r, palette->colors[4].g, palette->colors[4].b);
1297 }
1298 }
1299
GB_set_palette(GB_gameboy_t * gb,const GB_palette_t * palette)1300 void GB_set_palette(GB_gameboy_t *gb, const GB_palette_t *palette)
1301 {
1302 gb->dmg_palette = palette;
1303 update_dmg_palette(gb);
1304 }
1305
GB_set_rgb_encode_callback(GB_gameboy_t * gb,GB_rgb_encode_callback_t callback)1306 void GB_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callback)
1307 {
1308
1309 gb->rgb_encode_callback = callback;
1310 update_dmg_palette(gb);
1311
1312 for (unsigned i = 0; i < 32; i++) {
1313 GB_palette_changed(gb, true, i * 2);
1314 GB_palette_changed(gb, false, i * 2);
1315 }
1316 }
1317
GB_set_infrared_callback(GB_gameboy_t * gb,GB_infrared_callback_t callback)1318 void GB_set_infrared_callback(GB_gameboy_t *gb, GB_infrared_callback_t callback)
1319 {
1320 gb->infrared_callback = callback;
1321 }
1322
GB_set_infrared_input(GB_gameboy_t * gb,bool state)1323 void GB_set_infrared_input(GB_gameboy_t *gb, bool state)
1324 {
1325 gb->infrared_input = state;
1326 }
1327
GB_set_rumble_callback(GB_gameboy_t * gb,GB_rumble_callback_t callback)1328 void GB_set_rumble_callback(GB_gameboy_t *gb, GB_rumble_callback_t callback)
1329 {
1330 gb->rumble_callback = callback;
1331 }
1332
GB_set_serial_transfer_bit_start_callback(GB_gameboy_t * gb,GB_serial_transfer_bit_start_callback_t callback)1333 void GB_set_serial_transfer_bit_start_callback(GB_gameboy_t *gb, GB_serial_transfer_bit_start_callback_t callback)
1334 {
1335 gb->serial_transfer_bit_start_callback = callback;
1336 }
1337
GB_set_serial_transfer_bit_end_callback(GB_gameboy_t * gb,GB_serial_transfer_bit_end_callback_t callback)1338 void GB_set_serial_transfer_bit_end_callback(GB_gameboy_t *gb, GB_serial_transfer_bit_end_callback_t callback)
1339 {
1340 gb->serial_transfer_bit_end_callback = callback;
1341 }
1342
GB_serial_get_data_bit(GB_gameboy_t * gb)1343 bool GB_serial_get_data_bit(GB_gameboy_t *gb)
1344 {
1345 if (gb->io_registers[GB_IO_SC] & 1) {
1346 /* Internal Clock */
1347 GB_log(gb, "Serial read request while using internal clock. \n");
1348 return 0xFF;
1349 }
1350 return gb->io_registers[GB_IO_SB] & 0x80;
1351 }
1352
GB_serial_set_data_bit(GB_gameboy_t * gb,bool data)1353 void GB_serial_set_data_bit(GB_gameboy_t *gb, bool data)
1354 {
1355 if (gb->io_registers[GB_IO_SC] & 1) {
1356 /* Internal Clock */
1357 GB_log(gb, "Serial write request while using internal clock. \n");
1358 return;
1359 }
1360 gb->io_registers[GB_IO_SB] <<= 1;
1361 gb->io_registers[GB_IO_SB] |= data;
1362 gb->serial_count++;
1363 if (gb->serial_count == 8) {
1364 gb->io_registers[GB_IO_IF] |= 8;
1365 gb->serial_count = 0;
1366 }
1367 }
1368
GB_disconnect_serial(GB_gameboy_t * gb)1369 void GB_disconnect_serial(GB_gameboy_t *gb)
1370 {
1371 gb->serial_transfer_bit_start_callback = NULL;
1372 gb->serial_transfer_bit_end_callback = NULL;
1373
1374 /* Reset any internally-emulated device. */
1375 memset(&gb->printer, 0, sizeof(gb->printer));
1376 memset(&gb->workboy, 0, sizeof(gb->workboy));
1377 }
1378
GB_is_inited(GB_gameboy_t * gb)1379 bool GB_is_inited(GB_gameboy_t *gb)
1380 {
1381 return gb->magic == state_magic();
1382 }
1383
GB_is_cgb(GB_gameboy_t * gb)1384 bool GB_is_cgb(GB_gameboy_t *gb)
1385 {
1386 return (gb->model & GB_MODEL_FAMILY_MASK) == GB_MODEL_CGB_FAMILY;
1387 }
1388
GB_is_sgb(GB_gameboy_t * gb)1389 bool GB_is_sgb(GB_gameboy_t *gb)
1390 {
1391 return (gb->model & ~GB_MODEL_PAL_BIT & ~GB_MODEL_NO_SFC_BIT) == GB_MODEL_SGB || (gb->model & ~GB_MODEL_NO_SFC_BIT) == GB_MODEL_SGB2;
1392 }
1393
GB_is_hle_sgb(GB_gameboy_t * gb)1394 bool GB_is_hle_sgb(GB_gameboy_t *gb)
1395 {
1396 return (gb->model & ~GB_MODEL_PAL_BIT) == GB_MODEL_SGB || gb->model == GB_MODEL_SGB2;
1397 }
1398
GB_set_turbo_mode(GB_gameboy_t * gb,bool on,bool no_frame_skip)1399 void GB_set_turbo_mode(GB_gameboy_t *gb, bool on, bool no_frame_skip)
1400 {
1401 gb->turbo = on;
1402 gb->turbo_dont_skip = no_frame_skip;
1403 }
1404
GB_set_rendering_disabled(GB_gameboy_t * gb,bool disabled)1405 void GB_set_rendering_disabled(GB_gameboy_t *gb, bool disabled)
1406 {
1407 gb->disable_rendering = disabled;
1408 }
1409
GB_get_user_data(GB_gameboy_t * gb)1410 void *GB_get_user_data(GB_gameboy_t *gb)
1411 {
1412 return gb->user_data;
1413 }
1414
GB_set_user_data(GB_gameboy_t * gb,void * data)1415 void GB_set_user_data(GB_gameboy_t *gb, void *data)
1416 {
1417 gb->user_data = data;
1418 }
1419
reset_ram(GB_gameboy_t * gb)1420 static void reset_ram(GB_gameboy_t *gb)
1421 {
1422 switch (gb->model) {
1423 case GB_MODEL_CGB_E:
1424 case GB_MODEL_AGB: /* Unverified */
1425 for (unsigned i = 0; i < gb->ram_size; i++) {
1426 gb->ram[i] = GB_random();
1427 }
1428 break;
1429
1430 case GB_MODEL_DMG_B:
1431 case GB_MODEL_SGB_NTSC: /* Unverified*/
1432 case GB_MODEL_SGB_PAL: /* Unverified */
1433 case GB_MODEL_SGB_NTSC_NO_SFC: /* Unverified */
1434 case GB_MODEL_SGB_PAL_NO_SFC: /* Unverified */
1435 for (unsigned i = 0; i < gb->ram_size; i++) {
1436 gb->ram[i] = GB_random();
1437 if (i & 0x100) {
1438 gb->ram[i] &= GB_random();
1439 }
1440 else {
1441 gb->ram[i] |= GB_random();
1442 }
1443 }
1444 break;
1445
1446 case GB_MODEL_SGB2:
1447 case GB_MODEL_SGB2_NO_SFC:
1448 for (unsigned i = 0; i < gb->ram_size; i++) {
1449 gb->ram[i] = 0x55;
1450 gb->ram[i] ^= GB_random() & GB_random() & GB_random();
1451 }
1452 break;
1453
1454 case GB_MODEL_CGB_C:
1455 for (unsigned i = 0; i < gb->ram_size; i++) {
1456 if ((i & 0x808) == 0x800 || (i & 0x808) == 0x008) {
1457 gb->ram[i] = 0;
1458 }
1459 else {
1460 gb->ram[i] = GB_random() | GB_random() | GB_random() | GB_random();
1461 }
1462 }
1463 break;
1464 }
1465
1466 /* HRAM */
1467 switch (gb->model) {
1468 case GB_MODEL_CGB_C:
1469 // case GB_MODEL_CGB_D:
1470 case GB_MODEL_CGB_E:
1471 case GB_MODEL_AGB:
1472 for (unsigned i = 0; i < sizeof(gb->hram); i++) {
1473 gb->hram[i] = GB_random();
1474 }
1475 break;
1476
1477 case GB_MODEL_DMG_B:
1478 case GB_MODEL_SGB_NTSC: /* Unverified*/
1479 case GB_MODEL_SGB_PAL: /* Unverified */
1480 case GB_MODEL_SGB_NTSC_NO_SFC: /* Unverified */
1481 case GB_MODEL_SGB_PAL_NO_SFC: /* Unverified */
1482 case GB_MODEL_SGB2:
1483 case GB_MODEL_SGB2_NO_SFC:
1484 for (unsigned i = 0; i < sizeof(gb->hram); i++) {
1485 if (i & 1) {
1486 gb->hram[i] = GB_random() | GB_random() | GB_random();
1487 }
1488 else {
1489 gb->hram[i] = GB_random() & GB_random() & GB_random();
1490 }
1491 }
1492 break;
1493 }
1494
1495 /* OAM */
1496 switch (gb->model) {
1497 case GB_MODEL_CGB_C:
1498 case GB_MODEL_CGB_E:
1499 case GB_MODEL_AGB:
1500 /* Zero'd out by boot ROM anyway*/
1501 break;
1502
1503 case GB_MODEL_DMG_B:
1504 case GB_MODEL_SGB_NTSC: /* Unverified */
1505 case GB_MODEL_SGB_PAL: /* Unverified */
1506 case GB_MODEL_SGB_NTSC_NO_SFC: /* Unverified */
1507 case GB_MODEL_SGB_PAL_NO_SFC: /* Unverified */
1508 case GB_MODEL_SGB2:
1509 case GB_MODEL_SGB2_NO_SFC:
1510 for (unsigned i = 0; i < 8; i++) {
1511 if (i & 2) {
1512 gb->oam[i] = GB_random() & GB_random() & GB_random();
1513 }
1514 else {
1515 gb->oam[i] = GB_random() | GB_random() | GB_random();
1516 }
1517 }
1518 for (unsigned i = 8; i < sizeof(gb->oam); i++) {
1519 gb->oam[i] = gb->oam[i - 8];
1520 }
1521 break;
1522 }
1523
1524 /* Wave RAM */
1525 switch (gb->model) {
1526 case GB_MODEL_CGB_C:
1527 case GB_MODEL_CGB_E:
1528 case GB_MODEL_AGB:
1529 /* Initialized by CGB-A and newer, 0s in CGB-0*/
1530 break;
1531
1532 case GB_MODEL_DMG_B:
1533 case GB_MODEL_SGB_NTSC: /* Unverified*/
1534 case GB_MODEL_SGB_PAL: /* Unverified */
1535 case GB_MODEL_SGB_NTSC_NO_SFC: /* Unverified */
1536 case GB_MODEL_SGB_PAL_NO_SFC: /* Unverified */
1537 case GB_MODEL_SGB2:
1538 case GB_MODEL_SGB2_NO_SFC: {
1539 for (unsigned i = 0; i < GB_IO_WAV_END - GB_IO_WAV_START; i++) {
1540 if (i & 1) {
1541 gb->io_registers[GB_IO_WAV_START + i] = GB_random() & GB_random() & GB_random();
1542 }
1543 else {
1544 gb->io_registers[GB_IO_WAV_START + i] = GB_random() | GB_random() | GB_random();
1545 }
1546 }
1547 break;
1548 }
1549 }
1550
1551 for (unsigned i = 0; i < sizeof(gb->extra_oam); i++) {
1552 gb->extra_oam[i] = GB_random();
1553 }
1554
1555 if (GB_is_cgb(gb)) {
1556 for (unsigned i = 0; i < 64; i++) {
1557 gb->background_palettes_data[i] = GB_random(); /* Doesn't really matter as the boot ROM overrides it anyway*/
1558 gb->sprite_palettes_data[i] = GB_random();
1559 }
1560 for (unsigned i = 0; i < 32; i++) {
1561 GB_palette_changed(gb, true, i * 2);
1562 GB_palette_changed(gb, false, i * 2);
1563 }
1564 }
1565 }
1566
request_boot_rom(GB_gameboy_t * gb)1567 static void request_boot_rom(GB_gameboy_t *gb)
1568 {
1569 if (gb->boot_rom_load_callback) {
1570 GB_boot_rom_t type = 0;
1571 switch (gb->model) {
1572 case GB_MODEL_DMG_B:
1573 type = GB_BOOT_ROM_DMG;
1574 break;
1575 case GB_MODEL_SGB_NTSC:
1576 case GB_MODEL_SGB_PAL:
1577 case GB_MODEL_SGB_NTSC_NO_SFC:
1578 case GB_MODEL_SGB_PAL_NO_SFC:
1579 type = GB_BOOT_ROM_SGB;
1580 break;
1581 case GB_MODEL_SGB2:
1582 case GB_MODEL_SGB2_NO_SFC:
1583 type = GB_BOOT_ROM_SGB2;
1584 break;
1585 case GB_MODEL_CGB_C:
1586 case GB_MODEL_CGB_E:
1587 type = GB_BOOT_ROM_CGB;
1588 break;
1589 case GB_MODEL_AGB:
1590 type = GB_BOOT_ROM_AGB;
1591 break;
1592 }
1593 gb->boot_rom_load_callback(gb, type);
1594 }
1595 }
1596
GB_reset(GB_gameboy_t * gb)1597 void GB_reset(GB_gameboy_t *gb)
1598 {
1599 uint32_t mbc_ram_size = gb->mbc_ram_size;
1600 GB_model_t model = gb->model;
1601 uint8_t rtc_section[GB_SECTION_SIZE(rtc)];
1602 memcpy(rtc_section, GB_GET_SECTION(gb, rtc), sizeof(rtc_section));
1603 memset(gb, 0, (size_t)GB_GET_SECTION((GB_gameboy_t *) 0, unsaved));
1604 memcpy(GB_GET_SECTION(gb, rtc), rtc_section, sizeof(rtc_section));
1605 gb->model = model;
1606 gb->version = GB_STRUCT_VERSION;
1607
1608 gb->mbc_rom_bank = 1;
1609 gb->last_rtc_second = time(NULL);
1610 gb->cgb_ram_bank = 1;
1611 gb->io_registers[GB_IO_JOYP] = 0xCF;
1612 gb->mbc_ram_size = mbc_ram_size;
1613 if (GB_is_cgb(gb)) {
1614 gb->ram_size = 0x1000 * 8;
1615 gb->vram_size = 0x2000 * 2;
1616 memset(gb->vram, 0, gb->vram_size);
1617 gb->cgb_mode = true;
1618 gb->object_priority = GB_OBJECT_PRIORITY_INDEX;
1619 }
1620 else {
1621 gb->ram_size = 0x2000;
1622 gb->vram_size = 0x2000;
1623 memset(gb->vram, 0, gb->vram_size);
1624 gb->object_priority = GB_OBJECT_PRIORITY_X;
1625
1626 update_dmg_palette(gb);
1627 }
1628 reset_ram(gb);
1629
1630 /* The serial interrupt always occur on the 0xF7th cycle of every 0x100 cycle since boot. */
1631 gb->serial_cycles = 0x100-0xF7;
1632 gb->io_registers[GB_IO_SC] = 0x7E;
1633
1634 /* These are not deterministic, but 00 (CGB) and FF (DMG) are the most common initial values by far */
1635 gb->io_registers[GB_IO_DMA] = gb->io_registers[GB_IO_OBP0] = gb->io_registers[GB_IO_OBP1] = GB_is_cgb(gb)? 0x00 : 0xFF;
1636
1637 gb->accessed_oam_row = -1;
1638
1639
1640 if (GB_is_hle_sgb(gb)) {
1641 if (!gb->sgb) {
1642 gb->sgb = malloc(sizeof(*gb->sgb));
1643 }
1644 memset(gb->sgb, 0, sizeof(*gb->sgb));
1645 memset(gb->sgb_intro_jingle_phases, 0, sizeof(gb->sgb_intro_jingle_phases));
1646 gb->sgb_intro_sweep_phase = 0;
1647 gb->sgb_intro_sweep_previous_sample = 0;
1648 gb->sgb->intro_animation = -10;
1649
1650 gb->sgb->player_count = 1;
1651 GB_sgb_load_default_data(gb);
1652
1653 }
1654 else {
1655 if (gb->sgb) {
1656 free(gb->sgb);
1657 gb->sgb = NULL;
1658 }
1659 }
1660
1661 /* Todo: Ugly, fixme, see comment in the timer state machine */
1662 gb->div_state = 3;
1663
1664 GB_apu_update_cycles_per_sample(gb);
1665
1666 if (gb->nontrivial_jump_state) {
1667 free(gb->nontrivial_jump_state);
1668 gb->nontrivial_jump_state = NULL;
1669 }
1670
1671 gb->magic = state_magic();
1672 request_boot_rom(gb);
1673 }
1674
GB_switch_model_and_reset(GB_gameboy_t * gb,GB_model_t model)1675 void GB_switch_model_and_reset(GB_gameboy_t *gb, GB_model_t model)
1676 {
1677 gb->model = model;
1678 if (GB_is_cgb(gb)) {
1679 gb->ram = realloc(gb->ram, gb->ram_size = 0x1000 * 8);
1680 gb->vram = realloc(gb->vram, gb->vram_size = 0x2000 * 2);
1681 }
1682 else {
1683 gb->ram = realloc(gb->ram, gb->ram_size = 0x2000);
1684 gb->vram = realloc(gb->vram, gb->vram_size = 0x2000);
1685 }
1686 if (gb->undo_state) {
1687 free(gb->undo_state);
1688 gb->undo_state = NULL;
1689 }
1690 GB_rewind_free(gb);
1691 GB_reset(gb);
1692 load_default_border(gb);
1693 }
1694
GB_get_direct_access(GB_gameboy_t * gb,GB_direct_access_t access,size_t * size,uint16_t * bank)1695 void *GB_get_direct_access(GB_gameboy_t *gb, GB_direct_access_t access, size_t *size, uint16_t *bank)
1696 {
1697 /* Set size and bank to dummy pointers if not set */
1698 size_t dummy_size;
1699 uint16_t dummy_bank;
1700 if (!size) {
1701 size = &dummy_size;
1702 }
1703
1704 if (!bank) {
1705 bank = &dummy_bank;
1706 }
1707
1708
1709 switch (access) {
1710 case GB_DIRECT_ACCESS_ROM:
1711 *size = gb->rom_size;
1712 *bank = gb->mbc_rom_bank;
1713 return gb->rom;
1714 case GB_DIRECT_ACCESS_RAM:
1715 *size = gb->ram_size;
1716 *bank = gb->cgb_ram_bank;
1717 return gb->ram;
1718 case GB_DIRECT_ACCESS_CART_RAM:
1719 *size = gb->mbc_ram_size;
1720 *bank = gb->mbc_ram_bank;
1721 return gb->mbc_ram;
1722 case GB_DIRECT_ACCESS_VRAM:
1723 *size = gb->vram_size;
1724 *bank = gb->cgb_vram_bank;
1725 return gb->vram;
1726 case GB_DIRECT_ACCESS_HRAM:
1727 *size = sizeof(gb->hram);
1728 *bank = 0;
1729 return &gb->hram;
1730 case GB_DIRECT_ACCESS_IO:
1731 *size = sizeof(gb->io_registers);
1732 *bank = 0;
1733 return &gb->io_registers;
1734 case GB_DIRECT_ACCESS_BOOTROM:
1735 *size = GB_is_cgb(gb)? sizeof(gb->boot_rom) : 0x100;
1736 *bank = 0;
1737 return &gb->boot_rom;
1738 case GB_DIRECT_ACCESS_OAM:
1739 *size = sizeof(gb->oam);
1740 *bank = 0;
1741 return &gb->oam;
1742 case GB_DIRECT_ACCESS_BGP:
1743 *size = sizeof(gb->background_palettes_data);
1744 *bank = 0;
1745 return &gb->background_palettes_data;
1746 case GB_DIRECT_ACCESS_OBP:
1747 *size = sizeof(gb->sprite_palettes_data);
1748 *bank = 0;
1749 return &gb->sprite_palettes_data;
1750 case GB_DIRECT_ACCESS_IE:
1751 *size = sizeof(gb->interrupt_enable);
1752 *bank = 0;
1753 return &gb->interrupt_enable;
1754 default:
1755 *size = 0;
1756 *bank = 0;
1757 return NULL;
1758 }
1759 }
1760
GB_set_clock_multiplier(GB_gameboy_t * gb,double multiplier)1761 void GB_set_clock_multiplier(GB_gameboy_t *gb, double multiplier)
1762 {
1763 gb->clock_multiplier = multiplier;
1764 GB_apu_update_cycles_per_sample(gb);
1765 }
1766
GB_get_clock_rate(GB_gameboy_t * gb)1767 uint32_t GB_get_clock_rate(GB_gameboy_t *gb)
1768 {
1769 return GB_get_unmultiplied_clock_rate(gb) * gb->clock_multiplier;
1770 }
1771
1772
GB_get_unmultiplied_clock_rate(GB_gameboy_t * gb)1773 uint32_t GB_get_unmultiplied_clock_rate(GB_gameboy_t *gb)
1774 {
1775 if (gb->model & GB_MODEL_PAL_BIT) {
1776 return SGB_PAL_FREQUENCY;
1777 }
1778 if ((gb->model & ~GB_MODEL_NO_SFC_BIT) == GB_MODEL_SGB) {
1779 return SGB_NTSC_FREQUENCY;
1780 }
1781 return CPU_FREQUENCY;
1782 }
GB_set_border_mode(GB_gameboy_t * gb,GB_border_mode_t border_mode)1783 void GB_set_border_mode(GB_gameboy_t *gb, GB_border_mode_t border_mode)
1784 {
1785 if (gb->border_mode > GB_BORDER_ALWAYS) return;
1786 gb->border_mode = border_mode;
1787 }
1788
GB_get_screen_width(GB_gameboy_t * gb)1789 unsigned GB_get_screen_width(GB_gameboy_t *gb)
1790 {
1791 switch (gb->border_mode) {
1792 default:
1793 case GB_BORDER_SGB:
1794 return GB_is_hle_sgb(gb)? 256 : 160;
1795 case GB_BORDER_NEVER:
1796 return 160;
1797 case GB_BORDER_ALWAYS:
1798 return 256;
1799 }
1800 }
1801
GB_get_screen_height(GB_gameboy_t * gb)1802 unsigned GB_get_screen_height(GB_gameboy_t *gb)
1803 {
1804 switch (gb->border_mode) {
1805 default:
1806 case GB_BORDER_SGB:
1807 return GB_is_hle_sgb(gb)? 224 : 144;
1808 case GB_BORDER_NEVER:
1809 return 144;
1810 case GB_BORDER_ALWAYS:
1811 return 224;
1812 }
1813 }
1814
GB_get_player_count(GB_gameboy_t * gb)1815 unsigned GB_get_player_count(GB_gameboy_t *gb)
1816 {
1817 return GB_is_hle_sgb(gb)? gb->sgb->player_count : 1;
1818 }
1819
GB_set_update_input_hint_callback(GB_gameboy_t * gb,GB_update_input_hint_callback_t callback)1820 void GB_set_update_input_hint_callback(GB_gameboy_t *gb, GB_update_input_hint_callback_t callback)
1821 {
1822 gb->update_input_hint_callback = callback;
1823 }
1824
GB_get_usual_frame_rate(GB_gameboy_t * gb)1825 double GB_get_usual_frame_rate(GB_gameboy_t *gb)
1826 {
1827 return GB_get_clock_rate(gb) / (double)LCDC_PERIOD;
1828 }
1829
GB_set_joyp_write_callback(GB_gameboy_t * gb,GB_joyp_write_callback_t callback)1830 void GB_set_joyp_write_callback(GB_gameboy_t *gb, GB_joyp_write_callback_t callback)
1831 {
1832 gb->joyp_write_callback = callback;
1833 }
1834
GB_set_icd_pixel_callback(GB_gameboy_t * gb,GB_icd_pixel_callback_t callback)1835 void GB_set_icd_pixel_callback(GB_gameboy_t *gb, GB_icd_pixel_callback_t callback)
1836 {
1837 gb->icd_pixel_callback = callback;
1838 }
1839
GB_set_icd_hreset_callback(GB_gameboy_t * gb,GB_icd_hreset_callback_t callback)1840 void GB_set_icd_hreset_callback(GB_gameboy_t *gb, GB_icd_hreset_callback_t callback)
1841 {
1842 gb->icd_hreset_callback = callback;
1843 }
1844
1845
GB_set_icd_vreset_callback(GB_gameboy_t * gb,GB_icd_vreset_callback_t callback)1846 void GB_set_icd_vreset_callback(GB_gameboy_t *gb, GB_icd_vreset_callback_t callback)
1847 {
1848 gb->icd_vreset_callback = callback;
1849 }
1850
GB_set_boot_rom_load_callback(GB_gameboy_t * gb,GB_boot_rom_load_callback_t callback)1851 void GB_set_boot_rom_load_callback(GB_gameboy_t *gb, GB_boot_rom_load_callback_t callback)
1852 {
1853 gb->boot_rom_load_callback = callback;
1854 request_boot_rom(gb);
1855 }
1856
GB_time_to_alarm(GB_gameboy_t * gb)1857 unsigned GB_time_to_alarm(GB_gameboy_t *gb)
1858 {
1859 if (gb->cartridge_type->mbc_type != GB_HUC3) return 0;
1860 if (!gb->huc3_alarm_enabled) return 0;
1861 if (!(gb->huc3_alarm_days & 0x2000)) return 0;
1862 unsigned current_time = (gb->huc3_days & 0x1FFF) * 24 * 60 * 60 + gb->huc3_minutes * 60 + (time(NULL) % 60);
1863 unsigned alarm_time = (gb->huc3_alarm_days & 0x1FFF) * 24 * 60 * 60 + gb->huc3_alarm_minutes * 60;
1864 if (current_time > alarm_time) return 0;
1865 return alarm_time - current_time;
1866 }
1867
GB_set_rtc_mode(GB_gameboy_t * gb,GB_rtc_mode_t mode)1868 void GB_set_rtc_mode(GB_gameboy_t *gb, GB_rtc_mode_t mode)
1869 {
1870 if (gb->rtc_mode != mode) {
1871 gb->rtc_mode = mode;
1872 gb->rtc_cycles = 0;
1873 gb->last_rtc_second = time(NULL);
1874 }
1875 }
1876
GB_get_rom_title(GB_gameboy_t * gb,char * title)1877 void GB_get_rom_title(GB_gameboy_t *gb, char *title)
1878 {
1879 memset(title, 0, 17);
1880 if (gb->rom_size >= 0x4000) {
1881 for (unsigned i = 0; i < 0x10; i++) {
1882 if (gb->rom[0x134 + i] < 0x20 || gb->rom[0x134 + i] >= 0x80) break;
1883 title[i] = gb->rom[0x134 + i];
1884 }
1885 }
1886 }
1887
GB_get_rom_crc32(GB_gameboy_t * gb)1888 uint32_t GB_get_rom_crc32(GB_gameboy_t *gb)
1889 {
1890 static const uint32_t table[] = {
1891 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
1892 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
1893 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
1894 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
1895 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
1896 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
1897 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
1898 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
1899 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
1900 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1901 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
1902 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
1903 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
1904 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
1905 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
1906 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
1907 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
1908 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
1909 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
1910 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1911 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
1912 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
1913 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
1914 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
1915 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
1916 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
1917 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
1918 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
1919 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
1920 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1921 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
1922 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
1923 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
1924 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
1925 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
1926 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
1927 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
1928 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
1929 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
1930 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1931 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
1932 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
1933 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
1934 };
1935
1936 const uint8_t *byte = gb->rom;
1937 uint32_t size = gb->rom_size;
1938 uint32_t ret = 0xFFFFFFFF;
1939 while (size--) {
1940 ret = table[(ret ^ *byte++) & 0xFF] ^ (ret >> 8);
1941 }
1942 return ~ret;
1943 }
1944