gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
gbdk-lib/examples/cross-platform/irq/src/irq.c
1 #include <gbdk/platform.h>
2 #include <gbdk/console.h>
3
4 #include <stdint.h>
5 #include <stdio.h>
6 #include <string.h>
7
8 // counters are 16-bit so we need a mutual exclusion access
9 unsigned int vbl_cnt, tim_cnt;
10
11 void vbl(void)
12 {
13 // Upon IRQ, interrupts are automatically disabled
14 vbl_cnt++;
15 }
16
17 #if defined(NINTENDO_NES)
18 // For NES make sure to wrap TIM interrupt handlers with the nooverlay pragma.
19 // This avoids interrupts accidentally overwriting variables in the overlay segment that were being used when the NMI occurred.
20 #pragma save
21 #pragma nooverlay
22 #endif
23 void tim(void)
24 {
25 // Upon IRQ, interrupts are automatically disabled
26 tim_cnt++;
27 }
28 #if defined(NINTENDO_NES)
29 #pragma restore
30 #endif
31
32 void print_counter(void)
33 {
34 unsigned int cnt;
35
36 // Ensure mutual exclusion
37 CRITICAL {
38 cnt = tim_cnt;
39 }
40
41 printf(" TIM %u", cnt);
42 gotoxy(9, posy());
43
44 // Ensure mutual exclusion
45 CRITICAL {
46 cnt = vbl_cnt;
47 }
48
49 printf("- VBL %u\n", cnt);
50 }
51
52 void main(void)
53 {
54 uint8_t double_speed_mode = 0;
55 #if defined(NINTENDO)
56 set_default_palette();
57 if (_cpu == CGB_TYPE) {
58 // Use double-speed mode for GBC
59 cpu_fast();
60 double_speed_mode = 1;
61 }
62 #endif
63
64 #if defined(NINTENDO_NES)
65 // NES TIM emulation is based on GBC's double-speed mode
66 double_speed_mode = 1;
67 #endif
68
69 // Ensure mutual exclusion
70 CRITICAL {
71 vbl_cnt = tim_cnt = 0;
72 add_VBL(vbl);
73 add_TIM(tim);
74 }
75
76 #if defined(NINTENDO) || defined(NINTENDO_NES)
77 // Set TMA to divide clock by 0x80 (0x100 for GBC)
78 TMA_REG = double_speed_mode ? 0x00U : 0x80;
79 // Set clock to 4096 Hertz (8192 Hertz for GBC)
80 TAC_REG = 0x04U;
81 #elif defined(SEGA)
82 TMA_REG = 0xFCU;
83 #endif
84
85 // Handle VBL and TIM interrupts
86 set_interrupts(VBL_IFLAG | TIM_IFLAG);
87
88 for(;;) {
89 uint8_t num_frames = (get_system() == SYSTEM_50HZ) ? 50 : 60;
90 print_counter();
91 // Loop for 1 second
92 for(int i = 0; i < num_frames; i++) {
93 vsync();
94 }
95 }
96 }
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.