diff --git a/cpu.c b/cpu.c index 2cef16b..a051d60 100644 --- a/cpu.c +++ b/cpu.c @@ -1573,14 +1573,11 @@ void set_cpu_mode(cpu_mode_type new_mode) reg[CPU_MODE] = new_mode; } -void raise_interrupt(irq_type irq_raised) +cpu_alert_type check_interrupts() { - // The specific IRQ must be enabled in IE, master IRQ enable must be on, - // and it must be on in the flags. - write_ioreg(REG_IF, read_ioreg(REG_IF) | irq_raised); - - if((read_ioreg(REG_IE) & irq_raised) && read_ioreg(REG_IME) && - ((reg[REG_CPSR] & 0x80) == 0)) + // Check any IRQ flag pending, IME and CPSR-IRQ enabled + u16 umirq = read_ioreg(REG_IE) & io_registers[REG_IF]; + if(!(reg[REG_CPSR] & 0x80) && read_ioreg(REG_IME) && umirq) { // Value after the FIQ returns, should be improved reg[REG_BUS_VALUE] = 0xe55ec002; @@ -1594,7 +1591,18 @@ void raise_interrupt(irq_type irq_raised) set_cpu_mode(MODE_IRQ); reg[CPU_HALT_STATE] = CPU_ACTIVE; reg[CHANGED_PC_STATUS] = 1; + return CPU_ALERT_IRQ; } + return CPU_ALERT_NONE; +} + +void raise_interrupt(irq_type irq_raised) +{ + // The specific IRQ must be enabled in IE, master IRQ enable must be on, + // and it must be on in the flags. + write_ioreg(REG_IF, read_ioreg(REG_IF) | irq_raised); + + check_interrupts(); } #ifndef HAVE_DYNAREC diff --git a/cpu.h b/cpu.h index 00aeddf..db2f2d2 100644 --- a/cpu.h +++ b/cpu.h @@ -110,6 +110,7 @@ typedef enum extern u32 instruction_count; void execute_arm(u32 cycles); +cpu_alert_type check_interrupts(void); void raise_interrupt(irq_type irq_raised); void set_cpu_mode(cpu_mode_type new_mode); diff --git a/gba_memory.c b/gba_memory.c index a51eebe..99ca684 100644 --- a/gba_memory.c +++ b/gba_memory.c @@ -1339,6 +1339,11 @@ cpu_alert_type function_cc write_io_register16(u32 address, u32 value) case 0x130: break; + // REG_IE + case 0x200: + write_ioreg(REG_IE, value); + return check_interrupts(); + // Interrupt flag case 0x202: write_ioreg(REG_IF, read_ioreg(REG_IF) & (~value)); @@ -1349,6 +1354,11 @@ cpu_alert_type function_cc write_io_register16(u32 address, u32 value) write_ioreg(REG_WAITCNT, value); break; + // REG_IME + case 0x208: + write_ioreg(REG_IME, value); + return check_interrupts(); + // Halt case 0x300: if(((value >> 8) & 0x01) == 0)