Improved serial interrupt timing, fixes boot_sclk_align.

This commit is contained in:
Lior Halphon 2017-06-23 17:58:04 +03:00
parent 623f92378d
commit c4ccbd5cce
4 changed files with 14 additions and 9 deletions

View File

@ -479,6 +479,8 @@ void GB_reset(GB_gameboy_t *gb)
} }
gb->io_registers[GB_IO_OBP0] = gb->io_registers[GB_IO_OBP1] = 0xFF; gb->io_registers[GB_IO_OBP0] = gb->io_registers[GB_IO_OBP1] = 0xFF;
} }
/* The serial interrupt always occur on the 0xF8th cycle of every 0x100 cycle since boot. */
gb->serial_cycles = 0x100 - 0xF8;
gb->io_registers[GB_IO_SC] = 0x7E; gb->io_registers[GB_IO_SC] = 0x7E;
gb->magic = (uintptr_t)'SAME'; gb->magic = (uintptr_t)'SAME';
} }

View File

@ -329,7 +329,9 @@ struct GB_gameboy_internal_s {
uint32_t display_cycles; uint32_t display_cycles;
uint32_t div_cycles; uint32_t div_cycles;
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; GB_PADDING(uint16_t, serial_cycles);
uint16_t serial_cycles; /* This field changed its meaning in v0.10 */
uint16_t serial_length;
); );
/* APU */ /* APU */

View File

@ -617,13 +617,15 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
} }
gb->io_registers[GB_IO_SC] = value | (~0x83); gb->io_registers[GB_IO_SC] = value | (~0x83);
if ((value & 0x80) && (value & 0x1) ) { if ((value & 0x80) && (value & 0x1) ) {
gb->serial_cycles = gb->cgb_mode && (value & 2)? 128 : 4096; gb->serial_length = gb->cgb_mode && (value & 2)? 128 : 4096;
/* Todo: This is probably incorrect for CGB's faster clock mode. */
gb->serial_cycles &= 0xFF;
if (gb->serial_transfer_start_callback) { if (gb->serial_transfer_start_callback) {
gb->serial_transfer_start_callback(gb, gb->io_registers[GB_IO_SB]); gb->serial_transfer_start_callback(gb, gb->io_registers[GB_IO_SB]);
} }
} }
else { else {
gb->serial_cycles = 0; gb->serial_length = 0;
} }
return; return;

View File

@ -107,9 +107,11 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
} }
} }
if (gb->serial_cycles) { uint16_t previous_serial_cycles = gb->serial_cycles;
if (gb->serial_cycles <= cycles) { gb->serial_cycles += cycles;
gb->serial_cycles = 0; if (gb->serial_length) {
if ((gb->serial_cycles & gb->serial_length) != (previous_serial_cycles & gb->serial_length)) {
gb->serial_length = 0;
gb->io_registers[GB_IO_SC] &= ~0x80; gb->io_registers[GB_IO_SC] &= ~0x80;
/* TODO: Does SB "update" bit by bit? */ /* TODO: Does SB "update" bit by bit? */
if (gb->serial_transfer_end_callback) { if (gb->serial_transfer_end_callback) {
@ -121,9 +123,6 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
gb->io_registers[GB_IO_IF] |= 8; gb->io_registers[GB_IO_IF] |= 8;
} }
else {
gb->serial_cycles -= cycles;
}
} }
gb->debugger_ticks += cycles; gb->debugger_ticks += cycles;