From a925ef130dfcae85c91a321670cdbf53ea22e8b1 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Mon, 17 Apr 2017 20:16:17 +0300 Subject: [PATCH] =?UTF-8?q?Stabilizing=20API:=20New=20joypad,=20debugger?= =?UTF-8?q?=20and=20reset=20APIs;=20internal=20APIs=20and=20direct=20struc?= =?UTF-8?q?t=20access=20are=20no=20longer=20available=20without=20defining?= =?UTF-8?q?=20GB=5FINTERNAL.=20The=20SDL=20port=20uses=20the=20new=20?= =?UTF-8?q?=E2=80=9Cpublic=E2=80=9D=20APIs,=20as=20well=20as=20most=20of?= =?UTF-8?q?=20the=20non-debug=20Cocoa=20code.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cocoa/Document.m | 93 ++++++------- Cocoa/GBMemoryByteArray.m | 1 + Cocoa/GBView.m | 8 +- Core/apu.c | 3 +- Core/apu.h | 9 +- Core/camera.c | 4 +- Core/camera.h | 6 +- Core/debugger.c | 18 ++- Core/debugger.h | 13 +- Core/display.c | 1 - Core/display.h | 4 +- Core/gb.c | 133 ++++++++++++++----- Core/gb.h | 239 +++++++++++++++++----------------- Core/gb_struct_def.h | 5 + Core/joypad.c | 10 +- Core/joypad.h | 20 ++- Core/mbc.h | 25 +++- Core/memory.c | 7 - Core/memory.h | 2 + Core/printer.h | 8 +- Core/symbol_hash.h | 11 +- Core/timing.c | 3 - Core/timing.h | 9 ++ Core/z80_cpu.c | 4 - Core/z80_cpu.h | 3 + Core/z80_disassembler.c | 3 - Makefile | 4 + QuickLook/get_image_for_rom.c | 7 +- SDL/main.c | 30 ++--- Tester/main.c | 3 + 30 files changed, 399 insertions(+), 287 deletions(-) create mode 100644 Core/gb_struct_def.h diff --git a/Cocoa/Document.m b/Cocoa/Document.m index d3f6e1e..924f212 100644 --- a/Cocoa/Document.m +++ b/Cocoa/Document.m @@ -1,16 +1,13 @@ +#define GB_INTERNAL // Todo: several debugging functions access the GB struct directly #include #include #include "GBAudioClient.h" #include "Document.h" #include "AppDelegate.h" -#include "gb.h" -#include "debugger.h" -#include "memory.h" -#include "camera.h" -#include "display.h" #include "HexFiend/HexFiend.h" #include "GBMemoryByteArray.h" #include "GBWarningPopover.h" +#include "gb.h" /* Todo: The general Objective-C coding style conflicts with SameBoy's. This file needs a cleanup. */ /* Todo: Split into category files! This is so messy!!! */ @@ -61,25 +58,25 @@ static void vblank(GB_gameboy_t *gb) { - Document *self = (__bridge Document *)(gb->user_data); + Document *self = (__bridge Document *)GB_get_user_data(gb); [self vblank]; } static void consoleLog(GB_gameboy_t *gb, const char *string, GB_log_attributes attributes) { - Document *self = (__bridge Document *)(gb->user_data); + Document *self = (__bridge Document *)GB_get_user_data(gb); [self log:string withAttributes: attributes]; } static char *consoleInput(GB_gameboy_t *gb) { - Document *self = (__bridge Document *)(gb->user_data); + Document *self = (__bridge Document *)GB_get_user_data(gb); return strdup([self getDebuggerInput]); } static char *asyncConsoleInput(GB_gameboy_t *gb) { - Document *self = (__bridge Document *)(gb->user_data); + Document *self = (__bridge Document *)GB_get_user_data(gb); const char *ret = [self getAsyncDebuggerInput]; return ret? strdup(ret) : NULL; } @@ -91,20 +88,20 @@ static uint32_t rgbEncode(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b) static void cameraRequestUpdate(GB_gameboy_t *gb) { - Document *self = (__bridge Document *)(gb->user_data); + Document *self = (__bridge Document *)GB_get_user_data(gb); [self cameraRequestUpdate]; } static uint8_t cameraGetPixel(GB_gameboy_t *gb, uint8_t x, uint8_t y) { - Document *self = (__bridge Document *)(gb->user_data); + Document *self = (__bridge Document *)GB_get_user_data(gb); return [self cameraGetPixelAtX:x andY:y]; } static void printImage(GB_gameboy_t *gb, uint32_t *image, uint8_t height, uint8_t top_margin, uint8_t bottom_margin, uint8_t exposure) { - Document *self = (__bridge Document *)(gb->user_data); + Document *self = (__bridge Document *)GB_get_user_data(gb); [self printImage:image height:height topMargin:top_margin bottomMargin:bottom_margin exposure:exposure]; } @@ -138,12 +135,11 @@ static void printImage(GB_gameboy_t *gb, uint32_t *image, uint8_t height, GB_init_cgb(&gb); [self initCommon]; GB_load_boot_rom(&gb, [[[NSBundle mainBundle] pathForResource:@"cgb_boot" ofType:@"bin"] UTF8String]); - } - (void) initCommon { - gb.user_data = (__bridge void *)(self); + GB_set_user_data(&gb, (__bridge void *)(self)); GB_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank); GB_set_log_callback(&gb, (GB_log_callback_t) consoleLog); GB_set_input_callback(&gb, (GB_input_callback_t) consoleInput); @@ -151,13 +147,7 @@ static void printImage(GB_gameboy_t *gb, uint32_t *image, uint8_t height, GB_set_rgb_encode_callback(&gb, rgbEncode); GB_set_camera_get_pixel_callback(&gb, cameraGetPixel); GB_set_camera_update_request_callback(&gb, cameraRequestUpdate); - NSString *rom_warnings = [self captureOutputForBlock:^{ - [self loadROM]; - }]; - if (rom_warnings && !rom_warning_issued) { - rom_warning_issued = true; - [GBWarningPopover popoverWithContents:rom_warnings onWindow:self.mainWindow]; - } + [self loadROM]; } - (void) vblank @@ -203,52 +193,37 @@ static void printImage(GB_gameboy_t *gb, uint32_t *image, uint8_t height, - (void) stop { if (!running) return; - gb.debug_disable = true; - if (gb.debug_stopped) { + GB_debugger_set_disabled(&gb, true); + if (GB_debugger_is_stopped(&gb)) { gb.debug_stopped = false; [self consoleInput:nil]; } stopping = true; running = false; while (stopping); - gb.debug_disable = false; + GB_debugger_set_disabled(&gb, false); } - (IBAction)reset:(id)sender { - bool was_cgb = gb.is_cgb; [self stop]; - /* Back up user's breakpoints/watchpoints */ - typeof(gb.breakpoints) breakpoints = gb.breakpoints; - typeof(gb.n_breakpoints) n_breakpoints = gb.n_breakpoints; - typeof(gb.watchpoints) watchpoints = gb.watchpoints; - typeof(gb.n_watchpoints) n_watchpoints = gb.n_watchpoints; - - /* Reset them so they're not freed*/ - gb.watchpoints = NULL; - gb.breakpoints = NULL; - gb.n_watchpoints = gb.n_breakpoints = 0; - - GB_free(&gb); - if (([sender tag] == 0 && was_cgb) || [sender tag] == 2) { - [self initCGB]; + if ([sender tag] == 0) { + GB_reset(&gb); } else { - [self initDMG]; + GB_switch_model_and_reset(&gb, [sender tag] == 2); + GB_load_boot_rom(&gb, [[[NSBundle mainBundle] pathForResource:[sender tag] == 2? @"cgb_boot" : @"dmg_boot" ofType:@"bin"] UTF8String]); } - /* Restore backpoints/watchpoints */ - gb.breakpoints = breakpoints; - gb.n_breakpoints = n_breakpoints; - gb.watchpoints = watchpoints; - gb.n_watchpoints = n_watchpoints; - if ([sender tag] != 0) { /* User explictly selected a model, save the preference */ - [[NSUserDefaults standardUserDefaults] setBool:!gb.is_cgb forKey:@"EmulateDMG"]; + [[NSUserDefaults standardUserDefaults] setBool:[sender tag] == 1 forKey:@"EmulateDMG"]; } - [self readFromFile:self.fileName ofType:@"gb"]; + + /* Reload the ROM, SAV and SYM files */ + [self loadROM]; + [self start]; if (hex_controller) { @@ -380,10 +355,16 @@ static void printImage(GB_gameboy_t *gb, uint32_t *image, uint8_t height, - (void) loadROM { - GB_load_rom(&gb, [self.fileName UTF8String]); - GB_load_battery(&gb, [[[self.fileName stringByDeletingPathExtension] stringByAppendingPathExtension:@"sav"] UTF8String]); - GB_debugger_load_symbol_file(&gb, [[[NSBundle mainBundle] pathForResource:@"registers" ofType:@"sym"] UTF8String]); - GB_debugger_load_symbol_file(&gb, [[[self.fileName stringByDeletingPathExtension] stringByAppendingPathExtension:@"sym"] UTF8String]); + NSString *rom_warnings = [self captureOutputForBlock:^{ + GB_load_rom(&gb, [self.fileName UTF8String]); + GB_load_battery(&gb, [[[self.fileName stringByDeletingPathExtension] stringByAppendingPathExtension:@"sav"] UTF8String]); + GB_debugger_load_symbol_file(&gb, [[[NSBundle mainBundle] pathForResource:@"registers" ofType:@"sym"] UTF8String]); + GB_debugger_load_symbol_file(&gb, [[[self.fileName stringByDeletingPathExtension] stringByAppendingPathExtension:@"sym"] UTF8String]); + }]; + if (rom_warnings && !rom_warning_issued) { + rom_warning_issued = true; + [GBWarningPopover popoverWithContents:rom_warnings onWindow:self.mainWindow]; + } } - (void)close @@ -398,7 +379,7 @@ static void printImage(GB_gameboy_t *gb, uint32_t *image, uint8_t height, - (IBAction) interrupt:(id)sender { [self log:"^C\n"]; - gb.debug_stopped = true; + GB_debugger_break(&gb); if (!running) { [self start]; } @@ -428,8 +409,8 @@ static void printImage(GB_gameboy_t *gb, uint32_t *image, uint8_t height, [(NSMenuItem*)anItem setState:!self.audioClient.isPlaying]; } else if ([anItem action] == @selector(togglePause:)) { - [(NSMenuItem*)anItem setState:(!running) || (gb.debug_stopped)]; - return !gb.debug_stopped; + [(NSMenuItem*)anItem setState:(!running) || (GB_debugger_is_stopped(&gb))]; + return !GB_debugger_is_stopped(&gb); } else if ([anItem action] == @selector(reset:) && anItem.tag != 0) { [(NSMenuItem*)anItem setState:(anItem.tag == 1 && !gb.is_cgb) || (anItem.tag == 2 && gb.is_cgb)]; @@ -653,7 +634,7 @@ static void printImage(GB_gameboy_t *gb, uint32_t *image, uint8_t height, - (void) performAtomicBlock: (void (^)())block { while (!GB_is_inited(&gb)); - bool was_running = running && !gb.debug_stopped; + bool was_running = running && !GB_debugger_is_stopped(&gb); if (was_running) { [self stop]; } diff --git a/Cocoa/GBMemoryByteArray.m b/Cocoa/GBMemoryByteArray.m index a81fb11..2655579 100644 --- a/Cocoa/GBMemoryByteArray.m +++ b/Cocoa/GBMemoryByteArray.m @@ -1,3 +1,4 @@ +#define GB_INTERNAL // Todo: Some memory accesses are being done using the struct directly #import "GBMemoryByteArray.h" #import "GBCompleteByteSlice.h" diff --git a/Cocoa/GBView.m b/Cocoa/GBView.m index 316d95f..fc0c04a 100644 --- a/Cocoa/GBView.m +++ b/Cocoa/GBView.m @@ -172,11 +172,11 @@ handled = true; switch (i) { case GBTurbo: - _gb->turbo = true; + GB_set_turbo_mode(_gb, true); break; default: - _gb->keys[i] = true; + GB_set_key_state(_gb, (GB_key_t)i, true); break; } } @@ -198,11 +198,11 @@ handled = true; switch (i) { case GBTurbo: - _gb->turbo = false; + GB_set_turbo_mode(_gb, false); break; default: - _gb->keys[i] = false; + GB_set_key_state(_gb, (GB_key_t)i, false); break; } } diff --git a/Core/apu.c b/Core/apu.c index 4743fcb..49b4f21 100755 --- a/Core/apu.c +++ b/Core/apu.c @@ -1,7 +1,6 @@ #include #include #include -#include "apu.h" #include "gb.h" #undef max @@ -443,4 +442,4 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) } break; } -} \ No newline at end of file +} diff --git a/Core/apu.h b/Core/apu.h index ffd10e9..261c1e1 100644 --- a/Core/apu.h +++ b/Core/apu.h @@ -2,15 +2,11 @@ #define apu_h #include #include - +#include "gb_struct_def.h" /* Divides nicely and never overflows with 4 channels */ #define MAX_CH_AMP 0x1E00 #define CH_STEP (0x1E00/0xF) -#include "save_struct.h" - -struct GB_gameboy_s; -typedef struct GB_gameboy_s GB_gameboy_t; typedef struct { @@ -59,10 +55,13 @@ typedef struct } GB_apu_t; void GB_apu_copy_buffer(GB_gameboy_t *gb, GB_sample_t *dest, unsigned int count); + +#ifdef GB_INTERNAL void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value); uint8_t GB_apu_read(GB_gameboy_t *gb, uint8_t reg); void GB_apu_get_samples_and_update_pcm_regs(GB_gameboy_t *gb, GB_sample_t *samples); void GB_apu_init(GB_gameboy_t *gb); void GB_apu_run(GB_gameboy_t *gb); +#endif #endif /* apu_h */ diff --git a/Core/camera.c b/Core/camera.c index 5a087d2..b0b9156 100644 --- a/Core/camera.c +++ b/Core/camera.c @@ -1,4 +1,4 @@ -#include "camera.h" +#include "gb.h" static int noise_seed = 0; @@ -147,4 +147,4 @@ uint8_t GB_camera_read_register(GB_gameboy_t *gb, uint16_t addr) return gb->camera_registers[GB_CAMERA_SHOOT_AND_1D_FLAGS]; } return 0; -} \ No newline at end of file +} diff --git a/Core/camera.h b/Core/camera.h index 5adda5d..21c69b6 100644 --- a/Core/camera.h +++ b/Core/camera.h @@ -1,6 +1,10 @@ #ifndef camera_h #define camera_h -#include "gb.h" +#include +#include "gb_struct_def.h" + +typedef uint8_t (*GB_camera_get_pixel_callback_t)(GB_gameboy_t *gb, uint8_t x, uint8_t y); +typedef void (*GB_camera_update_request_callback_t)(GB_gameboy_t *gb); enum { GB_CAMERA_SHOOT_AND_1D_FLAGS = 0, diff --git a/Core/debugger.c b/Core/debugger.c index 8a39556..8d2dca7 100644 --- a/Core/debugger.c +++ b/Core/debugger.c @@ -1,9 +1,6 @@ #include #include #include -#include "debugger.h" -#include "memory.h" -#include "z80_cpu.h" #include "gb.h" typedef struct { @@ -1792,3 +1789,18 @@ bool GB_debugger_evaluate(GB_gameboy_t *gb, const char *string, uint16_t *result } return error; } + +void GB_debugger_break(GB_gameboy_t *gb) +{ + gb->debug_stopped = true; +} + +bool GB_debugger_is_stopped(GB_gameboy_t *gb) +{ + return gb->debug_stopped; +} + +void GB_debugger_set_disabled(GB_gameboy_t *gb, bool disabled) +{ + gb->debug_disable = disabled; +} diff --git a/Core/debugger.h b/Core/debugger.h index 882f843..fadf8d4 100644 --- a/Core/debugger.h +++ b/Core/debugger.h @@ -1,15 +1,24 @@ #ifndef debugger_h #define debugger_h -#include "gb.h" +#include +#include +#include "gb_struct_def.h" +#include "symbol_hash.h" +#ifdef GB_INTERNAL void GB_debugger_run(GB_gameboy_t *gb); void GB_debugger_handle_async_commands(GB_gameboy_t *gb); void GB_debugger_call_hook(GB_gameboy_t *gb, uint16_t call_addr); void GB_debugger_ret_hook(GB_gameboy_t *gb); void GB_debugger_test_write_watchpoint(GB_gameboy_t *gb, uint16_t addr, uint8_t value); void GB_debugger_test_read_watchpoint(GB_gameboy_t *gb, uint16_t addr); -void GB_debugger_load_symbol_file(GB_gameboy_t *gb, const char *path); const GB_bank_symbol_t *GB_debugger_find_symbol(GB_gameboy_t *gb, uint16_t addr); +#endif + +void GB_debugger_load_symbol_file(GB_gameboy_t *gb, const char *path); const char *GB_debugger_name_for_address(GB_gameboy_t *gb, uint16_t addr); bool GB_debugger_evaluate(GB_gameboy_t *gb, const char *string, uint16_t *result, uint16_t *result_bank); /* result_bank is -1 if unused. */ +void GB_debugger_break(GB_gameboy_t *gb); +bool GB_debugger_is_stopped(GB_gameboy_t *gb); +void GB_debugger_set_disabled(GB_gameboy_t *gb, bool disabled); #endif /* debugger_h */ diff --git a/Core/display.c b/Core/display.c index 4e892ed..ddb1524 100755 --- a/Core/display.c +++ b/Core/display.c @@ -5,7 +5,6 @@ #include #include #include "gb.h" -#include "display.h" #ifdef _WIN32 #define _WIN32_WINNT 0x0500 #include diff --git a/Core/display.h b/Core/display.h index cc43f3f..418bd66 100644 --- a/Core/display.h +++ b/Core/display.h @@ -2,8 +2,10 @@ #define display_h #include "gb.h" +#ifdef GB_INTERNAL void GB_display_run(GB_gameboy_t *gb, uint8_t cycles); void GB_palette_changed(GB_gameboy_t *gb, bool background_palette, uint8_t index); +#endif typedef enum { GB_PALETTE_NONE, @@ -33,6 +35,6 @@ typedef struct { void GB_draw_tileset(GB_gameboy_t *gb, uint32_t *dest, GB_palette_type_t palette_type, uint8_t palette_index); void GB_draw_tilemap(GB_gameboy_t *gb, uint32_t *dest, GB_palette_type_t palette_type, uint8_t palette_index, GB_map_type_t map_type, GB_tileset_type_t tileset_type); - uint8_t GB_get_oam_info(GB_gameboy_t *gb, GB_oam_info_t *dest); + #endif /* display_h */ diff --git a/Core/gb.c b/Core/gb.c index 7c7c212..9261e2d 100755 --- a/Core/gb.c +++ b/Core/gb.c @@ -9,13 +9,6 @@ #include #include #include "gb.h" -#include "memory.h" -#include "timing.h" -#include "z80_cpu.h" -#include "joypad.h" -#include "display.h" -#include "debugger.h" -#include "mbc.h" void GB_attributed_logv(GB_gameboy_t *gb, GB_log_attributes attributes, const char *fmt, va_list args) { @@ -92,54 +85,28 @@ static char *default_async_input_callback(GB_gameboy_t *gb) void GB_init(GB_gameboy_t *gb) { memset(gb, 0, sizeof(*gb)); - gb->version = GB_STRUCT_VERSION; gb->ram = malloc(gb->ram_size = 0x2000); - memset(gb->ram, 0, gb->ram_size); gb->vram = malloc(gb->vram_size = 0x2000); - memset(gb->vram, 0, gb->vram_size); - gb->mbc_rom_bank = 1; - gb->last_rtc_second = time(NULL); - gb->last_vblank = clock(); - gb->cgb_ram_bank = 1; - - /* Todo: this bypasses the rgb encoder because it is not set yet. */ - gb->sprite_palletes_rgb[4] = gb->sprite_palletes_rgb[0] = gb->background_palletes_rgb[0] = 0xFFFFFFFF; - gb->sprite_palletes_rgb[5] = gb->sprite_palletes_rgb[1] = gb->background_palletes_rgb[1] = 0xAAAAAAAA; - gb->sprite_palletes_rgb[6] = gb->sprite_palletes_rgb[2] = gb->background_palletes_rgb[2] = 0x55555555; gb->input_callback = default_input_callback; gb->async_input_callback = default_async_input_callback; gb->cartridge_type = &GB_cart_defs[0]; // Default cartridge type - - gb->io_registers[GB_IO_OBP0] = gb->io_registers[GB_IO_OBP1] = 0xFF; - gb->io_registers[GB_IO_JOYP] = 0xF; - gb->io_registers[GB_IO_SC] = 0x7E; - gb->magic = (uintptr_t)'SAME'; + + GB_reset(gb); } void GB_init_cgb(GB_gameboy_t *gb) { memset(gb, 0, sizeof(*gb)); - gb->version = GB_STRUCT_VERSION; gb->ram = malloc(gb->ram_size = 0x2000 * 8); - memset(gb->ram, 0, gb->ram_size); gb->vram = malloc(gb->vram_size = 0x2000 * 2); - memset(gb->vram, 0, gb->vram_size); gb->is_cgb = true; - gb->cgb_mode = true; - gb->mbc_rom_bank = 1; - gb->last_rtc_second = time(NULL); - gb->last_vblank = clock(); - gb->cgb_ram_bank = 1; gb->input_callback = default_input_callback; gb->async_input_callback = default_async_input_callback; gb->cartridge_type = &GB_cart_defs[0]; // Default cartridge type - gb->io_registers[GB_IO_OBP0] = gb->io_registers[GB_IO_OBP1] = 0xFF; - gb->io_registers[GB_IO_JOYP] = 0xF; - gb->io_registers[GB_IO_SC] = 0x7C; - gb->magic = 'SAME'; + GB_reset(gb); } void GB_free(GB_gameboy_t *gb) @@ -200,6 +167,9 @@ int GB_load_rom(GB_gameboy_t *gb, const char *path) gb->rom_size++; } fseek(f, 0, SEEK_SET); + if (gb->rom) { + free(gb->rom); + } gb->rom = malloc(gb->rom_size); memset(gb->rom, 0xFF, gb->rom_size); /* Pad with 0xFFs */ fread(gb->rom, gb->rom_size, 1, f); @@ -476,6 +446,16 @@ void GB_set_async_input_callback(GB_gameboy_t *gb, GB_input_callback_t callback) void GB_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callback) { + if (!gb->rgb_encode_callback && !gb->is_cgb) { + gb->sprite_palletes_rgb[4] = gb->sprite_palletes_rgb[0] = gb->background_palletes_rgb[0] = + callback(gb, 0xFF, 0xFF, 0xFF); + gb->sprite_palletes_rgb[5] = gb->sprite_palletes_rgb[1] = gb->background_palletes_rgb[1] = + callback(gb, 0xAA, 0xAA, 0xAA); + gb->sprite_palletes_rgb[6] = gb->sprite_palletes_rgb[2] = gb->background_palletes_rgb[2] = + callback(gb, 0x55, 0x55, 0x55); + gb->sprite_palletes_rgb[7] = gb->sprite_palletes_rgb[3] = gb->background_palletes_rgb[3] = + callback(gb, 0, 0, 0); + } gb->rgb_encode_callback = callback; } @@ -554,3 +534,84 @@ void GB_disconnect_serial(GB_gameboy_t *gb) /* Reset any internally-emulated device. Currently, only the printer. */ memset(&gb->printer, 0, sizeof(gb->printer)); } + +bool GB_is_inited(GB_gameboy_t *gb) +{ + return gb->magic == 'SAME'; +} + +void GB_set_turbo_mode(GB_gameboy_t *gb, bool on) +{ + gb->turbo = on; +} + +void *GB_get_user_data(GB_gameboy_t *gb) +{ + return gb->user_data; +} + +void GB_set_user_data(GB_gameboy_t *gb, void *data) +{ + gb->user_data = data; +} + +void GB_reset(GB_gameboy_t *gb) +{ + bool cgb = gb->is_cgb; + memset(gb, 0, (size_t)GB_GET_SECTION((GB_gameboy_t *) 0, unsaved)); + gb->version = GB_STRUCT_VERSION; + + gb->mbc_rom_bank = 1; + gb->last_rtc_second = time(NULL); + gb->last_vblank = clock(); + gb->cgb_ram_bank = 1; + gb->io_registers[GB_IO_JOYP] = 0xF; + gb->io_registers[GB_IO_OBP0] = gb->io_registers[GB_IO_OBP1] = 0xFF; + + if (cgb) { + gb->ram_size = 0x2000 * 8; + memset(gb->ram, 0, gb->ram_size); + gb->vram_size = 0x2000 * 2; + memset(gb->vram, 0, gb->vram_size); + + gb->is_cgb = true; + gb->cgb_mode = true; + + gb->io_registers[GB_IO_SC] = 0x7C; + } + else { + gb->ram_size = 0x2000; + memset(gb->ram, 0, gb->ram_size); + gb->vram_size = 0x2000; + memset(gb->vram, 0, gb->vram_size); + + if (gb->rgb_encode_callback) { + gb->sprite_palletes_rgb[4] = gb->sprite_palletes_rgb[0] = gb->background_palletes_rgb[0] = + gb->rgb_encode_callback(gb, 0xFF, 0xFF, 0xFF); + gb->sprite_palletes_rgb[5] = gb->sprite_palletes_rgb[1] = gb->background_palletes_rgb[1] = + gb->rgb_encode_callback(gb, 0xAA, 0xAA, 0xAA); + gb->sprite_palletes_rgb[6] = gb->sprite_palletes_rgb[2] = gb->background_palletes_rgb[2] = + gb->rgb_encode_callback(gb, 0x55, 0x55, 0x55); + gb->sprite_palletes_rgb[7] = gb->sprite_palletes_rgb[3] = gb->background_palletes_rgb[3] = + gb->rgb_encode_callback(gb, 0, 0, 0); + } + + gb->io_registers[GB_IO_SC] = 0x7E; + } + gb->magic = (uintptr_t)'SAME'; +} + +void GB_switch_model_and_reset(GB_gameboy_t *gb, bool is_cgb) +{ + if (is_cgb) { + gb->ram = realloc(gb->ram, gb->ram_size = 0x2000 * 8); + gb->vram = realloc(gb->vram, gb->vram_size = 0x2000 * 2); + } + else { + gb->ram = realloc(gb->ram, gb->ram_size = 0x2000); + gb->vram = realloc(gb->vram, gb->vram_size = 0x2000); + } + gb->is_cgb = is_cgb; + GB_reset(gb); + +} diff --git a/Core/gb.h b/Core/gb.h index 84e1367..72abea3 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -4,11 +4,21 @@ #include #include #include -#include "printer.h" -#include "apu.h" -#include "save_struct.h" -#include "symbol_hash.h" +#include "gb_struct_def.h" +#include "save_struct.h" + +#include "apu.h" +#include "camera.h" +#include "debugger.h" +#include "display.h" +#include "joypad.h" +#include "mbc.h" +#include "memory.h" +#include "printer.h" +#include "timing.h" +#include "z80_cpu.h" +#include "symbol_hash.h" #define GB_STRUCT_VERSION 10 @@ -140,12 +150,6 @@ enum { GB_IO_UNKNOWN8 = 0x7F, // Unknown, write only }; -#define LCDC_PERIOD 70224 -#define CPU_FREQUENCY 0x400000 -#define DIV_CYCLES (0x100) -#define INTERNAL_DIV_CYCLES (0x40000) -#define FRAME_LENGTH 16742706 // in nanoseconds - typedef enum { GB_LOG_BOLD = 1, GB_LOG_DASHED_UNDERLINE = 2, @@ -153,40 +157,23 @@ typedef enum { GB_LOG_UNDERLINE_MASK = GB_LOG_DASHED_UNDERLINE | GB_LOG_UNDERLINE } GB_log_attributes; -struct GB_gameboy_s; -typedef struct GB_gameboy_s GB_gameboy_t; +#ifdef GB_INTERNAL +#define LCDC_PERIOD 70224 +#define CPU_FREQUENCY 0x400000 +#define DIV_CYCLES (0x100) +#define INTERNAL_DIV_CYCLES (0x40000) +#define FRAME_LENGTH 16742706 // in nanoseconds +#endif + typedef void (*GB_vblank_callback_t)(GB_gameboy_t *gb); typedef void (*GB_log_callback_t)(GB_gameboy_t *gb, const char *string, GB_log_attributes attributes); typedef char *(*GB_input_callback_t)(GB_gameboy_t *gb); typedef uint32_t (*GB_rgb_encode_callback_t)(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b); typedef void (*GB_infrared_callback_t)(GB_gameboy_t *gb, bool on, long cycles_since_last_update); -typedef uint8_t (*GB_camera_get_pixel_callback_t)(GB_gameboy_t *gb, uint8_t x, uint8_t y); -typedef void (*GB_camera_update_request_callback_t)(GB_gameboy_t *gb); typedef void (*GB_rumble_callback_t)(GB_gameboy_t *gb, bool rumble_on); typedef void (*GB_serial_transfer_start_callback_t)(GB_gameboy_t *gb, uint8_t byte_to_send); typedef uint8_t (*GB_serial_transfer_end_callback_t)(GB_gameboy_t *gb); - -typedef struct { - enum { - GB_NO_MBC, - GB_MBC1, - GB_MBC2, - GB_MBC3, - GB_MBC5, - GB_HUC1, /* Todo: HUC1 features are not emulated. Should be unified with the CGB IR sensor API. */ - GB_HUC3, - } mbc_type; - enum { - GB_STANDARD_MBC, - GB_CAMERA, - } mbc_subtype; - bool has_ram; - bool has_battery; - bool has_rtc; - bool has_rumble; -} GB_cartridge_t; - typedef struct { bool state; long delay; @@ -205,13 +192,11 @@ struct GB_watchpoint_s; /* Todo: We might want to typedef our own bool if this prevents SameBoy from working on specific platforms. */ _Static_assert(sizeof(bool) == 1, "sizeof(bool) != 1"); -enum { - GB_TIMA_RUNNING = 0, - GB_TIMA_RELOADING = 1, - GB_TIMA_RELOADED = 2 -}; - -typedef struct GB_gameboy_s { +#ifdef GB_INTERNAL +struct GB_gameboy_s { +#else +struct GB_gameboy_internal_s { +#endif GB_SECTION(header, /* The magic makes sure a state file is: - Indeed a SameBoy state file. @@ -389,95 +374,103 @@ typedef struct GB_gameboy_s { ); /* Unsaved data. This includes all pointers, as well as everything that shouldn't be on a save state */ + /* This data is reserved on reset and must come last in the struct */ + GB_SECTION(unsaved, + /* ROM */ + uint8_t *rom; + uint32_t rom_size; + const GB_cartridge_t *cartridge_type; + enum { + GB_STANDARD_MBC1_WIRING, + GB_MBC1M_WIRING, + } mbc1_wiring; - /* ROM */ - uint8_t *rom; - uint32_t rom_size; - const GB_cartridge_t *cartridge_type; - enum { - GB_STANDARD_MBC1_WIRING, - GB_MBC1M_WIRING, - } mbc1_wiring; + /* Various RAMs */ + uint8_t *ram; + uint8_t *vram; + uint8_t *mbc_ram; - /* Various RAMs */ - uint8_t *ram; - uint8_t *vram; - uint8_t *mbc_ram; + /* I/O */ + uint32_t *screen; + GB_sample_t *audio_buffer; + bool keys[GB_KEY_MAX]; - /* I/O */ - uint32_t *screen; - GB_sample_t *audio_buffer; - bool keys[8]; + /* Audio Specific */ + unsigned int buffer_size; + unsigned int sample_rate; + unsigned int audio_position; + bool audio_stream_started; // detects first copy request to minimize lag + volatile bool audio_copy_in_progress; + volatile bool apu_lock; - /* Audio Specific */ - unsigned int buffer_size; - unsigned int sample_rate; - unsigned int audio_position; - bool audio_stream_started; // detects first copy request to minimize lag - volatile bool audio_copy_in_progress; - volatile bool apu_lock; + /* Callbacks */ + void *user_data; + GB_log_callback_t log_callback; + GB_input_callback_t input_callback; + GB_input_callback_t async_input_callback; + GB_rgb_encode_callback_t rgb_encode_callback; + GB_vblank_callback_t vblank_callback; + GB_infrared_callback_t infrared_callback; + GB_camera_get_pixel_callback_t camera_get_pixel_callback; + GB_camera_update_request_callback_t camera_update_request_callback; + GB_rumble_callback_t rumble_callback; + GB_serial_transfer_start_callback_t serial_transfer_start_callback; + GB_serial_transfer_end_callback_t serial_transfer_end_callback; + /* IR */ + long cycles_since_ir_change; + long cycles_since_input_ir_change; + GB_ir_queue_item_t ir_queue[GB_MAX_IR_QUEUE]; + size_t ir_queue_length; - /* Callbacks */ - void *user_data; - GB_log_callback_t log_callback; - GB_input_callback_t input_callback; - GB_input_callback_t async_input_callback; - GB_rgb_encode_callback_t rgb_encode_callback; - GB_vblank_callback_t vblank_callback; - GB_infrared_callback_t infrared_callback; - GB_camera_get_pixel_callback_t camera_get_pixel_callback; - GB_camera_update_request_callback_t camera_update_request_callback; - GB_rumble_callback_t rumble_callback; - GB_serial_transfer_start_callback_t serial_transfer_start_callback; - GB_serial_transfer_end_callback_t serial_transfer_end_callback; - /* IR */ - long cycles_since_ir_change; - long cycles_since_input_ir_change; - GB_ir_queue_item_t ir_queue[GB_MAX_IR_QUEUE]; - size_t ir_queue_length; + /*** Debugger ***/ + volatile bool debug_stopped, debug_disable; + bool debug_fin_command, debug_next_command; - /*** Debugger ***/ - volatile bool debug_stopped, debug_disable; - bool debug_fin_command, debug_next_command; + /* Breakpoints */ + uint16_t n_breakpoints; + struct GB_breakpoint_s *breakpoints; - /* Breakpoints */ - uint16_t n_breakpoints; - struct GB_breakpoint_s *breakpoints; + /* SLD (Todo: merge with backtrace) */ + bool stack_leak_detection; + int debug_call_depth; + uint16_t sp_for_call_depth[0x200]; /* Should be much more than enough */ + uint16_t addr_for_call_depth[0x200]; - /* SLD (Todo: merge with backtrace) */ - bool stack_leak_detection; - int debug_call_depth; - uint16_t sp_for_call_depth[0x200]; /* Should be much more than enough */ - uint16_t addr_for_call_depth[0x200]; + /* Backtrace */ + unsigned int backtrace_size; + uint16_t backtrace_sps[0x200]; + struct { + uint16_t bank; + uint16_t addr; + } backtrace_returns[0x200]; - /* Backtrace */ - unsigned int backtrace_size; - uint16_t backtrace_sps[0x200]; - struct { - uint16_t bank; - uint16_t addr; - } backtrace_returns[0x200]; + /* Watchpoints */ + uint16_t n_watchpoints; + struct GB_watchpoint_s *watchpoints; - /* Watchpoints */ - uint16_t n_watchpoints; - struct GB_watchpoint_s *watchpoints; + /* Symbol tables */ + GB_symbol_map_t *bank_symbols[0x200]; + GB_reversed_symbol_map_t reversed_symbol_map; - /* Symbol tables */ - GB_symbol_map_t *bank_symbols[0x200]; - GB_reversed_symbol_map_t reversed_symbol_map; + /* Ticks command */ + unsigned long debugger_ticks; - /* Ticks command */ - unsigned long debugger_ticks; + /* Misc */ + bool turbo; + bool turbo_dont_skip; + bool disable_rendering; + uint32_t ram_size; // Different between CGB and DMG + uint8_t boot_rom[0x900]; + bool vblank_just_occured; // For slow operations involving syscalls; these should only run once per vblank + ); +}; + +#ifndef GB_INTERNAL +struct GB_gameboy_s { + char __internal[sizeof(struct GB_gameboy_internal_s)]; +}; +#endif - /* Misc */ - bool turbo; - bool turbo_dont_skip; - bool disable_rendering; - uint32_t ram_size; // Different between CGB and DMG - uint8_t boot_rom[0x900]; - bool vblank_just_occured; // For slow operations involving syscalls; these should only run once per vblank - -} GB_gameboy_t; #ifndef __printflike /* Missing from Linux headers. */ @@ -488,6 +481,8 @@ __attribute__((__format__ (__printf__, fmtarg, firstvararg))) void GB_init(GB_gameboy_t *gb); void GB_init_cgb(GB_gameboy_t *gb); void GB_free(GB_gameboy_t *gb); +void GB_reset(GB_gameboy_t *gb); +void GB_switch_model_and_reset(GB_gameboy_t *gb, bool is_cgb); int GB_load_boot_rom(GB_gameboy_t *gb, const char *path); int GB_load_rom(GB_gameboy_t *gb, const char *path); int GB_save_battery(GB_gameboy_t *gb, const char *path); @@ -519,8 +514,8 @@ void GB_serial_set_data(GB_gameboy_t *gb, uint8_t data); void GB_disconnect_serial(GB_gameboy_t *gb); -static inline bool GB_is_inited(GB_gameboy_t *gb) -{ - return gb->magic == 'SAME'; -} +bool GB_is_inited(GB_gameboy_t *gb); +void GB_set_turbo_mode(GB_gameboy_t *gb, bool on); +void *GB_get_user_data(GB_gameboy_t *gb); +void GB_set_user_data(GB_gameboy_t *gb, void *data); #endif /* GB_h */ diff --git a/Core/gb_struct_def.h b/Core/gb_struct_def.h new file mode 100644 index 0000000..0e0ebd1 --- /dev/null +++ b/Core/gb_struct_def.h @@ -0,0 +1,5 @@ +#ifndef gb_struct_def_h +#define gb_struct_def_h +struct GB_gameboy_s; +typedef struct GB_gameboy_s GB_gameboy_t; +#endif diff --git a/Core/joypad.c b/Core/joypad.c index bf3e120..c5c4f08 100644 --- a/Core/joypad.c +++ b/Core/joypad.c @@ -1,6 +1,6 @@ #include #include "gb.h" -#include "joypad.h" +#include void GB_update_joyp(GB_gameboy_t *gb) { @@ -54,4 +54,10 @@ void GB_update_joyp(GB_gameboy_t *gb) gb->io_registers[GB_IO_IF] |= 0x10; } gb->io_registers[GB_IO_JOYP] |= 0xC0; // No SGB support -} \ No newline at end of file +} + +void GB_set_key_state(GB_gameboy_t *gb, GB_key_t index, bool pressed) +{ + assert(index >= 0 && index < GB_KEY_MAX); + gb->keys[index] = pressed; +} diff --git a/Core/joypad.h b/Core/joypad.h index e7487a5..def4b9a 100644 --- a/Core/joypad.h +++ b/Core/joypad.h @@ -1,8 +1,22 @@ #ifndef joypad_h #define joypad_h -#include "gb.h" +#include "gb_struct_def.h" +typedef enum { + GB_KEY_RIGHT, + GB_KEY_LEFT, + GB_KEY_UP, + GB_KEY_DOWN, + GB_KEY_A, + GB_KEY_B, + GB_KEY_SELECT, + GB_KEY_START, + GB_KEY_MAX +} GB_key_t; + +void GB_set_key_state(GB_gameboy_t *gb, GB_key_t index, bool pressed); + +#ifdef GB_INTERNAL void GB_update_joyp(GB_gameboy_t *gb); -void GB_update_keys_status(GB_gameboy_t *gb); - +#endif #endif /* joypad_h */ diff --git a/Core/mbc.h b/Core/mbc.h index cd992b0..e7260f5 100644 --- a/Core/mbc.h +++ b/Core/mbc.h @@ -1,8 +1,31 @@ #ifndef MBC_h #define MBC_h -#include "gb.h" +#include "gb_struct_def.h" +typedef struct { + enum { + GB_NO_MBC, + GB_MBC1, + GB_MBC2, + GB_MBC3, + GB_MBC5, + GB_HUC1, /* Todo: HUC1 features are not emulated. Should be unified with the CGB IR sensor API. */ + GB_HUC3, + } mbc_type; + enum { + GB_STANDARD_MBC, + GB_CAMERA, + } mbc_subtype; + bool has_ram; + bool has_battery; + bool has_rtc; + bool has_rumble; +} GB_cartridge_t; + +#ifdef GB_INTERNAL extern const GB_cartridge_t GB_cart_defs[256]; void GB_update_mbc_mappings(GB_gameboy_t *gb); void GB_configure_cart(GB_gameboy_t *gb); +#endif + #endif /* MBC_h */ diff --git a/Core/memory.c b/Core/memory.c index 3c8356e..fb8e7cc 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -1,13 +1,6 @@ #include #include #include "gb.h" -#include "joypad.h" -#include "display.h" -#include "memory.h" -#include "debugger.h" -#include "mbc.h" -#include "timing.h" -#include "camera.h" typedef uint8_t GB_read_function_t(GB_gameboy_t *gb, uint16_t addr); typedef void GB_write_function_t(GB_gameboy_t *gb, uint16_t addr, uint8_t value); diff --git a/Core/memory.h b/Core/memory.h index b106742..16b3b92 100644 --- a/Core/memory.h +++ b/Core/memory.h @@ -4,7 +4,9 @@ uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr); void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value); +#ifdef GB_INTERNAL void GB_dma_run(GB_gameboy_t *gb); void GB_hdma_run(GB_gameboy_t *gb); +#endif #endif /* memory_h */ diff --git a/Core/printer.h b/Core/printer.h index c6322a8..e5d9036 100644 --- a/Core/printer.h +++ b/Core/printer.h @@ -2,12 +2,10 @@ #define printer_h #include #include - +#include "gb_struct_def.h" #define GB_PRINTER_MAX_COMMAND_LENGTH 0x280 #define GB_PRINTER_DATA_SIZE 0x280 -typedef struct GB_gameboy_s GB_gameboy_t; - typedef void (*GB_print_image_callback_t)(GB_gameboy_t *gb, uint32_t *image, uint8_t height, @@ -57,7 +55,5 @@ typedef struct } GB_printer_t; -typedef struct GB_gameboy_s GB_gameboy_t; - void GB_connect_printer(GB_gameboy_t *gb, GB_print_image_callback_t callback); -#endif \ No newline at end of file +#endif diff --git a/Core/symbol_hash.h b/Core/symbol_hash.h index 0544f94..239b0e3 100644 --- a/Core/symbol_hash.h +++ b/Core/symbol_hash.h @@ -21,16 +21,17 @@ typedef struct { size_t n_symbols; } GB_symbol_map_t; -GB_bank_symbol_t *GB_map_add_symbol(GB_symbol_map_t *map, uint16_t addr, const char *name); -const GB_bank_symbol_t *GB_map_find_symbol(GB_symbol_map_t *map, uint16_t addr); -GB_symbol_map_t *GB_map_alloc(void); -void GB_map_free(GB_symbol_map_t *map); - typedef struct { GB_symbol_t *buckets[0x400]; } GB_reversed_symbol_map_t; +#ifdef GB_INTERNAL void GB_reversed_map_add_symbol(GB_reversed_symbol_map_t *map, uint16_t bank, GB_bank_symbol_t *symbol); const GB_symbol_t *GB_reversed_map_find_symbol(GB_reversed_symbol_map_t *map, const char *name); +GB_bank_symbol_t *GB_map_add_symbol(GB_symbol_map_t *map, uint16_t addr, const char *name); +const GB_bank_symbol_t *GB_map_find_symbol(GB_symbol_map_t *map, uint16_t addr); +GB_symbol_map_t *GB_map_alloc(void); +void GB_map_free(GB_symbol_map_t *map); +#endif #endif /* symbol_hash_h */ diff --git a/Core/timing.c b/Core/timing.c index 1113984..d08006b 100644 --- a/Core/timing.c +++ b/Core/timing.c @@ -1,7 +1,4 @@ #include "gb.h" -#include "timing.h" -#include "memory.h" -#include "display.h" static void GB_ir_run(GB_gameboy_t *gb) { diff --git a/Core/timing.h b/Core/timing.h index 426ad9d..bd3b2f2 100644 --- a/Core/timing.h +++ b/Core/timing.h @@ -2,8 +2,17 @@ #define timing_h #include "gb.h" +#ifdef GB_INTERNAL void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles); void GB_set_internal_div_counter(GB_gameboy_t *gb, uint32_t value); void GB_rtc_run(GB_gameboy_t *gb); void GB_emulate_timer_glitch(GB_gameboy_t *gb, uint8_t old_tac, uint8_t new_tac); + +enum { + GB_TIMA_RUNNING = 0, + GB_TIMA_RELOADING = 1, + GB_TIMA_RELOADED = 2 +}; +#endif + #endif /* timing_h */ diff --git a/Core/z80_cpu.c b/Core/z80_cpu.c index 713ebe8..0a1bde5 100644 --- a/Core/z80_cpu.c +++ b/Core/z80_cpu.c @@ -1,9 +1,5 @@ #include #include -#include "z80_cpu.h" -#include "timing.h" -#include "memory.h" -#include "debugger.h" #include "gb.h" diff --git a/Core/z80_cpu.h b/Core/z80_cpu.h index 55a0ff8..1434ed7 100644 --- a/Core/z80_cpu.h +++ b/Core/z80_cpu.h @@ -1,7 +1,10 @@ #ifndef z80_cpu_h #define z80_cpu_h #include "gb.h" + void GB_cpu_disassemble(GB_gameboy_t *gb, uint16_t pc, uint16_t count); +#ifdef GB_INTERNAL void GB_cpu_run(GB_gameboy_t *gb); +#endif #endif /* z80_cpu_h */ diff --git a/Core/z80_disassembler.c b/Core/z80_disassembler.c index f9bfc8a..08fb62f 100644 --- a/Core/z80_disassembler.c +++ b/Core/z80_disassembler.c @@ -1,9 +1,6 @@ #include #include -#include "z80_cpu.h" -#include "memory.h" #include "gb.h" -#include "debugger.h" typedef void GB_opcode_t(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc); diff --git a/Makefile b/Makefile index ed7d3cb..18dbe23 100755 --- a/Makefile +++ b/Makefile @@ -135,6 +135,10 @@ $(OBJ)/%.dep: % # Compilation rules +$(OBJ)/Core/%.c.o: Core/%.c + -@$(MKDIR) -p $(dir $@) + $(CC) $(CFLAGS) -DGB_INTERNAL -c $< -o $@ + $(OBJ)/%.c.o: %.c -@$(MKDIR) -p $(dir $@) $(CC) $(CFLAGS) -c $< -o $@ diff --git a/QuickLook/get_image_for_rom.c b/QuickLook/get_image_for_rom.c index 3372526..59e1c5d 100755 --- a/QuickLook/get_image_for_rom.c +++ b/QuickLook/get_image_for_rom.c @@ -1,3 +1,6 @@ +#define GB_INTERNAL // Todo: This file runs SameBoy in a special configuration + // of the turbo mode, which is not available without direct + // struct access #include #include #include @@ -27,7 +30,7 @@ static void log_callback(GB_gameboy_t *gb, const char *string, GB_log_attributes static void vblank(GB_gameboy_t *gb) { - struct local_data *local_data = (struct local_data *)gb->user_data; + struct local_data *local_data = (struct local_data *)GB_get_user_data(gb); if (local_data->frames == LENGTH) { local_data->running = false; @@ -66,7 +69,7 @@ int get_image_for_rom(const char *filename, const char *boot_path, uint32_t *out /* Run emulation */ struct local_data local_data = {0,}; - gb.user_data = &local_data; + GB_set_user_data(&gb, &local_data); local_data.running = true; local_data.frames = 0; gb.turbo = gb.turbo_dont_skip = gb.disable_rendering = true; diff --git a/SDL/main.c b/SDL/main.c index a742228..943ff7d 100755 --- a/SDL/main.c +++ b/SDL/main.c @@ -16,7 +16,6 @@ #endif #include "gb.h" -#include "debugger.h" static bool running = false; static char *filename; @@ -38,34 +37,33 @@ static void GB_update_keys_status(GB_gameboy_t *gb) running = false; case SDL_KEYDOWN: case SDL_KEYUP: - gb->stopped = false; switch (event.key.keysym.sym) { case SDLK_RIGHT: - gb->keys[0] = event.type == SDL_KEYDOWN; + GB_set_key_state(gb, GB_KEY_RIGHT, event.type == SDL_KEYDOWN); break; case SDLK_LEFT: - gb->keys[1] = event.type == SDL_KEYDOWN; + GB_set_key_state(gb, GB_KEY_LEFT, event.type == SDL_KEYDOWN); break; case SDLK_UP: - gb->keys[2] = event.type == SDL_KEYDOWN; + GB_set_key_state(gb, GB_KEY_UP, event.type == SDL_KEYDOWN); break; case SDLK_DOWN: - gb->keys[3] = event.type == SDL_KEYDOWN; + GB_set_key_state(gb, GB_KEY_DOWN, event.type == SDL_KEYDOWN); break; case SDLK_x: - gb->keys[4] = event.type == SDL_KEYDOWN; + GB_set_key_state(gb, GB_KEY_A, event.type == SDL_KEYDOWN); break; case SDLK_z: - gb->keys[5] = event.type == SDL_KEYDOWN; + GB_set_key_state(gb, GB_KEY_B, event.type == SDL_KEYDOWN); break; case SDLK_BACKSPACE: - gb->keys[6] = event.type == SDL_KEYDOWN; + GB_set_key_state(gb, GB_KEY_SELECT, event.type == SDL_KEYDOWN); break; case SDLK_RETURN: - gb->keys[7] = event.type == SDL_KEYDOWN; + GB_set_key_state(gb, GB_KEY_START, event.type == SDL_KEYDOWN); break; case SDLK_SPACE: - gb->turbo = event.type == SDL_KEYDOWN; + GB_set_turbo_mode(gb, event.type == SDL_KEYDOWN); break; case SDLK_LCTRL: case SDLK_RCTRL: @@ -85,7 +83,7 @@ static void GB_update_keys_status(GB_gameboy_t *gb) case SDLK_c: if (ctrl && event.type == SDL_KEYDOWN) { ctrl = false; - gb->debug_stopped = true; + GB_debugger_break(gb); } break; @@ -122,7 +120,7 @@ static void GB_update_keys_status(GB_gameboy_t *gb) static void vblank(GB_gameboy_t *gb) { - SDL_Surface *screen = gb->user_data; + SDL_Surface *screen = GB_get_user_data(gb); SDL_Flip(screen); GB_update_keys_status(gb); @@ -189,10 +187,10 @@ static uint32_t rgb_encode(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b) static void debugger_interrupt(int ignore) { /* ^C twice to exit */ - if (gb.debug_stopped) { + if (GB_debugger_is_stopped(&gb)) { exit(0); } - gb.debug_stopped = true; + GB_debugger_break(&gb); } @@ -280,7 +278,7 @@ usage: /* Configure Screen */ SDL_LockSurface(screen); GB_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank); - gb.user_data = screen; + GB_set_user_data(&gb, screen); GB_set_pixels_output(&gb, screen->pixels); GB_set_rgb_encode_callback(&gb, rgb_encode); diff --git a/Tester/main.c b/Tester/main.c index 891f35f..36cf567 100755 --- a/Tester/main.c +++ b/Tester/main.c @@ -1,3 +1,6 @@ +// The tester requires low-level access to the GB struct to detect failures +#define GB_INTERNAL + #include #include #include