From 346e499602babe09288c76386a33e9528eb79d3a Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Mon, 15 Jul 2019 23:02:58 +0300 Subject: [PATCH] ICD APIs --- Core/display.c | 24 +++++++++++++++++++----- Core/gb.c | 27 +++++++++++++++++++++++++-- Core/gb.h | 11 +++++++++-- Core/memory.c | 4 ++++ 4 files changed, 57 insertions(+), 9 deletions(-) diff --git a/Core/display.c b/Core/display.c index cdcdeb2..54c53a5 100644 --- a/Core/display.c +++ b/Core/display.c @@ -137,9 +137,8 @@ static void display_vblank(GB_gameboy_t *gb) if (!gb->disable_rendering && ((!(gb->io_registers[GB_IO_LCDC] & 0x80) || gb->stopped) || gb->frame_skip_state == GB_FRAMESKIP_LCD_TURNED_ON)) { /* LCD is off, set screen to white or black (if LCD is on in stop mode) */ if (gb->sgb) { - uint8_t color = (gb->io_registers[GB_IO_LCDC] & 0x80) && gb->stopped && GB_is_cgb(gb) ? 0x3 : 0x0; for (unsigned i = 0; i < WIDTH * LINES; i++) { - gb->sgb->screen_buffer[i] = color; + gb->sgb->screen_buffer[i] = 0x0; } } else { @@ -387,9 +386,12 @@ static void render_pixel_if_possible(GB_gameboy_t *gb) } if (gb->sgb) { if (gb->current_lcd_line < LINES) { - gb->sgb->screen_buffer[gb->position_in_line + gb->current_lcd_line * WIDTH] = pixel; + gb->sgb->screen_buffer[gb->position_in_line + gb->current_lcd_line * WIDTH] = gb->stopped? 0 : pixel; } } + else if (gb->model & GB_MODEL_NO_SFC_BIT) { + gb->icd_row[gb->position_in_line] = pixel; + } else { gb->screen[gb->position_in_line + gb->current_line * WIDTH] = gb->background_palettes_rgb[fifo_item->palette * 4 + pixel]; } @@ -403,9 +405,12 @@ static void render_pixel_if_possible(GB_gameboy_t *gb) } if (gb->sgb) { if (gb->current_lcd_line < LINES) { - gb->sgb->screen_buffer[gb->position_in_line + gb->current_lcd_line * WIDTH] = pixel; + gb->sgb->screen_buffer[gb->position_in_line + gb->current_lcd_line * WIDTH] = gb->stopped? 0 : pixel; } } + else if (gb->model & GB_MODEL_NO_SFC_BIT) { + gb->icd_row[gb->position_in_line] = pixel; + } else { gb->screen[gb->position_in_line + gb->current_line * WIDTH] = gb->sprite_palettes_rgb[oam_fifo_item->palette * 4 + pixel]; } @@ -890,6 +895,11 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) } GB_SLEEP(gb, display, 11, LINE_LENGTH - gb->cycles_for_line); gb->mode_for_interrupt = 2; + + /* TODO: Can this timing even be verified? */ + if (gb->icd_row_callback) { + gb->icd_row_callback(gb, gb->icd_row); + } } /* Lines 144 - 152 */ @@ -961,7 +971,11 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) gb->wy_diff = 0; gb->window_disabled_while_active = false; gb->current_line = 0; - gb->current_lcd_line = -1; // TODO: not the correct timing + // TODO: not the correct timing + gb->current_lcd_line = -1; + if (gb->icd_vreset_callback) { + gb->icd_vreset_callback(gb); + } } } diff --git a/Core/gb.c b/Core/gb.c index a1d0f19..ff2fd3c 100644 --- a/Core/gb.c +++ b/Core/gb.c @@ -112,6 +112,11 @@ void GB_init(GB_gameboy_t *gb, GB_model_t model) gb->cartridge_type = &GB_cart_defs[0]; // Default cartridge type gb->clock_multiplier = 1.0; + if (model & GB_MODEL_NO_SFC_BIT) { + /* Disable time syncing. Timing should be done by the SFC emulator. */ + gb->turbo = true; + } + GB_reset(gb); } @@ -576,6 +581,7 @@ static void reset_ram(GB_gameboy_t *gb) case GB_MODEL_DMG_B: case GB_MODEL_SGB_NTSC: /* Unverified*/ case GB_MODEL_SGB_PAL: /* Unverified */ + case GB_MODEL_SGB_NO_SFC: for (unsigned i = 0; i < gb->ram_size; i++) { gb->ram[i] = GB_random(); if (i & 0x100) { @@ -588,6 +594,7 @@ static void reset_ram(GB_gameboy_t *gb) break; case GB_MODEL_SGB2: + case GB_MODEL_SGB2_NO_SFC: for (unsigned i = 0; i < gb->ram_size; i++) { gb->ram[i] = 0x55; gb->ram[i] ^= GB_random() & GB_random() & GB_random(); @@ -620,7 +627,9 @@ static void reset_ram(GB_gameboy_t *gb) case GB_MODEL_DMG_B: case GB_MODEL_SGB_NTSC: /* Unverified*/ case GB_MODEL_SGB_PAL: /* Unverified */ + case GB_MODEL_SGB_NO_SFC: case GB_MODEL_SGB2: + case GB_MODEL_SGB2_NO_SFC: for (unsigned i = 0; i < sizeof(gb->hram); i++) { if (i & 1) { gb->hram[i] = GB_random() | GB_random() | GB_random(); @@ -641,9 +650,11 @@ static void reset_ram(GB_gameboy_t *gb) break; case GB_MODEL_DMG_B: - case GB_MODEL_SGB_NTSC: /* Unverified*/ + case GB_MODEL_SGB_NTSC: /* Unverified */ case GB_MODEL_SGB_PAL: /* Unverified */ + case GB_MODEL_SGB_NO_SFC: /* Unverified */ case GB_MODEL_SGB2: + case GB_MODEL_SGB2_NO_SFC: for (unsigned i = 0; i < 8; i++) { if (i & 2) { gb->oam[i] = GB_random() & GB_random() & GB_random(); @@ -669,7 +680,9 @@ static void reset_ram(GB_gameboy_t *gb) case GB_MODEL_DMG_B: case GB_MODEL_SGB_NTSC: /* Unverified*/ case GB_MODEL_SGB_PAL: /* Unverified */ - case GB_MODEL_SGB2: { + case GB_MODEL_SGB_NO_SFC: /* Unverified */ + case GB_MODEL_SGB2: + case GB_MODEL_SGB2_NO_SFC: { uint8_t temp; for (unsigned i = 0; i < GB_IO_WAV_END - GB_IO_WAV_START; i++) { if (i & 1) { @@ -911,3 +924,13 @@ void GB_set_joyp_write_callback(GB_gameboy_t *gb, GB_joyp_write_callback_t callb { gb->joyp_write_callback = callback; } + +void GB_set_icd_row_callback(GB_gameboy_t *gb, GB_icd_row_callback_t callback) +{ + gb->icd_row_callback = callback; +} + +void GB_set_icd_vreset_callback(GB_gameboy_t *gb, GB_icd_vreset_callback_t callback) +{ + gb->icd_vreset_callback = callback; +} diff --git a/Core/gb.h b/Core/gb.h index b82d743..eed23e4 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -23,7 +23,6 @@ #define GB_STRUCT_VERSION 13 -#ifdef GB_INTERNAL #define GB_MODEL_FAMILY_MASK 0xF00 #define GB_MODEL_DMG_FAMILY 0x000 #define GB_MODEL_MGB_FAMILY 0x100 @@ -31,6 +30,7 @@ #define GB_MODEL_PAL_BIT 0x1000 #define GB_MODEL_NO_SFC_BIT 0x2000 +#ifdef GB_INTERNAL #if __clang__ #define UNROLL _Pragma("unroll") #elif __GNUC__ @@ -243,6 +243,8 @@ typedef void (*GB_serial_transfer_bit_start_callback_t)(GB_gameboy_t *gb, bool b typedef bool (*GB_serial_transfer_bit_end_callback_t)(GB_gameboy_t *gb); typedef void (*GB_update_input_hint_callback_t)(GB_gameboy_t *gb); typedef void (*GB_joyp_write_callback_t)(GB_gameboy_t *gb, uint8_t value); +typedef void (*GB_icd_row_callback_t)(GB_gameboy_t *gb, uint8_t *row); +typedef void (*GB_icd_vreset_callback_t)(GB_gameboy_t *gb); typedef struct { bool state; @@ -420,6 +422,7 @@ struct GB_gameboy_internal_s { uint16_t serial_length; uint8_t double_speed_alignment; uint8_t serial_count; + uint8_t icd_row[160]; ); /* APU */ @@ -535,6 +538,8 @@ struct GB_gameboy_internal_s { GB_serial_transfer_bit_end_callback_t serial_transfer_bit_end_callback; GB_update_input_hint_callback_t update_input_hint_callback; GB_joyp_write_callback_t joyp_write_callback; + GB_icd_row_callback_t icd_row_callback; + GB_icd_vreset_callback_t icd_vreset_callback; /* IR */ long cycles_since_ir_change; // In 8MHz units @@ -696,7 +701,9 @@ void GB_disconnect_serial(GB_gameboy_t *gb); /* For integration with SFC/SNES emulators */ void GB_set_joyp_write_callback(GB_gameboy_t *gb, GB_joyp_write_callback_t callback); - +void GB_set_icd_row_callback(GB_gameboy_t *gb, GB_icd_row_callback_t callback); +void GB_set_icd_vreset_callback(GB_gameboy_t *gb, GB_icd_vreset_callback_t callback); + #ifdef GB_INTERNAL uint32_t GB_get_clock_rate(GB_gameboy_t *gb); #endif diff --git a/Core/memory.c b/Core/memory.c index 868a245..e5983cb 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -273,7 +273,9 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr) case GB_MODEL_DMG_B: case GB_MODEL_SGB_NTSC: case GB_MODEL_SGB_PAL: + case GB_MODEL_SGB_NO_SFC: case GB_MODEL_SGB2: + case GB_MODEL_SGB2_NO_SFC: ; } } @@ -584,7 +586,9 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) case GB_MODEL_DMG_B: case GB_MODEL_SGB_NTSC: case GB_MODEL_SGB_PAL: + case GB_MODEL_SGB_NO_SFC: case GB_MODEL_SGB2: + case GB_MODEL_SGB2_NO_SFC: case GB_MODEL_CGB_E: case GB_MODEL_AGB: break;