Correctly emulate speed switch timing

This commit is contained in:
Lior Halphon 2019-01-13 01:09:41 +02:00
parent c74b39e712
commit ba5c07bed9
3 changed files with 21 additions and 6 deletions

View File

@ -403,6 +403,7 @@ struct GB_gameboy_internal_s {
uint8_t tima_reload_state; /* After TIMA overflows, it becomes 0 for 4 cycles before actually reloading. */ uint8_t tima_reload_state; /* After TIMA overflows, it becomes 0 for 4 cycles before actually reloading. */
uint16_t serial_cycles; uint16_t serial_cycles;
uint16_t serial_length; uint16_t serial_length;
uint8_t double_speed_alignment;
); );
/* APU */ /* APU */

View File

@ -211,14 +211,27 @@ static void nop(GB_gameboy_t *gb, uint8_t opcode)
static void stop(GB_gameboy_t *gb, uint8_t opcode) static void stop(GB_gameboy_t *gb, uint8_t opcode)
{ {
if (gb->io_registers[GB_IO_KEY1] & 0x1) { if (gb->io_registers[GB_IO_KEY1] & 0x1) {
/* Make sure we don't leave display_cycles not divisble by 8 in single speed mode */ flush_pending_cycles(gb);
if (gb->display_cycles % 8 == 4) { bool needs_alignment = false;
cycle_no_access(gb);
GB_advance_cycles(gb, 0x4);
/* Make sure we keep the CPU ticks aligned correctly when returning from double speed mode */
if (gb->double_speed_alignment & 7) {
GB_advance_cycles(gb, 0x4);
needs_alignment = true;
} }
/* Todo: the switch is not instant. We should emulate this. */
gb->cgb_double_speed ^= true; gb->cgb_double_speed ^= true;
gb->io_registers[GB_IO_KEY1] = 0; gb->io_registers[GB_IO_KEY1] = 0;
for (unsigned i = 0x800; i--;) {
GB_advance_cycles(gb, 0x40);
}
if (!needs_alignment) {
GB_advance_cycles(gb, 0x4);
}
} }
else { else {
gb->stopped = true; gb->stopped = true;

View File

@ -193,6 +193,7 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
} }
// Not affected by speed boost // Not affected by speed boost
gb->double_speed_alignment += cycles;
gb->hdma_cycles += cycles; gb->hdma_cycles += cycles;
gb->apu_output.sample_cycles += cycles; gb->apu_output.sample_cycles += cycles;
gb->cycles_since_ir_change += cycles; gb->cycles_since_ir_change += cycles;