Skip to content

Instantly share code, notes, and snippets.

@felixjones
Last active March 20, 2019 13:52
Show Gist options
  • Save felixjones/ecb20db32097345e16133812b98c1ffc to your computer and use it in GitHub Desktop.
Save felixjones/ecb20db32097345e16133812b98c1ffc to your computer and use it in GitHub Desktop.
C++ clone of rust gba-console's irq.rs example
#include <gba.hpp>
#define EVER ;;
using namespace gba;
static constexpr color::bgr555 BLACK( 0, 0, 0 );
static constexpr color::bgr555 RED( 31, 0, 0 );
static constexpr color::bgr555 GREEN( 0, 31, 0 );
static constexpr color::bgr555 BLUE( 0, 0, 31 );
static constexpr color::bgr555 YELLOW( 31, 31, 0 );
static constexpr color::bgr555 PINK( 31, 0, 31 );
static void irq_handler( const irq::flags flags );
static void start_timers() {
constexpr auto timerSettings = clock::control().irq_on_tick( true );
clock::timer[0].start_tickrate( timerSettings.frequency( clock::cycles_1024 ), 64 );
clock::timer[1].start_tickrate( timerSettings.frequency( clock::cycles_64 ), 64 );
}
int main( int argc, char * argv[] ) {
display::control = display::mode( 3 ).enable_layers( { 2 } );
video::mode3.fill( BLACK );
// Set the IRQ handler to use.
// Enable all interrupts that are set in the IE register.
irq::interrupt.set_handler( irq_handler ).enable();
// Request that VBlank, HBlank and VCount will generate IRQs.
display::status = display::state().irq_on_vblank().irq_on_hblank().irq_on_vcount();
// Start two timers with overflow IRQ generation.
start_timers();
for ( EVER ) {
const auto this_frame_keys = io::keys.read_keys();
// The VBlank IRQ must be enabled at minimum, or else the CPU will halt
// at the call to vblank_interrupt_wait() as the VBlank IRQ will never
// be triggered.
auto flags = irq::vblank;
// Enable interrupts based on key input.
if ( this_frame_keys.button.A ) {
flags |= irq::hblank;
}
if ( this_frame_keys.button.B ) {
flags |= irq::vcount;
}
if ( this_frame_keys.button.L ) {
flags |= irq::timer[0];
}
if ( this_frame_keys.button.R ) {
flags |= irq::timer[1];
}
irq::interrupt.set( flags );
// Puts the CPU into low power mode until a VBlank IRQ is received. This
// will yield considerably better power efficiency as opposed to spin
// waiting.
bios::VBlankIntrWait();
}
}
static uint16 pixel = 0;
static void write_pixel( const color::bgr555& color ) {
video::mode3.get_pixel_address()[pixel] = color;
pixel = ( pixel + 1 ) % ( video::mode3.get_width() * video::mode3.get_height() );
}
void vblank_handler() {
write_pixel( BLUE );
}
void hblank_handler() {
write_pixel( GREEN );
}
void vcount_handler() {
write_pixel( RED );
}
void timer0_handler() {
write_pixel( YELLOW );
}
void timer1_handler() {
write_pixel( PINK );
}
void irq_handler( const irq::flags flags ) {
if ( flags.vblank() ) {
vblank_handler();
}
if ( flags.hblank() ) {
hblank_handler();
}
if ( flags.vcount() ) {
vcount_handler();
}
if ( flags.timer( 0 ) ) {
timer0_handler();
}
if ( flags.timer( 1 ) ) {
timer1_handler();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment