From 0f643e01b733b1e59f9a9eb17c7582a399b31a42 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Fri, 8 Sep 2017 12:58:35 +0300 Subject: [PATCH 1/8] Removing the delayed interrupt mechanism, research is not complete enough for implementation --- Core/display.c | 11 ----------- Core/gb.h | 1 - Core/timing.c | 3 +-- Core/z80_cpu.c | 2 +- 4 files changed, 2 insertions(+), 15 deletions(-) diff --git a/Core/display.c b/Core/display.c index 4def6c8..ae0e77f 100755 --- a/Core/display.c +++ b/Core/display.c @@ -300,7 +300,6 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) uint8_t vram_blocking_rush = gb->is_cgb? 0 : 4; for (; cycles; cycles -= atomic_increase) { - gb->delayed_interrupts &= ~3; gb->display_cycles += atomic_increase; /* The very first line is 4 clocks shorter when the LCD turns on. Verified on SGB2, CGB in CGB mode and CGB in double speed mode. */ @@ -344,10 +343,6 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) gb->io_registers[GB_IO_STAT] &= ~3; gb->io_registers[GB_IO_STAT] |= 1; gb->io_registers[GB_IO_IF] |= 1; - if (gb->is_cgb) { - /* See comment on STAT interrupt at the end of the loop */ - gb->delayed_interrupts |= 1; - } /* Entering VBlank state triggers the OAM interrupt. In CGB, it happens 4 cycles earlier */ if (gb->io_registers[GB_IO_STAT] & 0x20 && !gb->is_cgb) { @@ -563,12 +558,6 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) if (gb->stat_interrupt_line && !previous_stat_interrupt_line) { gb->io_registers[GB_IO_IF] |= 2; - if (gb->is_cgb) { - /* On CGB, the STAT interrupt is not aligned to a T-Cycle, therefore it is only effective the next T-Cycle - Todo: verify on DMG mode CGB. This was only tested on LYC STAT interrupts, should be tested on others - as well. */ - gb->delayed_interrupts |= 2; - } } #if 0 diff --git a/Core/gb.h b/Core/gb.h index 773dccc..c18bf30 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -332,7 +332,6 @@ struct GB_gameboy_internal_s { GB_PADDING(uint16_t, serial_cycles); uint16_t serial_cycles; /* This field changed its meaning in v0.10 */ uint16_t serial_length; - uint8_t delayed_interrupts; /* When an interrupt occurs while not aligned to a T-cycle, it must be "delayed" */ bool dont_delay_timer_interrupt; /* If the timer glitch causes a TIMA overflow, it causes the timer to overflow with different timing, so the triggered interrupt is not delayed. Todo: needs test ROM. */ diff --git a/Core/timing.c b/Core/timing.c index 626cb45..e5ac788 100644 --- a/Core/timing.c +++ b/Core/timing.c @@ -82,14 +82,13 @@ static void GB_ir_run(GB_gameboy_t *gb) static void advance_tima_state_machine(GB_gameboy_t *gb) { - gb->delayed_interrupts &= ~4; if (gb->tima_reload_state == GB_TIMA_RELOADED) { gb->tima_reload_state = GB_TIMA_RUNNING; } else if (gb->tima_reload_state == GB_TIMA_RELOADING) { gb->io_registers[GB_IO_IF] |= 4; if (!gb->dont_delay_timer_interrupt) { - gb->delayed_interrupts |= 4; // Timer interrupt is not aligned to a T-cycle and therefore is effective only the next one. + // Todo } gb->tima_reload_state = GB_TIMA_RELOADED; } diff --git a/Core/z80_cpu.c b/Core/z80_cpu.c index b6dde8a..ce30d55 100644 --- a/Core/z80_cpu.c +++ b/Core/z80_cpu.c @@ -1337,7 +1337,7 @@ static GB_opcode_t *opcodes[256] = { void GB_cpu_run(GB_gameboy_t *gb) { gb->vblank_just_occured = false; - uint8_t interrupt_queue = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F & ~gb->delayed_interrupts; + uint8_t interrupt_queue = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F; if (interrupt_queue) { gb->halted = false; From 0f1fa3176f2d7f4aeacb6cceda5baa465befca8f Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Fri, 8 Sep 2017 12:59:57 +0300 Subject: [PATCH 2/8] Refinements to LCD timing (breaks vblank_stat_intr-GS for now) --- Core/display.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Core/display.c b/Core/display.c index ae0e77f..b3dd4b6 100755 --- a/Core/display.c +++ b/Core/display.c @@ -292,9 +292,12 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) /* According to AntonioND's docs this value should be 0 in CGB mode, but tests I ran on my CGB seem to contradict these findings. Todo: Investigate what causes the difference between our findings */ - uint8_t stat_delay = gb->cgb_double_speed? 2 : 4; //(gb->cgb_mode? 0 : 4); - /* Todo: This is correct for DMG. Is it correct for the 3 CGB modes (DMG/single/double)?*/ - uint8_t scx_delay = ((gb->effective_scx & 7) + atomic_increase - 1) & ~(atomic_increase - 1); + uint8_t stat_delay = gb->cgb_double_speed? 2 : 4; // (gb->cgb_mode? 0 : 4); + /* Todo: This is correct for DMG and single speed CGB. Is it correct for double speed and DMG mode CGB?*/ + uint8_t scx_delay = ((uint8_t []){0, 2, 2, 4, 4, 6, 6, 8})[gb->effective_scx]; + if (!gb->cgb_double_speed) { + scx_delay &= ~3; + } /* Todo: These are correct for DMG, DMG-mode CGB, and single speed CGB. Is is correct for double speed CGB? */ uint8_t oam_blocking_rush = gb->cgb_double_speed? 2 : 4; uint8_t vram_blocking_rush = gb->is_cgb? 0 : 4; @@ -303,7 +306,7 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) gb->display_cycles += atomic_increase; /* The very first line is 4 clocks shorter when the LCD turns on. Verified on SGB2, CGB in CGB mode and CGB in double speed mode. */ - if (gb->first_scanline && gb->display_cycles >= LINE_LENGTH - 4) { + if (gb->first_scanline && gb->display_cycles >= LINE_LENGTH - 8) { gb->first_scanline = false; gb->display_cycles += 4; } @@ -382,7 +385,7 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) gb->oam_write_blocked = true; gb->vram_write_blocked = true; } - else if (gb->display_cycles == MODE2_LENGTH + MODE3_LENGTH) { + else if (gb->display_cycles == MODE2_LENGTH + MODE3_LENGTH + scx_delay) { gb->io_registers[GB_IO_STAT] &= ~3; gb->oam_read_blocked = false; gb->vram_read_blocked = false; From e5d354e896236b4fab562885b6778fe602b8c185 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Fri, 8 Sep 2017 17:25:01 +0300 Subject: [PATCH 3/8] =?UTF-8?q?Refined=20SCX=E2=80=99s=20effects=20on=20PP?= =?UTF-8?q?U=20timing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/display.c | 50 +++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/Core/display.c b/Core/display.c index b3dd4b6..2106617 100755 --- a/Core/display.c +++ b/Core/display.c @@ -250,9 +250,6 @@ void GB_palette_changed(GB_gameboy_t *gb, bool background_palette, uint8_t index static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) { - uint8_t previous_stat_interrupt_line = gb->stat_interrupt_line; - gb->stat_interrupt_line = false; - if (!(gb->io_registers[GB_IO_LCDC] & 0x80)) { /* LCD is disabled, state is constant */ @@ -261,6 +258,7 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) gb->io_registers[GB_IO_LY] = 0; gb->io_registers[GB_IO_STAT] &= ~3; gb->io_registers[GB_IO_STAT] |= 4; + gb->effective_scx = gb->io_registers[GB_IO_SCX]; if (gb->hdma_on_hblank) { gb->hdma_on_hblank = false; gb->hdma_on = false; @@ -294,15 +292,16 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) Todo: Investigate what causes the difference between our findings */ uint8_t stat_delay = gb->cgb_double_speed? 2 : 4; // (gb->cgb_mode? 0 : 4); /* Todo: This is correct for DMG and single speed CGB. Is it correct for double speed and DMG mode CGB?*/ - uint8_t scx_delay = ((uint8_t []){0, 2, 2, 4, 4, 6, 6, 8})[gb->effective_scx]; - if (!gb->cgb_double_speed) { - scx_delay &= ~3; - } + uint8_t scx_delay = (gb->effective_scx + (gb->first_scanline ? 2 : 0)) & (gb->cgb_double_speed? ~1 : ~3); + /* Todo: These are correct for DMG, DMG-mode CGB, and single speed CGB. Is is correct for double speed CGB? */ uint8_t oam_blocking_rush = gb->cgb_double_speed? 2 : 4; uint8_t vram_blocking_rush = gb->is_cgb? 0 : 4; for (; cycles; cycles -= atomic_increase) { + bool previous_stat_interrupt_line = gb->stat_interrupt_line; + gb->stat_interrupt_line = false; + gb->display_cycles += atomic_increase; /* The very first line is 4 clocks shorter when the LCD turns on. Verified on SGB2, CGB in CGB mode and CGB in double speed mode. */ @@ -312,6 +311,7 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) } bool should_compare_ly = true; uint8_t ly_for_comparison = gb->io_registers[GB_IO_LY] = gb->display_cycles / LINE_LENGTH; + bool just_entered_hblank = false; /* Handle cycle completion. STAT's initial value depends on model and mode */ @@ -380,6 +380,7 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) else if (gb->display_cycles == MODE2_LENGTH) { gb->io_registers[GB_IO_STAT] &= ~3; gb->io_registers[GB_IO_STAT] |= 3; + gb->effective_scx = gb->io_registers[GB_IO_SCX]; gb->oam_read_blocked = true; gb->vram_read_blocked = true; gb->oam_write_blocked = true; @@ -391,6 +392,7 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) gb->vram_read_blocked = false; gb->oam_write_blocked = false; gb->vram_write_blocked = false; + just_entered_hblank = true; } } @@ -438,6 +440,7 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) gb->previous_lcdc_x = - (gb->effective_scx & 0x7); } else if (position_in_line == MODE2_LENGTH + MODE3_LENGTH + stat_delay + scx_delay) { + just_entered_hblank = true; gb->io_registers[GB_IO_STAT] &= ~3; gb->oam_read_blocked = false; gb->vram_read_blocked = false; @@ -539,28 +542,33 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) if (!gb->stat_interrupt_line) { switch (gb->io_registers[GB_IO_STAT] & 3) { - case 0: gb->stat_interrupt_line = gb->io_registers[GB_IO_STAT] & 8; break; + case 0: + gb->stat_interrupt_line = (gb->io_registers[GB_IO_STAT] & 8); + if (just_entered_hblank && ((gb->effective_scx + (gb->first_scanline ? 2 : 0)) & 3) == 3) { + gb->stat_interrupt_line = false; + } + break; case 1: gb->stat_interrupt_line = gb->io_registers[GB_IO_STAT] & 0x10; break; case 2: gb->stat_interrupt_line = gb->io_registers[GB_IO_STAT] & 0x20; break; } - /* Use requested a LY=LYC interrupt and the LY=LYC bit is on */ + /* User requested a LY=LYC interrupt and the LY=LYC bit is on */ if ((gb->io_registers[GB_IO_STAT] & 0x44) == 0x44) { gb->stat_interrupt_line = true; } } - } - - /* On the CGB, the last cycle of line 144 triggers an OAM interrupt - Todo: Verify timing for CGB in CGB mode and double speed CGB */ - if (gb->is_cgb && - gb->display_cycles == LINES * LINE_LENGTH + stat_delay - atomic_increase && - (gb->io_registers[GB_IO_STAT] & 0x20)) { - gb->stat_interrupt_line = true; - } - - if (gb->stat_interrupt_line && !previous_stat_interrupt_line) { - gb->io_registers[GB_IO_IF] |= 2; + + /* On the CGB, the last cycle of line 144 triggers an OAM interrupt + Todo: Verify timing for CGB in CGB mode and double speed CGB */ + if (gb->is_cgb && + gb->display_cycles == LINES * LINE_LENGTH + stat_delay - atomic_increase && + (gb->io_registers[GB_IO_STAT] & 0x20)) { + gb->stat_interrupt_line = true; + } + + if (gb->stat_interrupt_line && !previous_stat_interrupt_line) { + gb->io_registers[GB_IO_IF] |= 2; + } } #if 0 From 742c9e95d3d133ff3ca53097c0bc63cfce43bb6e Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Fri, 8 Sep 2017 23:46:38 +0300 Subject: [PATCH 4/8] Updated previous timing improvements to correctly implement double speed behavior --- Core/display.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Core/display.c b/Core/display.c index 2106617..c0f385f 100755 --- a/Core/display.c +++ b/Core/display.c @@ -291,8 +291,14 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) these findings. Todo: Investigate what causes the difference between our findings */ uint8_t stat_delay = gb->cgb_double_speed? 2 : 4; // (gb->cgb_mode? 0 : 4); - /* Todo: This is correct for DMG and single speed CGB. Is it correct for double speed and DMG mode CGB?*/ - uint8_t scx_delay = (gb->effective_scx + (gb->first_scanline ? 2 : 0)) & (gb->cgb_double_speed? ~1 : ~3); + /* Todo: Is this correct for DMG mode CGB? */ + uint8_t scx_delay = gb->effective_scx; + if (gb->cgb_double_speed) { + scx_delay = (scx_delay + 1) & ~1; + } + else { + scx_delay = (scx_delay + (gb->first_scanline ? 2 : 0)) & ~3; + } /* Todo: These are correct for DMG, DMG-mode CGB, and single speed CGB. Is is correct for double speed CGB? */ uint8_t oam_blocking_rush = gb->cgb_double_speed? 2 : 4; @@ -544,7 +550,7 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) switch (gb->io_registers[GB_IO_STAT] & 3) { case 0: gb->stat_interrupt_line = (gb->io_registers[GB_IO_STAT] & 8); - if (just_entered_hblank && ((gb->effective_scx + (gb->first_scanline ? 2 : 0)) & 3) == 3) { + if (!gb->cgb_double_speed && just_entered_hblank && ((gb->effective_scx + (gb->first_scanline ? 2 : 0)) & 3) == 3) { gb->stat_interrupt_line = false; } break; From 1e90400916031b5f5d95fe377019cd53a8069fd8 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sat, 9 Sep 2017 13:32:12 +0300 Subject: [PATCH 5/8] Reimplemented delayed/future interrupts, currently correct only for CGB. --- Core/display.c | 17 +++++++++++++++-- Core/gb.h | 5 ++--- Core/memory.c | 5 +++-- Core/timing.c | 9 +++------ Core/z80_cpu.c | 4 ++++ 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/Core/display.c b/Core/display.c index c0f385f..3889717 100755 --- a/Core/display.c +++ b/Core/display.c @@ -305,6 +305,9 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) uint8_t vram_blocking_rush = gb->is_cgb? 0 : 4; for (; cycles; cycles -= atomic_increase) { + gb->io_registers[GB_IO_IF] |= gb->future_interrupts & 3; + gb->future_interrupts &= ~3; + bool previous_stat_interrupt_line = gb->stat_interrupt_line; gb->stat_interrupt_line = false; @@ -351,7 +354,12 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) else if (gb->display_cycles == LINES * LINE_LENGTH + stat_delay) { gb->io_registers[GB_IO_STAT] &= ~3; gb->io_registers[GB_IO_STAT] |= 1; - gb->io_registers[GB_IO_IF] |= 1; + if (gb->is_cgb) { + gb->future_interrupts |= 1; + } + else { + gb->io_registers[GB_IO_IF] |= 1; + } /* Entering VBlank state triggers the OAM interrupt. In CGB, it happens 4 cycles earlier */ if (gb->io_registers[GB_IO_STAT] & 0x20 && !gb->is_cgb) { @@ -573,7 +581,12 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) } if (gb->stat_interrupt_line && !previous_stat_interrupt_line) { - gb->io_registers[GB_IO_IF] |= 2; + if (gb->is_cgb) { + gb->future_interrupts |= 2; + } + else { + gb->io_registers[GB_IO_IF] |= 2; + } } } diff --git a/Core/gb.h b/Core/gb.h index c18bf30..37dada4 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -332,9 +332,8 @@ struct GB_gameboy_internal_s { GB_PADDING(uint16_t, serial_cycles); uint16_t serial_cycles; /* This field changed its meaning in v0.10 */ uint16_t serial_length; - bool dont_delay_timer_interrupt; /* If the timer glitch causes a TIMA overflow, it causes the timer to overflow - with different timing, so the triggered interrupt is not delayed. - Todo: needs test ROM. */ + uint8_t future_interrupts; /* Interrupts can occur in any T-cycle. Some timings result in different interrupt + timing when the CPU is in halt mode, and might also affect the DI instruction. */ ); /* APU */ diff --git a/Core/memory.c b/Core/memory.c index d8f7df7..4fbd1f1 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -136,7 +136,7 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr) if (addr < 0xFF80) { switch (addr & 0xFF) { case GB_IO_IF: - return gb->io_registers[GB_IO_IF] | 0xE0; + return gb->io_registers[GB_IO_IF] | 0xE0 | gb->future_interrupts; case GB_IO_TAC: return gb->io_registers[GB_IO_TAC] | 0xF8; case GB_IO_STAT: @@ -416,8 +416,9 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) case GB_IO_WX: GB_window_related_write(gb, addr & 0xFF, value); break; - case GB_IO_SCX: case GB_IO_IF: + gb->future_interrupts = 0; + case GB_IO_SCX: case GB_IO_SCY: case GB_IO_LYC: case GB_IO_BGP: diff --git a/Core/timing.c b/Core/timing.c index e5ac788..9a96f59 100644 --- a/Core/timing.c +++ b/Core/timing.c @@ -82,14 +82,13 @@ static void GB_ir_run(GB_gameboy_t *gb) static void advance_tima_state_machine(GB_gameboy_t *gb) { + gb->io_registers[GB_IO_IF] |= gb->future_interrupts & 4; + gb->future_interrupts &= ~4; if (gb->tima_reload_state == GB_TIMA_RELOADED) { gb->tima_reload_state = GB_TIMA_RUNNING; } else if (gb->tima_reload_state == GB_TIMA_RELOADING) { - gb->io_registers[GB_IO_IF] |= 4; - if (!gb->dont_delay_timer_interrupt) { - // Todo - } + gb->future_interrupts |= 4; gb->tima_reload_state = GB_TIMA_RELOADED; } } @@ -157,7 +156,6 @@ static void increase_tima(GB_gameboy_t *gb) { gb->io_registers[GB_IO_TIMA]++; if (gb->io_registers[GB_IO_TIMA] == 0) { - gb->dont_delay_timer_interrupt = false; gb->io_registers[GB_IO_TIMA] = gb->io_registers[GB_IO_TMA]; gb->tima_reload_state = GB_TIMA_RELOADING; } @@ -197,7 +195,6 @@ void GB_emulate_timer_glitch(GB_gameboy_t *gb, uint8_t old_tac, uint8_t new_tac) /* And now either the timer must be disabled, or the new bit used for overflow testing be 0. */ if (!(new_tac & 4) || gb->div_cycles & (new_clocks >> 1)) { increase_tima(gb); - gb->dont_delay_timer_interrupt = true; } } } diff --git a/Core/z80_cpu.c b/Core/z80_cpu.c index ce30d55..878358d 100644 --- a/Core/z80_cpu.c +++ b/Core/z80_cpu.c @@ -1338,6 +1338,10 @@ void GB_cpu_run(GB_gameboy_t *gb) { gb->vblank_just_occured = false; uint8_t interrupt_queue = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F; + if (!gb->halted) { + interrupt_queue |= gb->future_interrupts & gb->interrupt_enable; + } + if (interrupt_queue) { gb->halted = false; From 026baddbab1f91ff2b5194d4fc8de72381c6dd7c Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sat, 9 Sep 2017 13:45:01 +0300 Subject: [PATCH 6/8] Implemented delayed/future interrupts for DMG hblank interrupt. Restores vblank_stat_intr-GS support. --- Core/display.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/display.c b/Core/display.c index 3889717..9ca6e4a 100755 --- a/Core/display.c +++ b/Core/display.c @@ -305,6 +305,7 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) uint8_t vram_blocking_rush = gb->is_cgb? 0 : 4; for (; cycles; cycles -= atomic_increase) { + bool dmg_future_stat = false; gb->io_registers[GB_IO_IF] |= gb->future_interrupts & 3; gb->future_interrupts &= ~3; @@ -561,6 +562,9 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) if (!gb->cgb_double_speed && just_entered_hblank && ((gb->effective_scx + (gb->first_scanline ? 2 : 0)) & 3) == 3) { gb->stat_interrupt_line = false; } + else if (just_entered_hblank && ((gb->effective_scx + (gb->first_scanline ? 2 : 0)) & 3) != 0) { + dmg_future_stat = true; + } break; case 1: gb->stat_interrupt_line = gb->io_registers[GB_IO_STAT] & 0x10; break; case 2: gb->stat_interrupt_line = gb->io_registers[GB_IO_STAT] & 0x20; break; @@ -569,6 +573,7 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) /* User requested a LY=LYC interrupt and the LY=LYC bit is on */ if ((gb->io_registers[GB_IO_STAT] & 0x44) == 0x44) { gb->stat_interrupt_line = true; + dmg_future_stat = false; } } @@ -581,7 +586,7 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) } if (gb->stat_interrupt_line && !previous_stat_interrupt_line) { - if (gb->is_cgb) { + if (gb->is_cgb || dmg_future_stat) { gb->future_interrupts |= 2; } else { From 02841ddde6cb12f5d5710dcb827d503236c9ea14 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sat, 9 Sep 2017 16:55:24 +0300 Subject: [PATCH 7/8] Whoops --- Core/display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/display.c b/Core/display.c index 9ca6e4a..fd502ec 100755 --- a/Core/display.c +++ b/Core/display.c @@ -294,10 +294,10 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) /* Todo: Is this correct for DMG mode CGB? */ uint8_t scx_delay = gb->effective_scx; if (gb->cgb_double_speed) { - scx_delay = (scx_delay + 1) & ~1; + scx_delay = (scx_delay + 1) & ~1 & 7; } else { - scx_delay = (scx_delay + (gb->first_scanline ? 2 : 0)) & ~3; + scx_delay = (scx_delay + (gb->first_scanline ? 2 : 0)) & ~3 & 7; } /* Todo: These are correct for DMG, DMG-mode CGB, and single speed CGB. Is is correct for double speed CGB? */ From 14f267b4fa4eb93c0c7c6298c2ada2c829710ee5 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sat, 9 Sep 2017 19:31:05 +0300 Subject: [PATCH 8/8] Another whoops --- Core/z80_cpu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/z80_cpu.c b/Core/z80_cpu.c index 878358d..e7b1b5c 100644 --- a/Core/z80_cpu.c +++ b/Core/z80_cpu.c @@ -1341,8 +1341,10 @@ void GB_cpu_run(GB_gameboy_t *gb) if (!gb->halted) { interrupt_queue |= gb->future_interrupts & gb->interrupt_enable; } - + gb->io_registers[GB_IO_IF] |= gb->future_interrupts; + gb->future_interrupts = 0; + if (interrupt_queue) { gb->halted = false; }