diff --git a/examples/bg_demo.rs b/examples/bg_demo.rs index 3fa219f..553a15f 100644 --- a/examples/bg_demo.rs +++ b/examples/bg_demo.rs @@ -1,6 +1,16 @@ #![no_std] #![feature(start)] +use gba::{ + io::{ + background::{BackgroundControlSetting, BG0}, + display::{DisplayControlSetting, DISPCNT}, + }, + palram::index_palram_bg_4bpp, + video::tiled::{TextScreenblockEntry, Tile4bpp, VRAM_CHARBLOCKS, VRAM_TEXT_SCREENBLOCKS}, + Color, +}; + #[panic_handler] fn panic(_info: &core::panic::PanicInfo) -> ! { loop {} @@ -8,148 +18,54 @@ fn panic(_info: &core::panic::PanicInfo) -> ! { #[start] fn main(_argc: isize, _argv: *const *const u8) -> isize { + pub const WHITE: Color = Color::from_rgb(31, 31, 31); + pub const LIGHT_GRAY: Color = Color::from_rgb(25, 25, 25); + pub const DARK_GRAY: Color = Color::from_rgb(15, 15, 15); // bg palette - set_bg_palette_4bpp(0, 1, WHITE); - set_bg_palette_4bpp(0, 2, LIGHT_GRAY); - set_bg_palette_4bpp(0, 3, DARK_GRAY); + index_palram_bg_4bpp(0, 1).write(WHITE); + index_palram_bg_4bpp(0, 2).write(LIGHT_GRAY); + index_palram_bg_4bpp(0, 3).write(DARK_GRAY); // bg tiles set_bg_tile_4bpp(0, 0, ALL_TWOS); set_bg_tile_4bpp(0, 1, ALL_THREES); // screenblock - let light_entry = RegularScreenblockEntry::from_tile_id(0); - let dark_entry = RegularScreenblockEntry::from_tile_id(1); + let light_entry = TextScreenblockEntry::from_tile_index(0); + let dark_entry = TextScreenblockEntry::from_tile_index(1); checker_screenblock(8, light_entry, dark_entry); // bg0 control - unsafe { BG0CNT.write(BackgroundControlSetting::from_base_block(8)) }; + BG0::BG0CNT.write(BackgroundControlSetting::from_screen_base_block(8)); // Display Control - unsafe { DISPCNT.write(DisplayControlSetting::JUST_ENABLE_BG0) }; + DISPCNT.write(DisplayControlSetting::new().with_display_bg0(true)); loop { // TODO the whole thing } } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(transparent)] -pub struct VolatilePtr(pub *mut T); -impl VolatilePtr { - pub unsafe fn read(&self) -> T { - core::ptr::read_volatile(self.0) - } - pub unsafe fn write(&self, data: T) { - core::ptr::write_volatile(self.0, data); - } - pub fn offset(self, count: isize) -> Self { - VolatilePtr(self.0.wrapping_offset(count)) - } - pub fn cast(self) -> VolatilePtr { - VolatilePtr(self.0 as *mut Z) - } -} +pub const ALL_TWOS: Tile4bpp = Tile4bpp([ + 0x22222222, 0x22222222, 0x22222222, 0x22222222, 0x22222222, 0x22222222, 0x22222222, 0x22222222, +]); -pub const BACKGROUND_PALETTE: VolatilePtr = VolatilePtr(0x500_0000 as *mut u16); - -pub fn set_bg_palette_4bpp(palbank: usize, slot: usize, color: u16) { - assert!(palbank < 16); - assert!(slot > 0 && slot < 16); - unsafe { - BACKGROUND_PALETTE - .cast::<[u16; 16]>() - .offset(palbank as isize) - .cast::() - .offset(slot as isize) - .write(color); - } -} - -pub const fn rgb16(red: u16, green: u16, blue: u16) -> u16 { - blue << 10 | green << 5 | red -} - -pub const WHITE: u16 = rgb16(31, 31, 31); -pub const LIGHT_GRAY: u16 = rgb16(25, 25, 25); -pub const DARK_GRAY: u16 = rgb16(15, 15, 15); - -#[derive(Debug, Clone, Copy, Default)] -#[repr(transparent)] -pub struct Tile4bpp { - pub data: [u32; 8], -} - -pub const ALL_TWOS: Tile4bpp = Tile4bpp { - data: [ - 0x22222222, 0x22222222, 0x22222222, 0x22222222, 0x22222222, 0x22222222, 0x22222222, 0x22222222, - ], -}; - -pub const ALL_THREES: Tile4bpp = Tile4bpp { - data: [ - 0x33333333, 0x33333333, 0x33333333, 0x33333333, 0x33333333, 0x33333333, 0x33333333, 0x33333333, - ], -}; - -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct Charblock4bpp { - pub data: [Tile4bpp; 512], -} - -pub const VRAM: VolatilePtr = VolatilePtr(0x0600_0000 as *mut Charblock4bpp); +pub const ALL_THREES: Tile4bpp = Tile4bpp([ + 0x33333333, 0x33333333, 0x33333333, 0x33333333, 0x33333333, 0x33333333, 0x33333333, 0x33333333, +]); pub fn set_bg_tile_4bpp(charblock: usize, index: usize, tile: Tile4bpp) { assert!(charblock < 4); assert!(index < 512); - unsafe { VRAM.offset(charblock as isize).cast::().offset(index as isize).write(tile) } + unsafe { VRAM_CHARBLOCKS.index(charblock).cast::().offset(index as isize).write(tile) } } -#[derive(Debug, Clone, Copy, Default)] -#[repr(transparent)] -pub struct RegularScreenblockEntry(u16); - -impl RegularScreenblockEntry { - pub const SCREENBLOCK_ENTRY_TILE_ID_MASK: u16 = 0b11_1111_1111; - pub const fn from_tile_id(id: u16) -> Self { - RegularScreenblockEntry(id & Self::SCREENBLOCK_ENTRY_TILE_ID_MASK) - } -} - -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct RegularScreenblock { - pub data: [RegularScreenblockEntry; 32 * 32], -} - -pub fn checker_screenblock(slot: usize, a_entry: RegularScreenblockEntry, b_entry: RegularScreenblockEntry) { - let mut p = VRAM.cast::().offset(slot as isize).cast::(); +pub fn checker_screenblock(slot: usize, a_entry: TextScreenblockEntry, b_entry: TextScreenblockEntry) { + let mut p = unsafe { VRAM_TEXT_SCREENBLOCKS.index(slot).cast::() }; let mut checker = true; for _row in 0..32 { for _col in 0..32 { - unsafe { p.write(if checker { a_entry } else { b_entry }) }; - p = p.offset(1); + unsafe { + p.write(if checker { a_entry } else { b_entry }); + p = p.offset(1); + } checker = !checker; } checker = !checker; } } - -#[derive(Clone, Copy, Default, PartialEq, Eq)] -#[repr(transparent)] -pub struct BackgroundControlSetting(u16); - -impl BackgroundControlSetting { - pub const SCREEN_BASE_BLOCK_MASK: u16 = 0b1_1111; - pub const fn from_base_block(sbb: u16) -> Self { - BackgroundControlSetting((sbb & Self::SCREEN_BASE_BLOCK_MASK) << 8) - } -} - -pub const BG0CNT: VolatilePtr = VolatilePtr(0x400_0008 as *mut BackgroundControlSetting); - -#[derive(Clone, Copy, Default, PartialEq, Eq)] -#[repr(transparent)] -pub struct DisplayControlSetting(u16); - -impl DisplayControlSetting { - pub const JUST_ENABLE_BG0: DisplayControlSetting = DisplayControlSetting(1 << 8); -} - -pub const DISPCNT: VolatilePtr = VolatilePtr(0x0400_0000 as *mut DisplayControlSetting);