#include "gba.h" IrsFunc irs_table[] = { [IRQ_VBLANK ] = NULL, [IRQ_HBLANK ] = NULL, [IRQ_VCOUNT ] = NULL, [IRQ_TIMER_0] = NULL, [IRQ_TIMER_1] = NULL, [IRQ_TIMER_2] = NULL, [IRQ_TIMER_3] = NULL, [IRQ_SERIAL ] = NULL, [IRQ_DMA_0 ] = NULL, [IRQ_DMA_1 ] = NULL, [IRQ_DMA_2 ] = NULL, [IRQ_DMA_3 ] = NULL, [IRQ_KEYPAD ] = NULL, [IRQ_GAMEPAK] = NULL, }; // External irs_main function, has to be written in ARM assembly. void irs_main(void); #define IRS_MAIN *(IrsFunc*)(0x03007FFC) void irq_enable(IrqIndex idx) { switch (idx) { case IRQ_VBLANK: { DISP_STATUS |= DISP_VBLANK_IRQ; } break; case IRQ_HBLANK: { DISP_STATUS |= DISP_HBLANK_IRQ; } break; case IRQ_VCOUNT: { DISP_STATUS |= DISP_VCOUNT_IRQ; } break; case IRQ_TIMER_0: { TIMER_CTRL_0 |= TIMER_CTRL_IRQ; } break; case IRQ_TIMER_1: { TIMER_CTRL_1 |= TIMER_CTRL_IRQ; } break; case IRQ_TIMER_2: { TIMER_CTRL_2 |= TIMER_CTRL_IRQ; } break; case IRQ_TIMER_3: { TIMER_CTRL_3 |= TIMER_CTRL_IRQ; } break; case IRQ_SERIAL: { /* TODO: Set REG_SERIAL? */ } break; case IRQ_DMA_0: { DMA_CTRL(0) |= DMA_IRQ; } break; case IRQ_DMA_1: { DMA_CTRL(1) |= DMA_IRQ; } break; case IRQ_DMA_2: { DMA_CTRL(2) |= DMA_IRQ; } break; case IRQ_DMA_3: { DMA_CTRL(3) |= DMA_IRQ; } break; case IRQ_KEYPAD: { KEY_CTRL |= KEY_IRQ; } break; case IRQ_GAMEPAK: { /* Nothing to do here...*/ } break; } IRQ_ENABLE |= (1 << idx); } void irq_disable(IrqIndex idx) { switch (idx) { case IRQ_VBLANK: { DISP_STATUS &= ~DISP_VBLANK_IRQ; } break; case IRQ_HBLANK: { DISP_STATUS &= ~DISP_HBLANK_IRQ; } break; case IRQ_VCOUNT: { DISP_STATUS &= ~DISP_VCOUNT_IRQ; } break; case IRQ_TIMER_0: { TIMER_CTRL_0 &= ~TIMER_CTRL_IRQ; } break; case IRQ_TIMER_1: { TIMER_CTRL_1 &= ~TIMER_CTRL_IRQ; } break; case IRQ_TIMER_2: { TIMER_CTRL_2 &= ~TIMER_CTRL_IRQ; } break; case IRQ_TIMER_3: { TIMER_CTRL_3 &= ~TIMER_CTRL_IRQ; } break; case IRQ_SERIAL: { /* TODO: Set REG_SERIAL? */ } break; case IRQ_DMA_0: { DMA_CTRL(0) &= ~DMA_IRQ; } break; case IRQ_DMA_1: { DMA_CTRL(1) &= ~DMA_IRQ; } break; case IRQ_DMA_2: { DMA_CTRL(2) &= ~DMA_IRQ; } break; case IRQ_DMA_3: { DMA_CTRL(3) &= ~DMA_IRQ; } break; case IRQ_KEYPAD: { KEY_CTRL &= ~KEY_IRQ; } break; case IRQ_GAMEPAK: { /* Nothing to do here...*/ } break; } IRQ_ENABLE &= ~(1 << idx); } void irs_set(IrqIndex idx, IrsFunc func) { // Store IRQ_CTRL status and disable interrupts for now. u16 irq_ctrl = IRQ_CTRL; IRQ_CTRL = 0; // Update the IRS table and enable/disable the given IRQ. irs_table[idx] = func; if (func == NULL) { irq_disable(idx); } else { irq_enable(idx); } // Restore previous irq_ctrl. IRQ_CTRL = irq_ctrl; } void irq_init(void) { IRS_MAIN = irs_main; IRQ_CTRL = 1; } void irs_stub(void) {}