Refined timer interrupt timing
This commit is contained in:
parent
cbbaf2ee84
commit
54eb51d8db
@ -332,6 +332,7 @@ struct GB_gameboy_internal_s {
|
|||||||
GB_PADDING(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_cycles; /* This field changed its meaning in v0.10 */
|
||||||
uint16_t serial_length;
|
uint16_t serial_length;
|
||||||
|
uint8_t delayed_interrupts; /* When an interrupt occurs while not aligned to a T-cycle, it must be "delayed" */
|
||||||
);
|
);
|
||||||
|
|
||||||
/* APU */
|
/* APU */
|
||||||
|
@ -82,10 +82,13 @@ static void GB_ir_run(GB_gameboy_t *gb)
|
|||||||
|
|
||||||
static void advance_tima_state_machine(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) {
|
if (gb->tima_reload_state == GB_TIMA_RELOADED) {
|
||||||
gb->tima_reload_state = GB_TIMA_RUNNING;
|
gb->tima_reload_state = GB_TIMA_RUNNING;
|
||||||
}
|
}
|
||||||
else if (gb->tima_reload_state == GB_TIMA_RELOADING) {
|
else if (gb->tima_reload_state == GB_TIMA_RELOADING) {
|
||||||
|
gb->io_registers[GB_IO_IF] |= 4;
|
||||||
|
gb->delayed_interrupts |= 4; // Timer interrupt is not aligned to a T-cycle and therefore is effective only the next one.
|
||||||
gb->tima_reload_state = GB_TIMA_RELOADED;
|
gb->tima_reload_state = GB_TIMA_RELOADED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,7 +157,6 @@ static void increase_tima(GB_gameboy_t *gb)
|
|||||||
gb->io_registers[GB_IO_TIMA]++;
|
gb->io_registers[GB_IO_TIMA]++;
|
||||||
if (gb->io_registers[GB_IO_TIMA] == 0) {
|
if (gb->io_registers[GB_IO_TIMA] == 0) {
|
||||||
gb->io_registers[GB_IO_TIMA] = gb->io_registers[GB_IO_TMA];
|
gb->io_registers[GB_IO_TIMA] = gb->io_registers[GB_IO_TMA];
|
||||||
gb->io_registers[GB_IO_IF] |= 4;
|
|
||||||
gb->tima_reload_state = GB_TIMA_RELOADING;
|
gb->tima_reload_state = GB_TIMA_RELOADING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1337,9 +1337,9 @@ static GB_opcode_t *opcodes[256] = {
|
|||||||
void GB_cpu_run(GB_gameboy_t *gb)
|
void GB_cpu_run(GB_gameboy_t *gb)
|
||||||
{
|
{
|
||||||
gb->vblank_just_occured = false;
|
gb->vblank_just_occured = false;
|
||||||
bool interrupt = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F;
|
uint8_t interrupt_queue = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F & ~gb->delayed_interrupts;
|
||||||
|
|
||||||
if (interrupt) {
|
if (interrupt_queue) {
|
||||||
gb->halted = false;
|
gb->halted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1354,9 +1354,8 @@ void GB_cpu_run(GB_gameboy_t *gb)
|
|||||||
gb->ime_toggle = false;
|
gb->ime_toggle = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (effecitve_ime && interrupt) {
|
if (effecitve_ime && interrupt_queue) {
|
||||||
uint8_t interrupt_bit = 0;
|
uint8_t interrupt_bit = 0;
|
||||||
uint8_t interrupt_queue = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F;
|
|
||||||
while (!(interrupt_queue & 1)) {
|
while (!(interrupt_queue & 1)) {
|
||||||
interrupt_queue >>= 1;
|
interrupt_queue >>= 1;
|
||||||
interrupt_bit++;
|
interrupt_bit++;
|
||||||
|
Loading…
Reference in New Issue
Block a user