From 7d51ba3d9745917f7b5855bcc53e28dd7b5d2be2 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Fri, 21 Feb 2020 16:16:02 +0200 Subject: [PATCH] More fixes, SGB emulation of the same quirk --- Core/display.c | 19 +++++++++++++------ Core/gb.h | 1 + Core/sm83_cpu.c | 42 ++++++++++++++++++++++++++++++------------ 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/Core/display.c b/Core/display.c index 99b8185..7523f6d 100644 --- a/Core/display.c +++ b/Core/display.c @@ -735,6 +735,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) GB_STATE(gb, display, 36); GB_STATE(gb, display, 37); GB_STATE(gb, display, 38); + GB_STATE(gb, display, 39); } @@ -904,15 +905,16 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) gb->obj_comparators[gb->n_visible_objs - 1] < (uint8_t)(gb->position_in_line + 8)) { gb->n_visible_objs--; } + + gb->during_object_fetch = true; while (gb->n_visible_objs != 0 && (gb->io_registers[GB_IO_LCDC] & 2 || GB_is_cgb(gb)) && gb->obj_comparators[gb->n_visible_objs - 1] == (uint8_t)(gb->position_in_line + 8)) { - while (gb->fetcher_state < 5) { advance_fetcher_state_machine(gb); gb->cycles_for_line++; GB_SLEEP(gb, display, 27, 1); - if (!(gb->io_registers[GB_IO_LCDC] & 2) && !GB_is_cgb(gb)) { + if (gb->object_fetch_aborted) { goto abort_fetching_object; } } @@ -924,18 +926,20 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) GB_SLEEP(gb, display, 28, gb->extra_penalty_for_sprite_at_0); gb->extra_penalty_for_sprite_at_0 = 0; if (gb->object_fetch_aborted) { - gb->object_fetch_aborted = false; goto abort_fetching_object; } } } - gb->cycles_for_line += 6; - GB_SLEEP(gb, display, 20, 6); + gb->cycles_for_line += 5; + GB_SLEEP(gb, display, 20, 5); if (gb->object_fetch_aborted) { - gb->object_fetch_aborted = false; goto abort_fetching_object; } + gb->during_object_fetch = false; + gb->cycles_for_line++; + GB_SLEEP(gb, display, 39, 1); + /* TODO: what does the PPU read if DMA is active? */ const GB_object_t *object = &objects[gb->visible_objs[gb->n_visible_objs - 1]]; if (gb->oam_ppu_blocked) { @@ -973,6 +977,9 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) } abort_fetching_object: + gb->object_fetch_aborted = false; + gb->during_object_fetch = false; + /* Handle window */ /* Todo: Timing (Including penalty and access timings) not verified by test ROM */ if (!gb->in_window && window_enabled(gb) && diff --git a/Core/gb.h b/Core/gb.h index 4e31e00..11bd10e 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -519,6 +519,7 @@ struct GB_gameboy_internal_s { bool vram_ppu_blocked; bool cgb_palettes_ppu_blocked; bool object_fetch_aborted; + bool during_object_fetch; ); /* Unsaved data. This includes all pointers, as well as everything that shouldn't be on a save state */ diff --git a/Core/sm83_cpu.c b/Core/sm83_cpu.c index 1dbfc5e..4caaa34 100644 --- a/Core/sm83_cpu.c +++ b/Core/sm83_cpu.c @@ -19,6 +19,7 @@ typedef enum { GB_CONFLICT_PALETTE_DMG, GB_CONFLICT_PALETTE_CGB, GB_CONFLICT_DMG_LCDC, + GB_CONFLICT_SGB_LCDC, } GB_conflict_t; /* Todo: How does double speed mode affect these? */ @@ -56,7 +57,7 @@ static const GB_conflict_t dmg_conflict_map[0x80] = { static const GB_conflict_t sgb_conflict_map[0x80] = { [GB_IO_IF] = GB_CONFLICT_WRITE_CPU, [GB_IO_LYC] = GB_CONFLICT_READ_OLD, - [GB_IO_LCDC] = GB_CONFLICT_READ_NEW, + [GB_IO_LCDC] = GB_CONFLICT_SGB_LCDC, [GB_IO_SCY] = GB_CONFLICT_READ_NEW, [GB_IO_STAT] = GB_CONFLICT_STAT_DMG, @@ -207,16 +208,9 @@ static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value) uint8_t old_value = GB_read_memory(gb, addr); GB_advance_cycles(gb, gb->pending_cycles - 2); - if (gb->current_lcd_line == 108) { - - } - /* Handle disabling objects while already fetching an object */ if ((old_value & 2) && !(value & 2)) { - if (gb->display_state == 27) { - old_value &= ~2; - } - else if (gb->display_state == 20 || gb->display_state == 28) { + if (gb->during_object_fetch) { gb->cycles_for_line -= gb->display_cycles; gb->display_cycles = 0; gb->object_fetch_aborted = true; @@ -231,10 +225,34 @@ static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value) GB_advance_cycles(gb, 1); /* Handle disabling objects while already fetching an object */ if ((old_value & 2) && !(value & 2)) { - if (gb->display_state == 27) { - old_value &= ~2; + if (gb->during_object_fetch) { + gb->cycles_for_line -= gb->display_cycles; + gb->display_cycles = 0; + gb->object_fetch_aborted = true; } - else if (gb->display_state == 20 || gb->display_state == 28) { + } + GB_write_memory(gb, addr, value); + gb->pending_cycles = 5; + return; + } + + case GB_CONFLICT_SGB_LCDC: { + /* Simplified version of the above */ + + uint8_t old_value = GB_read_memory(gb, addr); + GB_advance_cycles(gb, gb->pending_cycles - 2); + /* Handle disabling objects while already fetching an object */ + if ((old_value & 2) && !(value & 2)) { + if (gb->during_object_fetch) { + gb->cycles_for_line -= gb->display_cycles; + gb->display_cycles = 0; + gb->object_fetch_aborted = true; + } + } + GB_advance_cycles(gb, 1); + /* Handle disabling objects while already fetching an object */ + if ((old_value & 2) && !(value & 2)) { + if (gb->during_object_fetch) { gb->cycles_for_line -= gb->display_cycles; gb->display_cycles = 0; gb->object_fetch_aborted = true;