Last active
March 20, 2019 13:52
-
-
Save felixjones/ecb20db32097345e16133812b98c1ffc to your computer and use it in GitHub Desktop.
C++ clone of rust gba-console's irq.rs example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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