mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2026-10-25 00:02:16 +00:00
100 lines
2.4 KiB
C
100 lines
2.4 KiB
C
/*
|
|
Interrupts on Game Boy.
|
|
|
|
Three interrupts matter in most games: the VBlank at ~60 Hz, the
|
|
programmable timer, and the LCD status line (see raster.c). GBDK installs
|
|
a VBlank handler by default; add_VBL()/add_TIM() append your own handler
|
|
to an interrupt's chain, and remove_*() takes it back out.
|
|
|
|
This demo counts VBlanks and timer overflows in two handlers. The timer
|
|
runs at 65536 Hz, so with TMA=0 it overflows about 256 times a second,
|
|
much faster than the VBlank. Press START to remove both handlers, then
|
|
press it again to add them back.
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include "gb/types.h"
|
|
#include "gb/hardware.h"
|
|
#include "gb/gb.h"
|
|
#include "gbtext.h"
|
|
|
|
// interrupt counters (volatile: written by the handlers)
|
|
volatile uint8_t vbl_count;
|
|
volatile uint16_t tim_count;
|
|
uint8_t handlers_installed = 1;
|
|
|
|
// VBlank handler: called once per frame
|
|
void vbl_handler(void) NONBANKED {
|
|
vbl_count++;
|
|
}
|
|
|
|
// timer handler: called when TIMA_REG overflows
|
|
void tim_handler(void) NONBANKED {
|
|
tim_count++;
|
|
}
|
|
|
|
// write a zero-padded 5-digit decimal number to the tile map
|
|
static void put_u16(uint8_t x, uint8_t y, uint16_t v) {
|
|
char buf[6];
|
|
int8_t i;
|
|
buf[5] = '\0';
|
|
for (i = 4; i >= 0; i--) {
|
|
buf[i] = '0' + (v % 10);
|
|
v /= 10;
|
|
}
|
|
put_str(x, y, buf);
|
|
}
|
|
|
|
void main(void) {
|
|
uint8_t keys, last_keys = 0;
|
|
|
|
DISPLAY_OFF;
|
|
BGP_REG = OBP0_REG = OBP1_REG = 0xE4;
|
|
font_init();
|
|
|
|
put_str(4, 0, "INTERRUPTS");
|
|
put_str(2, 3, "VBLANK");
|
|
put_str(2, 4, "00000");
|
|
put_str(2, 7, "TIMER");
|
|
put_str(2, 8, "00000");
|
|
put_str(2, 12, "START: PAUSE");
|
|
|
|
// timer overflows every 256 ticks at 65536 Hz
|
|
TMA_REG = 0x00;
|
|
TAC_REG = 0x06;
|
|
|
|
// install our handlers and enable their interrupts
|
|
add_VBL(vbl_handler);
|
|
add_TIM(tim_handler);
|
|
set_interrupts(VBL_IFLAG | TIM_IFLAG);
|
|
|
|
SHOW_BKG;
|
|
DISPLAY_ON;
|
|
|
|
while (1) {
|
|
uint16_t t;
|
|
wait_vbl_done();
|
|
|
|
// edge-detect START to add/remove the handlers
|
|
keys = joypad();
|
|
if ((keys & J_START) && !(last_keys & J_START)) {
|
|
handlers_installed = !handlers_installed;
|
|
if (handlers_installed) {
|
|
add_VBL(vbl_handler);
|
|
add_TIM(tim_handler);
|
|
put_str(2, 12, "START: PAUSE");
|
|
} else {
|
|
remove_VBL(vbl_handler);
|
|
remove_TIM(tim_handler);
|
|
put_str(2, 12, "START: GO");
|
|
}
|
|
}
|
|
last_keys = keys;
|
|
|
|
// read the 16-bit timer count without a torn read
|
|
CRITICAL { t = tim_count; }
|
|
put_u16(2, 4, vbl_count);
|
|
put_u16(2, 8, t);
|
|
}
|
|
}
|