diff options
Diffstat (limited to 'src/common.h')
-rw-r--r-- | src/common.h | 133 |
1 files changed, 132 insertions, 1 deletions
diff --git a/src/common.h b/src/common.h index e3405be..dac48ad 100644 --- a/src/common.h +++ b/src/common.h | |||
@@ -46,6 +46,15 @@ | |||
46 | #define DISP_OBJ (1 << 12) | 46 | #define DISP_OBJ (1 << 12) |
47 | #define DISP_ENABLE_SPRITES DISP_OBJ | DISP_OBJ_1D | 47 | #define DISP_ENABLE_SPRITES DISP_OBJ | DISP_OBJ_1D |
48 | 48 | ||
49 | // These bits are used to control the DISP_STATUS register. | ||
50 | #define DISP_VBLANK_STATUS (1 << 0x0) | ||
51 | #define DISP_HBLANK_STATUS (1 << 0x1) | ||
52 | #define DISP_VCOUNT_STATUS (1 << 0x2) | ||
53 | #define DISP_VBLANK_IRQ (1 << 0x3) | ||
54 | #define DISP_HBLANK_IRQ (1 << 0x4) | ||
55 | #define DISP_VCOUNT_IRQ (1 << 0x5) | ||
56 | #define DISP_VCOUNT_TRIGGER(N) ((N) << 0x8) | ||
57 | |||
49 | // Registers to control of BG layers. | 58 | // Registers to control of BG layers. |
50 | #define BG_CTRL(N) *((vu16*)(0x04000008 + 0x0002 * (N))) | 59 | #define BG_CTRL(N) *((vu16*)(0x04000008 + 0x0002 * (N))) |
51 | 60 | ||
@@ -245,8 +254,14 @@ u32 profile_stop(void) { | |||
245 | // Input handling. | 254 | // Input handling. |
246 | // | 255 | // |
247 | 256 | ||
248 | // Memory address for key input register | 257 | // Memory address for key input and control register |
249 | #define KEY_INPUTS *((vu16*) 0x04000130) | 258 | #define KEY_INPUTS *((vu16*) 0x04000130) |
259 | #define KEY_CTRL *((vu16*) 0x04000132) | ||
260 | |||
261 | // Key control register bits. | ||
262 | #define KEY_IRQ_KEY(N) (N) | ||
263 | #define KEY_IRQ (1 << 0xE) | ||
264 | #define KEY_IRQ_IF_SET (1 << 0xF) | ||
250 | 265 | ||
251 | // Alias for key pressing bits. | 266 | // Alias for key pressing bits. |
252 | #define KEY_A (1 << 0) | 267 | #define KEY_A (1 << 0) |
@@ -385,4 +400,120 @@ dma_fill(void *dst, const void *src, u32 size, int channel) { | |||
385 | dma_transfer_fill(dst, src, size / 4, channel, DMA_CHUNK_32 | DMA_ENABLE); | 400 | dma_transfer_fill(dst, src, size / 4, channel, DMA_CHUNK_32 | DMA_ENABLE); |
386 | } | 401 | } |
387 | 402 | ||
403 | // | ||
404 | // Interrupts. | ||
405 | // | ||
406 | |||
407 | #define IRQ_ENABLE *((vu16*) 0x04000200) | ||
408 | #define IRQ_ACK *((vu16*) 0x04000202) | ||
409 | #define IRQ_CTRL *((vu16*) 0x04000208) | ||
410 | #define IRQ_ACK_BIOS *((vu16*) 0x03007FF8) | ||
411 | |||
412 | typedef enum { | ||
413 | IRQ_VBLANK, | ||
414 | IRQ_HBLANK, | ||
415 | IRQ_VCOUNT, | ||
416 | IRQ_TIMER_0, | ||
417 | IRQ_TIMER_1, | ||
418 | IRQ_TIMER_2, | ||
419 | IRQ_TIMER_3, | ||
420 | IRQ_SERIAL, | ||
421 | IRQ_DMA_0, | ||
422 | IRQ_DMA_1, | ||
423 | IRQ_DMA_2, | ||
424 | IRQ_DMA_3, | ||
425 | IRQ_KEYPAD, | ||
426 | IRQ_GAMEPAK, | ||
427 | } IrqIndex; | ||
428 | |||
429 | typedef void (*IrsFunc)(void); | ||
430 | |||
431 | IrsFunc irs_table[] = { | ||
432 | [IRQ_VBLANK ] = NULL, | ||
433 | [IRQ_HBLANK ] = NULL, | ||
434 | [IRQ_VCOUNT ] = NULL, | ||
435 | [IRQ_TIMER_0] = NULL, | ||
436 | [IRQ_TIMER_1] = NULL, | ||
437 | [IRQ_TIMER_2] = NULL, | ||
438 | [IRQ_TIMER_3] = NULL, | ||
439 | [IRQ_SERIAL ] = NULL, | ||
440 | [IRQ_DMA_0 ] = NULL, | ||
441 | [IRQ_DMA_1 ] = NULL, | ||
442 | [IRQ_DMA_2 ] = NULL, | ||
443 | [IRQ_DMA_3 ] = NULL, | ||
444 | [IRQ_KEYPAD ] = NULL, | ||
445 | [IRQ_GAMEPAK] = NULL, | ||
446 | }; | ||
447 | |||
448 | void | ||
449 | irq_enable(IrqIndex idx) { | ||
450 | switch (idx) { | ||
451 | case IRQ_VBLANK: { DISP_STATUS |= DISP_VBLANK_IRQ; } break; | ||
452 | case IRQ_HBLANK: { DISP_STATUS |= DISP_HBLANK_IRQ; } break; | ||
453 | case IRQ_VCOUNT: { DISP_STATUS |= DISP_VCOUNT_IRQ; } break; | ||
454 | case IRQ_TIMER_0: { TIMER_CTRL_0 |= TIMER_CTRL_IRQ; } break; | ||
455 | case IRQ_TIMER_1: { TIMER_CTRL_1 |= TIMER_CTRL_IRQ; } break; | ||
456 | case IRQ_TIMER_2: { TIMER_CTRL_2 |= TIMER_CTRL_IRQ; } break; | ||
457 | case IRQ_TIMER_3: { TIMER_CTRL_3 |= TIMER_CTRL_IRQ; } break; | ||
458 | case IRQ_SERIAL: { /* TODO: Set REG_SERIAL? */ } break; | ||
459 | case IRQ_DMA_0: { DMA_CTRL(0) |= DMA_IRQ; } break; | ||
460 | case IRQ_DMA_1: { DMA_CTRL(1) |= DMA_IRQ; } break; | ||
461 | case IRQ_DMA_2: { DMA_CTRL(2) |= DMA_IRQ; } break; | ||
462 | case IRQ_DMA_3: { DMA_CTRL(3) |= DMA_IRQ; } break; | ||
463 | case IRQ_KEYPAD: { KEY_CTRL |= KEY_IRQ; } break; | ||
464 | case IRQ_GAMEPAK: { /* Nothing to do here...*/ } break; | ||
465 | } | ||
466 | IRQ_ENABLE |= (1 << idx); | ||
467 | } | ||
468 | |||
469 | void | ||
470 | irq_disable(IrqIndex idx) { | ||
471 | switch (idx) { | ||
472 | case IRQ_VBLANK: { DISP_STATUS &= ~DISP_VBLANK_IRQ; } break; | ||
473 | case IRQ_HBLANK: { DISP_STATUS &= ~DISP_HBLANK_IRQ; } break; | ||
474 | case IRQ_VCOUNT: { DISP_STATUS &= ~DISP_VCOUNT_IRQ; } break; | ||
475 | case IRQ_TIMER_0: { TIMER_CTRL_0 &= ~TIMER_CTRL_IRQ; } break; | ||
476 | case IRQ_TIMER_1: { TIMER_CTRL_1 &= ~TIMER_CTRL_IRQ; } break; | ||
477 | case IRQ_TIMER_2: { TIMER_CTRL_2 &= ~TIMER_CTRL_IRQ; } break; | ||
478 | case IRQ_TIMER_3: { TIMER_CTRL_3 &= ~TIMER_CTRL_IRQ; } break; | ||
479 | case IRQ_SERIAL: { /* TODO: Set REG_SERIAL? */ } break; | ||
480 | case IRQ_DMA_0: { DMA_CTRL(0) &= ~DMA_IRQ; } break; | ||
481 | case IRQ_DMA_1: { DMA_CTRL(1) &= ~DMA_IRQ; } break; | ||
482 | case IRQ_DMA_2: { DMA_CTRL(2) &= ~DMA_IRQ; } break; | ||
483 | case IRQ_DMA_3: { DMA_CTRL(3) &= ~DMA_IRQ; } break; | ||
484 | case IRQ_KEYPAD: { KEY_CTRL &= ~KEY_IRQ; } break; | ||
485 | case IRQ_GAMEPAK: { /* Nothing to do here...*/ } break; | ||
486 | } | ||
487 | IRQ_ENABLE &= ~(1 << idx); | ||
488 | } | ||
489 | |||
490 | void | ||
491 | irs_set(IrqIndex idx, IrsFunc func) { | ||
492 | // Store IRQ_CTRL status and disable interrupts for now. | ||
493 | u16 irq_ctrl = IRQ_CTRL; | ||
494 | IRQ_CTRL = 0; | ||
495 | |||
496 | // Update the IRS table and enable/disable the given IRQ. | ||
497 | irs_table[idx] = func; | ||
498 | if (func == NULL) { | ||
499 | irq_disable(idx); | ||
500 | } else { | ||
501 | irq_enable(idx); | ||
502 | } | ||
503 | |||
504 | // Restore previous irq_ctrl. | ||
505 | IRQ_CTRL = irq_ctrl; | ||
506 | } | ||
507 | |||
508 | #define IRS_MAIN *(IrsFunc*)(0x03007FFC) | ||
509 | |||
510 | // External irs_main function, has to be written in ARM assembly. | ||
511 | void irs_main(void); | ||
512 | |||
513 | void | ||
514 | irq_init() { | ||
515 | IRS_MAIN = irs_main; | ||
516 | IRQ_CTRL = 1; | ||
517 | } | ||
518 | |||
388 | #endif // GBAEXP_COMMON_H | 519 | #endif // GBAEXP_COMMON_H |