#![feature(start)] #![no_std] #[cfg(not(test))] #[panic_handler] fn panic(_info: &core::panic::PanicInfo) -> ! { loop {} } #[start] fn main(_argc: isize, _argv: *const *const u8) -> isize { unsafe { DISPCNT.write_volatile(MODE3 | BG2); mode3_pixel(120, 80, rgb16(31, 0, 0)); mode3_pixel(136, 80, rgb16(0, 31, 0)); mode3_pixel(120, 96, rgb16(0, 0, 31)); loop {} } } pub const DISPCNT: *mut u16 = 0x04000000 as *mut u16; pub const MODE3: u16 = 3; pub const BG2: u16 = 0b100_0000_0000; pub const VRAM: usize = 0x06000000; pub const SCREEN_WIDTH: isize = 240; pub const fn rgb16(red: u16, green: u16, blue: u16) -> u16 { blue << 10 | green << 5 | red } pub unsafe fn mode3_pixel(col: isize, row: isize, color: u16) { (VRAM as *mut u16).offset(col + row * SCREEN_WIDTH).write_volatile(color); } pub const KEYINPUT: *mut u16 = 0x400_0130 as *mut u16; /// A newtype over the key input state of the GBA. #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] #[repr(transparent)] pub struct KeyInputSetting(u16); /// A "tribool" value helps us interpret the arrow pad. #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] #[repr(i32)] pub enum TriBool { Minus = -1, Neutral = 0, Plus = 1, } pub fn read_key_input() -> KeyInputSetting { unsafe { KeyInputSetting(KEYINPUT.volatile_read() ^ 0b1111_1111_1111_1111) } } pub const KEY_A: u16 = 1 << 0; pub const KEY_B: u16 = 1 << 1; pub const KEY_SELECT: u16 = 1 << 2; pub const KEY_START: u16 = 1 << 3; pub const KEY_RIGHT: u16 = 1 << 4; pub const KEY_LEFT: u16 = 1 << 5; pub const KEY_UP: u16 = 1 << 6; pub const KEY_DOWN: u16 = 1 << 7; pub const KEY_R: u16 = 1 << 8; pub const KEY_L: u16 = 1 << 9; impl KeyInputSetting { pub fn contains(&self, key: u16) -> bool { (self.0 & key) != 0 } pub fn difference(&self, other: KeyInputSetting) -> KeyInputSetting { KeyInputSetting(self.0 ^ other.0) } pub fn column_direction(&self) -> TriBool { if self.contains(KEY_RIGHT) { TriBool::Plus } else if self.contains(KEY_LEFT) { TriBool::Minus } else { TriBool::Neutral } } pub fn row_direction(&self) -> TriBool { if self.contains(KEY_DOWN) { TriBool::Plus } else if self.contains(KEY_UP) { TriBool::Minus } else { TriBool::Neutral } } }