From 38de4e8f5a10afaeafc450cad2055a99915781cf Mon Sep 17 00:00:00 2001 From: Lokathor Date: Sun, 1 Jan 2023 00:20:11 -0700 Subject: [PATCH 1/6] outline the two checks from the `if` --- examples/game.rs | 56 ++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/examples/game.rs b/examples/game.rs index 93b0530..a8f5902 100644 --- a/examples/game.rs +++ b/examples/game.rs @@ -141,56 +141,56 @@ extern "C" fn main() -> ! { if keys.up() { let new_p = Position { x: player.x, y: player.y - 1 }; let new_r = Rect { x: new_p.x, y: new_p.y, w: 8, h: 8 }; - if new_r + let terrain_clear = new_r .iter_tiles() - .all(|(tx, ty)| allows_movement(world[ty as usize][tx as usize])) - && enemies.iter().all(|enemy| { - let enemy_r = Rect { x: enemy.x, y: enemy.y, w: 8, h: 8 }; - !new_r.intersect(enemy_r) - }) - { + .all(|(tx, ty)| allows_movement(world[ty as usize][tx as usize])); + let enemy_clear = enemies.iter().all(|enemy| { + let enemy_r = Rect { x: enemy.x, y: enemy.y, w: 8, h: 8 }; + !new_r.intersect(enemy_r) + }); + if terrain_clear && enemy_clear { *player = new_p; } } if keys.down() { let new_p = Position { x: player.x, y: player.y + 1 }; let new_r = Rect { x: new_p.x, y: new_p.y, w: 8, h: 8 }; - if new_r + let terrain_clear = new_r .iter_tiles() - .all(|(tx, ty)| allows_movement(world[ty as usize][tx as usize])) - && enemies.iter().all(|enemy| { - let enemy_r = Rect { x: enemy.x, y: enemy.y, w: 8, h: 8 }; - !new_r.intersect(enemy_r) - }) - { + .all(|(tx, ty)| allows_movement(world[ty as usize][tx as usize])); + let enemy_clear = enemies.iter().all(|enemy| { + let enemy_r = Rect { x: enemy.x, y: enemy.y, w: 8, h: 8 }; + !new_r.intersect(enemy_r) + }); + if terrain_clear && enemy_clear { *player = new_p; } } if keys.left() { let new_p = Position { x: player.x - 1, y: player.y }; let new_r = Rect { x: new_p.x, y: new_p.y, w: 8, h: 8 }; - if new_r + let terrain_clear = new_r .iter_tiles() - .all(|(tx, ty)| allows_movement(world[ty as usize][tx as usize])) - && enemies.iter().all(|enemy| { - let enemy_r = Rect { x: enemy.x, y: enemy.y, w: 8, h: 8 }; - !new_r.intersect(enemy_r) - }) - { + .all(|(tx, ty)| allows_movement(world[ty as usize][tx as usize])); + let enemy_clear = enemies.iter().all(|enemy| { + let enemy_r = Rect { x: enemy.x, y: enemy.y, w: 8, h: 8 }; + !new_r.intersect(enemy_r) + }); + if terrain_clear && enemy_clear { *player = new_p; } } if keys.right() { let new_p = Position { x: player.x + 1, y: player.y }; let new_r = Rect { x: new_p.x, y: new_p.y, w: 8, h: 8 }; - if new_r + let terrain_clear = new_r .iter_tiles() - .all(|(tx, ty)| allows_movement(world[ty as usize][tx as usize])) - && enemies.iter().all(|enemy| { - let enemy_r = Rect { x: enemy.x, y: enemy.y, w: 8, h: 8 }; - !new_r.intersect(enemy_r) - }) - { + .all(|(tx, ty)| allows_movement(world[ty as usize][tx as usize])); + let enemy_clear = enemies.iter().all(|enemy| { + let enemy_r = Rect { x: enemy.x, y: enemy.y, w: 8, h: 8 }; + !new_r.intersect(enemy_r) + }); + if terrain_clear && enemy_clear { *player = new_p; } } From 416f8a089cd7e441bc1c451eea6c419d759ab13e Mon Sep 17 00:00:00 2001 From: Lokathor Date: Sun, 1 Jan 2023 00:34:14 -0700 Subject: [PATCH 2/6] only print with debug asserts. --- examples/game.rs | 3 ++- examples/hello.rs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/game.rs b/examples/game.rs index a8f5902..a54da88 100644 --- a/examples/game.rs +++ b/examples/game.rs @@ -5,8 +5,9 @@ use gba::prelude::*; #[panic_handler] fn panic_handler(info: &core::panic::PanicInfo) -> ! { - use core::fmt::Write; + #[cfg(debug_assertions)] if let Ok(mut logger) = MgbaBufferedLogger::try_new(MgbaMessageLevel::Fatal) { + use core::fmt::Write; writeln!(logger, "{info}").ok(); } loop {} diff --git a/examples/hello.rs b/examples/hello.rs index 1a94d13..183b9d4 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -6,6 +6,7 @@ use gba::prelude::*; #[panic_handler] fn panic_handler(info: &core::panic::PanicInfo) -> ! { + #[cfg(debug_assertions)] if let Ok(mut logger) = MgbaBufferedLogger::try_new(MgbaMessageLevel::Fatal) { writeln!(logger, "{info}").ok(); } From be91260b33fddc27d7ad8e60d934bf1aaf3c8469 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Sun, 1 Jan 2023 18:01:23 -0700 Subject: [PATCH 3/6] palbank function --- src/mmio.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/mmio.rs b/src/mmio.rs index 6690c30..23a31d1 100644 --- a/src/mmio.rs +++ b/src/mmio.rs @@ -201,6 +201,19 @@ def_mmio!(0x0500_0000 = BACKDROP_COLOR: VolAddress; "Color th def_mmio!(0x0500_0000 = BG_PALETTE: VolBlock; "Background tile palette entries."); def_mmio!(0x0500_0200 = OBJ_PALETTE: VolBlock; "Object tile palette entries."); +#[inline] +#[must_use] +pub const fn bg_palbank(bank: usize) -> VolBlock { + let u = BG_PALETTE.index(bank * 16).as_usize(); + unsafe { VolBlock::new(u) } +} +#[inline] +#[must_use] +pub const fn obj_palbank(bank: usize) -> VolBlock { + let u = OBJ_PALETTE.index(bank * 16).as_usize(); + unsafe { VolBlock::new(u) } +} + // Video RAM (VRAM) /// The VRAM byte offset per screenblock index. From f9fe8b07f79df11cf276b1616590453d5be5c3d7 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Sun, 1 Jan 2023 18:04:00 -0700 Subject: [PATCH 4/6] track caller for palbank fns --- src/mmio.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mmio.rs b/src/mmio.rs index 23a31d1..3825dea 100644 --- a/src/mmio.rs +++ b/src/mmio.rs @@ -203,12 +203,14 @@ def_mmio!(0x0500_0200 = OBJ_PALETTE: VolBlock; "Object t #[inline] #[must_use] +#[cfg_attr(feature="track_caller", track_caller)] pub const fn bg_palbank(bank: usize) -> VolBlock { let u = BG_PALETTE.index(bank * 16).as_usize(); unsafe { VolBlock::new(u) } } #[inline] #[must_use] +#[cfg_attr(feature="track_caller", track_caller)] pub const fn obj_palbank(bank: usize) -> VolBlock { let u = OBJ_PALETTE.index(bank * 16).as_usize(); unsafe { VolBlock::new(u) } From c7ee6ba2ec3f37be251dd572106dc12464012102 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Sun, 1 Jan 2023 18:04:10 -0700 Subject: [PATCH 5/6] game updates --- examples/game.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/examples/game.rs b/examples/game.rs index a54da88..7ff67b7 100644 --- a/examples/game.rs +++ b/examples/game.rs @@ -26,7 +26,7 @@ struct Rect { h: u16, } impl Rect { - pub fn intersect(self, other: Self) -> bool { + fn intersect(self, other: Self) -> bool { self.x < other.x + other.w && self.x + self.w > other.x && self.y < other.y + other.h @@ -51,7 +51,7 @@ extern "C" fn main() -> ! { creatures[0].x = 11; creatures[0].y = 14; // - creatures[1].x = 41; + creatures[1].x = 44; creatures[1].y = 38; creatures[2].x = 100; creatures[2].y = 23; @@ -63,9 +63,9 @@ extern "C" fn main() -> ! { let mut world = [[0_u8; 32]; 32]; for i in 0..32 { world[0][i] = b'z'; - world[31][i] = b'z'; + world[19][i] = b'z'; world[i][0] = b'z'; - world[i][31] = b'z'; + world[i][29] = b'z'; } world[1][3] = b'B'; world[2][3] = b'G'; @@ -78,12 +78,14 @@ extern "C" fn main() -> ! { TIMER0_CONTROL.write(TimerControl::new().with_enabled(true)); + // bg BG_PALETTE.index(1).write(Color::MAGENTA); - OBJ_PALETTE.index(1).write(Color::CYAN); - OBJ_PALETTE.index(16 * 1 + 1).write(Color::GREEN); - OBJ_PALETTE.index(16 * 2 + 1).write(Color::RED); - OBJ_PALETTE.index(16 * 3 + 1).write(Color::BLUE); - OBJ_PALETTE.index(16 * 4 + 1).write(Color::YELLOW); + // obj + let colors = + [Color::CYAN, Color::GREEN, Color::RED, Color::BLUE, Color::YELLOW]; + for (pal, color) in colors.iter().enumerate() { + obj_palbank(pal).index(1).write(*color); + } Cga8x8Thick.bitunpack_4bpp(CHARBLOCK0_4BPP.as_region(), 0); Cga8x8Thick.bitunpack_4bpp(OBJ_TILES.as_region(), 0); From 2cd85c4b4d40b7a027f5d464d4b83a6a05189ad4 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Sun, 1 Jan 2023 18:44:48 -0700 Subject: [PATCH 6/6] name some glyphs --- examples/game.rs | 13 ++- src/builtin_art/cga_8x8_thick.rs | 152 ++++++++++++++++++++----------- 2 files changed, 110 insertions(+), 55 deletions(-) diff --git a/examples/game.rs b/examples/game.rs index 7ff67b7..6477baa 100644 --- a/examples/game.rs +++ b/examples/game.rs @@ -62,11 +62,16 @@ extern "C" fn main() -> ! { let mut world = [[0_u8; 32]; 32]; for i in 0..32 { - world[0][i] = b'z'; - world[19][i] = b'z'; - world[i][0] = b'z'; - world[i][29] = b'z'; + world[0][i] = Cga8x8Thick::BOX_HORIZONTAL; + world[19][i] = Cga8x8Thick::BOX_HORIZONTAL; + world[i][0] = Cga8x8Thick::BOX_VERTICAL; + world[i][29] = Cga8x8Thick::BOX_VERTICAL; } + world[0][0] = Cga8x8Thick::BOX_UPPER_LEFT; + world[0][29] = Cga8x8Thick::BOX_UPPER_RIGHT; + world[19][0] = Cga8x8Thick::BOX_LOWER_LEFT; + world[19][29] = Cga8x8Thick::BOX_LOWER_RIGHT; + // world[1][3] = b'B'; world[2][3] = b'G'; world[3][3] = b'0'; diff --git a/src/builtin_art/cga_8x8_thick.rs b/src/builtin_art/cga_8x8_thick.rs index 4e67d84..a6fbf89 100644 --- a/src/builtin_art/cga_8x8_thick.rs +++ b/src/builtin_art/cga_8x8_thick.rs @@ -7,6 +7,107 @@ use crate::{ video::{Tile4, Tile8}, }; +macro_rules! glyph { + ($name:ident = $id:expr) => { + pub const $name: u8 = $id; + }; +} + +#[derive(Debug, Clone, Copy)] +pub struct Cga8x8Thick; + +impl Cga8x8Thick { + // 0x0? + glyph!(NULL = 0x00); + glyph!(FACE = 0x01); + glyph!(FACE_INVERSE = 0x02); + glyph!(HEART = 0x03); + glyph!(DIAMOND = 0x04); + glyph!(CLUB = 0x05); + glyph!(SPADE = 0x06); + glyph!(BULLET = 0x07); + glyph!(BULLET_INVERSE = 0x08); + glyph!(CIRCLE = 0x09); + glyph!(CIRCLE_INVERSE = 0x0A); + glyph!(MALE = 0x0B); + glyph!(FEMALE = 0x0C); + glyph!(NOTE = 0x0D); + glyph!(NOTE_DOUBLE = 0x0E); + glyph!(SOLAR = 0x0F); + + // 0x1? + glyph!(POINTER_RIGHT = 0x10); + glyph!(POINTER_LEFT = 0x11); + glyph!(ARROW_UP_DOWN = 0x12); + glyph!(BANG_DOUBLE = 0x13); + glyph!(PARAGRAPH = 0x14); + glyph!(SECTION = 0x15); + glyph!(UNDERLINE_THICK = 0x16); + glyph!(ARROW_UP_DOWN_UNDERLINED = 0x17); + glyph!(ARROW_UP = 0x18); + glyph!(ARROW_DOWN = 0x19); + glyph!(ARROW_RIGHT = 0x1A); + glyph!(ARROW_LEFT = 0x1B); + glyph!(RIGHT_ANGLE = 0x1C); + glyph!(ARROW_LEFT_RIGHT = 0x1D); + glyph!(POINTER_UP = 0x1E); + glyph!(POINTER_DOWN = 0x1F); + + // Box drawing + glyph!(BOX_VERTICAL = 0xB3); + glyph!(BOX_HORIZONTAL = 0xC4); + glyph!(BOX_UPPER_RIGHT = 0xBF); + glyph!(BOX_UPPER_LEFT = 0xDA); + glyph!(BOX_LOWER_RIGHT = 0xD9); + glyph!(BOX_LOWER_LEFT = 0xC0); + + /// Bit unpacks the data (4bpp depth) to the location given. + /// + /// * `offset_and_touch_zero`: Works like the [`BitUnpackInfo`] field. By + /// default you should usually pass 0 here. + /// + /// ## Panics + /// * Requires at least 256 elements of space within the region. + #[inline] + pub fn bitunpack_4bpp( + self, b: VolRegion, offset_and_touch_zero: u32, + ) { + assert!(b.len() >= 256); + let src = CGA_8X8_THICK.as_ptr(); + let dest = b.index(0).as_usize() as *mut u32; + let info = BitUnpackInfo { + src_byte_len: size_of_val(&CGA_8X8_THICK) as u16, + src_elem_width: 1, + dest_elem_width: 4, + offset_and_touch_zero, + }; + unsafe { BitUnPack(src.cast(), dest, &info) }; + } + + /// Bit unpacks the data (8bpp depth) to the location given. + /// + /// * `offset_and_touch_zero`: Works like the [`BitUnpackInfo`] field. By + /// default you should usually pass 0 here. + /// + /// ## Panics + /// * Requires at least 256 elements of space within the region. + #[inline] + pub fn bitunpack_8bpp( + self, b: VolRegion, offset_and_touch_zero: u32, + ) { + assert!(b.len() >= 256); + let src = CGA_8X8_THICK.as_ptr(); + let dest = b.index(0).as_usize() as *mut u32; + let info = BitUnpackInfo { + src_byte_len: size_of_val(&CGA_8X8_THICK) as u16, + src_elem_width: 1, + dest_elem_width: 8, + offset_and_touch_zero, + }; + unsafe { BitUnPack(src.cast(), dest, &info) }; + } +} + /// The CGA [Code Page 437][cp437] type face, with thick lines. /// /// There's 256 tiles, packed down to 1bpp. @@ -126,54 +227,3 @@ pub static CGA_8X8_THICK: [u32; 512] = [ 0x3636361E, 0x00000036, 0x060C180E, 0x0000001E, 0x3C3C0000, 0x00003C3C, 0x00000000, 0x00000000, ]; - -#[derive(Debug, Clone, Copy)] -pub struct Cga8x8Thick; - -impl Cga8x8Thick { - /// Bit unpacks the data (4bpp depth) to the location given. - /// - /// * `offset_and_touch_zero`: Works like the [`BitUnpackInfo`] field. By - /// default you should usually pass 0 here. - /// - /// ## Panics - /// * Requires at least 256 elements of space within the region. - #[inline] - pub fn bitunpack_4bpp( - self, b: VolRegion, offset_and_touch_zero: u32, - ) { - assert!(b.len() >= 256); - let src = CGA_8X8_THICK.as_ptr(); - let dest = b.index(0).as_usize() as *mut u32; - let info = BitUnpackInfo { - src_byte_len: size_of_val(&CGA_8X8_THICK) as u16, - src_elem_width: 1, - dest_elem_width: 4, - offset_and_touch_zero, - }; - unsafe { BitUnPack(src.cast(), dest, &info) }; - } - - /// Bit unpacks the data (8bpp depth) to the location given. - /// - /// * `offset_and_touch_zero`: Works like the [`BitUnpackInfo`] field. By - /// default you should usually pass 0 here. - /// - /// ## Panics - /// * Requires at least 256 elements of space within the region. - #[inline] - pub fn bitunpack_8bpp( - self, b: VolRegion, offset_and_touch_zero: u32, - ) { - assert!(b.len() >= 256); - let src = CGA_8X8_THICK.as_ptr(); - let dest = b.index(0).as_usize() as *mut u32; - let info = BitUnpackInfo { - src_byte_len: size_of_val(&CGA_8X8_THICK) as u16, - src_elem_width: 1, - dest_elem_width: 8, - offset_and_touch_zero, - }; - unsafe { BitUnPack(src.cast(), dest, &info) }; - } -}