git.y1.nz

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.