From 5cfa64030aad7265b51e0b37e6b93a2f798df2f0 Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Wed, 30 Aug 2023 16:08:43 +0100 Subject: [PATCH 01/16] Generate the tileset directly --- agb-image-converter/src/rust_generator.rs | 9 ++++++++- agb/examples/affine_background.rs | 4 ++-- agb/examples/animated_background.rs | 6 +++--- agb/src/display/example_logo.rs | 6 +++--- agb/src/display/tile_data.rs | 6 +++--- agb/src/display/tiled/vram_manager.rs | 11 ++++++----- 6 files changed, 25 insertions(+), 17 deletions(-) diff --git a/agb-image-converter/src/rust_generator.rs b/agb-image-converter/src/rust_generator.rs index bd6f243c..4d8b4d5c 100644 --- a/agb-image-converter/src/rust_generator.rs +++ b/agb-image-converter/src/rust_generator.rs @@ -114,6 +114,11 @@ pub(crate) fn generate_code( }); let data = ByteString(&tile_data); + let tile_format = if assignment_offset.is_some() { + quote! { #crate_prefix::display::tiled::TileFormat::FourBpp } + } else { + quote! { #crate_prefix::display::tiled::TileFormat::EightBpp } + }; quote! { #[allow(non_upper_case_globals)] @@ -134,11 +139,13 @@ pub(crate) fn generate_code( &ALIGNED.bytes }; + const TILE_SET: #crate_prefix::display::tiled::TileSet = #crate_prefix::display::tiled::TileSet::new(TILE_DATA, #tile_format); + const TILE_SETTINGS: &[#crate_prefix::display::tiled::TileSetting] = &[ #(#tile_settings),* ]; - #crate_prefix::display::tile_data::TileData::new(TILE_DATA, TILE_SETTINGS) + #crate_prefix::display::tile_data::TileData::new(TILE_SET, TILE_SETTINGS) }; } } diff --git a/agb/examples/affine_background.rs b/agb/examples/affine_background.rs index a0bdd1ab..2f8d37ff 100644 --- a/agb/examples/affine_background.rs +++ b/agb/examples/affine_background.rs @@ -4,7 +4,7 @@ use agb::{ display::{ affine::AffineMatrixBackground, - tiled::{AffineBackgroundSize, TileFormat, TileSet, TiledMap}, + tiled::{AffineBackgroundSize, TiledMap}, Priority, }, fixnum::{num, Num}, @@ -18,7 +18,7 @@ fn main(mut gba: agb::Gba) -> ! { let (gfx, mut vram) = gba.display.video.tiled2(); let vblank = agb::interrupt::VBlank::get(); - let tileset = TileSet::new(affine_tiles::water_tiles.tiles, TileFormat::EightBpp); + let tileset = affine_tiles::water_tiles.tiles; vram.set_background_palettes(affine_tiles::PALETTES); diff --git a/agb/examples/animated_background.rs b/agb/examples/animated_background.rs index 398932b7..c3632390 100644 --- a/agb/examples/animated_background.rs +++ b/agb/examples/animated_background.rs @@ -3,7 +3,7 @@ use agb::{ display::{ - tiled::{RegularBackgroundSize, TileFormat, TileSet, TiledMap}, + tiled::{RegularBackgroundSize, TiledMap}, Priority, }, include_background_gfx, @@ -16,14 +16,14 @@ fn main(mut gba: agb::Gba) -> ! { let (gfx, mut vram) = gba.display.video.tiled0(); let vblank = agb::interrupt::VBlank::get(); - let tileset = TileSet::new(water_tiles::water_tiles.tiles, TileFormat::FourBpp); + let tileset = water_tiles::water_tiles.tiles; vram.set_background_palettes(water_tiles::PALETTES); let mut bg = gfx.background( Priority::P0, RegularBackgroundSize::Background32x32, - TileFormat::FourBpp, + tileset.format(), ); for y in 0..20u16 { diff --git a/agb/src/display/example_logo.rs b/agb/src/display/example_logo.rs index 5c008a29..e7374789 100644 --- a/agb/src/display/example_logo.rs +++ b/agb/src/display/example_logo.rs @@ -1,11 +1,11 @@ -use super::tiled::{RegularMap, TileFormat, TileSet, TiledMap, VRamManager}; +use super::tiled::{RegularMap, TiledMap, VRamManager}; crate::include_background_gfx!(crate, agb_logo, test_logo => deduplicate "gfx/test_logo.png"); pub fn display_logo(map: &mut RegularMap, vram: &mut VRamManager) { vram.set_background_palettes(agb_logo::PALETTES); - let background_tilemap = TileSet::new(agb_logo::test_logo.tiles, TileFormat::FourBpp); + let background_tilemap = agb_logo::test_logo.tiles; for y in 0..20 { for x in 0..30 { @@ -37,7 +37,7 @@ mod tests { let mut map = gfx.background( Priority::P0, RegularBackgroundSize::Background32x32, - TileFormat::FourBpp, + agb_logo::test_logo.tiles.format(), ); display_logo(&mut map, &mut vram); diff --git a/agb/src/display/tile_data.rs b/agb/src/display/tile_data.rs index c1193417..0e01397d 100644 --- a/agb/src/display/tile_data.rs +++ b/agb/src/display/tile_data.rs @@ -1,14 +1,14 @@ -use super::tiled::TileSetting; +use super::tiled::{TileSet, TileSetting}; #[non_exhaustive] pub struct TileData { - pub tiles: &'static [u8], + pub tiles: TileSet<'static>, pub tile_settings: &'static [TileSetting], } impl TileData { #[must_use] - pub const fn new(tiles: &'static [u8], tile_settings: &'static [TileSetting]) -> Self { + pub const fn new(tiles: TileSet<'static>, tile_settings: &'static [TileSetting]) -> Self { TileData { tiles, tile_settings, diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs index d98c968d..e14b259e 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -49,17 +49,18 @@ pub struct TileSet<'a> { impl<'a> TileSet<'a> { #[must_use] - pub fn new(tiles: &'a [u8], format: TileFormat) -> Self { + pub const fn new(tiles: &'a [u8], format: TileFormat) -> Self { Self { tiles, format } } + #[must_use] + pub const fn format(&self) -> TileFormat { + self.format + } + fn reference(&self) -> NonNull<[u8]> { self.tiles.into() } - - pub(crate) fn format(&self) -> TileFormat { - self.format - } } #[derive(Debug, Clone, Copy)] From 6853d36a9cbe0b76ade86795c8d1ac99f0d34c51 Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Wed, 30 Aug 2023 16:14:51 +0100 Subject: [PATCH 02/16] Dynamic tile can also return the setting directly --- agb/examples/dynamic_tiles.rs | 4 ++-- agb/examples/mixer_32768.rs | 6 ++---- agb/examples/stereo_sound.rs | 6 ++---- agb/examples/text_render.rs | 4 ++-- agb/src/display/font.rs | 6 +++--- agb/src/display/tiled/vram_manager.rs | 8 ++++++-- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/agb/examples/dynamic_tiles.rs b/agb/examples/dynamic_tiles.rs index aaa284b1..4871638b 100644 --- a/agb/examples/dynamic_tiles.rs +++ b/agb/examples/dynamic_tiles.rs @@ -3,7 +3,7 @@ use agb::display::{ palette16::Palette16, - tiled::{RegularBackgroundSize, TileFormat, TileSetting, TiledMap}, + tiled::{RegularBackgroundSize, TileFormat, TiledMap}, Priority, }; @@ -42,7 +42,7 @@ fn main(mut gba: agb::Gba) -> ! { &mut vram, (x as u16, y as u16).into(), &dynamic_tile.tile_set(), - TileSetting::from_raw(dynamic_tile.tile_index()), + dynamic_tile.tile_setting(), ); vram.remove_dynamic_tile(dynamic_tile); diff --git a/agb/examples/mixer_32768.rs b/agb/examples/mixer_32768.rs index b1ac9fc2..5ab57941 100644 --- a/agb/examples/mixer_32768.rs +++ b/agb/examples/mixer_32768.rs @@ -3,9 +3,7 @@ use agb::{ display::{ - tiled::{ - RegularBackgroundSize, RegularMap, TileFormat, TileSetting, TiledMap, VRamManager, - }, + tiled::{RegularBackgroundSize, RegularMap, TileFormat, TiledMap, VRamManager}, Font, Priority, }, include_font, include_wav, @@ -110,7 +108,7 @@ fn init_background(bg: &mut RegularMap, vram: &mut VRamManager) { vram, (x, y).into(), &background_tile.tile_set(), - TileSetting::from_raw(background_tile.tile_index()), + background_tile.tile_setting(), ); } } diff --git a/agb/examples/stereo_sound.rs b/agb/examples/stereo_sound.rs index c6ccc27b..23ed339c 100644 --- a/agb/examples/stereo_sound.rs +++ b/agb/examples/stereo_sound.rs @@ -3,9 +3,7 @@ use agb::{ display::{ - tiled::{ - RegularBackgroundSize, RegularMap, TileFormat, TileSetting, TiledMap, VRamManager, - }, + tiled::{RegularBackgroundSize, RegularMap, TileFormat, TiledMap, VRamManager}, Font, Priority, }, include_font, include_wav, @@ -98,7 +96,7 @@ fn init_background(bg: &mut RegularMap, vram: &mut VRamManager) { vram, (x, y).into(), &background_tile.tile_set(), - TileSetting::from_raw(background_tile.tile_index()), + background_tile.tile_setting(), ); } } diff --git a/agb/examples/text_render.rs b/agb/examples/text_render.rs index 4f0afa18..0d86a4b4 100644 --- a/agb/examples/text_render.rs +++ b/agb/examples/text_render.rs @@ -3,7 +3,7 @@ use agb::{ display::{ - tiled::{RegularBackgroundSize, TileFormat, TileSetting, TiledMap}, + tiled::{RegularBackgroundSize, TileFormat, TiledMap}, Font, Priority, }, include_font, @@ -37,7 +37,7 @@ fn main(mut gba: agb::Gba) -> ! { &mut vram, (x, y).into(), &background_tile.tile_set(), - TileSetting::from_raw(background_tile.tile_index()), + background_tile.tile_setting(), ); } } diff --git a/agb/src/display/font.rs b/agb/src/display/font.rs index e37a77a2..e70e66e0 100644 --- a/agb/src/display/font.rs +++ b/agb/src/display/font.rs @@ -3,7 +3,7 @@ use core::fmt::{Error, Write}; use crate::fixnum::Vector2D; use crate::hash_map::HashMap; -use super::tiled::{DynamicTile, RegularMap, TileSetting, VRamManager}; +use super::tiled::{DynamicTile, RegularMap, VRamManager}; /// The text renderer renders a variable width fixed size /// bitmap font using dynamic tiles as a rendering surface. @@ -230,7 +230,7 @@ impl<'a, 'b> TextRenderer<'b> { vram_manager, (self.tile_pos.x + *x as u16, self.tile_pos.y + *y as u16).into(), &tile.tile_set(), - TileSetting::from_raw(tile.tile_index()), + tile.tile_setting(), ); } } @@ -294,7 +294,7 @@ mod tests { &mut vram, (x, y).into(), &background_tile.tile_set(), - TileSetting::from_raw(background_tile.tile_index()), + background_tile.tile_setting(), ); } } diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs index e14b259e..3d8c04aa 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -10,6 +10,8 @@ use crate::{ memory_mapped::MemoryMapped1DArray, }; +use super::TileSetting; + const TILE_RAM_START: usize = 0x0600_0000; const PALETTE_BACKGROUND: MemoryMapped1DArray = @@ -189,9 +191,11 @@ impl DynamicTile<'_> { } #[must_use] - pub fn tile_index(&self) -> u16 { + pub fn tile_setting(&self) -> TileSetting { let difference = self.tile_data.as_ptr() as usize - TILE_RAM_START; - (difference / TileFormat::FourBpp.tile_size()) as u16 + let tile_id = (difference / TileFormat::FourBpp.tile_size()) as u16; + + TileSetting::new(tile_id, false, false, 0) } } From f0ddfc96b4a213fbe481af4367e75e05ad489731 Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Wed, 30 Aug 2023 16:18:08 +0100 Subject: [PATCH 03/16] Reference the TRANSPARENT_TILE_INDEX in the definition of BLANK --- agb/src/display/tiled/map.rs | 2 +- agb/src/display/tiled/mod.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/agb/src/display/tiled/map.rs b/agb/src/display/tiled/map.rs index 367f111b..b2a83013 100644 --- a/agb/src/display/tiled/map.rs +++ b/agb/src/display/tiled/map.rs @@ -128,7 +128,7 @@ pub struct RegularMap { tiles_dirty: bool, } -pub const TRANSPARENT_TILE_INDEX: u16 = (1 << 10) - 1; +pub(crate) const TRANSPARENT_TILE_INDEX: u16 = (1 << 10) - 1; impl TiledMapTypes for RegularMap { type Size = RegularBackgroundSize; diff --git a/agb/src/display/tiled/mod.rs b/agb/src/display/tiled/mod.rs index 7c289a3f..e9f20881 100644 --- a/agb/src/display/tiled/mod.rs +++ b/agb/src/display/tiled/mod.rs @@ -16,6 +16,8 @@ pub use tiled1::Tiled1; pub use tiled2::Tiled2; pub use vram_manager::{DynamicTile, TileFormat, TileIndex, TileSet, VRamManager}; +use map::TRANSPARENT_TILE_INDEX; + // affine layers start at BG2 pub(crate) const AFFINE_BG_ID_OFFSET: usize = 2; @@ -165,7 +167,7 @@ impl Tile { pub struct TileSetting(u16); impl TileSetting { - pub const BLANK: Self = TileSetting::new(1023, false, false, 0); + pub const BLANK: Self = TileSetting::new(TRANSPARENT_TILE_INDEX, false, false, 0); #[must_use] pub const fn new(tile_id: u16, hflip: bool, vflip: bool, palette_id: u8) -> Self { From 3a1f8ed8ed08216efadc11d60379fec9883b86cd Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Wed, 30 Aug 2023 16:22:55 +0100 Subject: [PATCH 04/16] Add a convienence fill_with method --- agb/src/display/example_logo.rs | 15 +-------------- agb/src/display/tiled/map.rs | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/agb/src/display/example_logo.rs b/agb/src/display/example_logo.rs index e7374789..ba92c2ad 100644 --- a/agb/src/display/example_logo.rs +++ b/agb/src/display/example_logo.rs @@ -5,20 +5,7 @@ crate::include_background_gfx!(crate, agb_logo, test_logo => deduplicate "gfx/te pub fn display_logo(map: &mut RegularMap, vram: &mut VRamManager) { vram.set_background_palettes(agb_logo::PALETTES); - let background_tilemap = agb_logo::test_logo.tiles; - - for y in 0..20 { - for x in 0..30 { - let tile_id = y * 30 + x; - - map.set_tile( - vram, - (x as u16, y as u16).into(), - &background_tilemap, - agb_logo::test_logo.tile_settings[tile_id], - ); - } - } + map.fill_with(vram, &agb_logo::test_logo); map.commit(vram); map.show(); diff --git a/agb/src/display/tiled/map.rs b/agb/src/display/tiled/map.rs index b2a83013..48ca05f5 100644 --- a/agb/src/display/tiled/map.rs +++ b/agb/src/display/tiled/map.rs @@ -3,6 +3,7 @@ use core::ops::{Deref, DerefMut}; use crate::bitarray::Bitarray; use crate::display::affine::AffineMatrixBackground; +use crate::display::tile_data::TileData; use crate::display::{Priority, DISPLAY_CONTROL}; use crate::dma::dma_copy16; use crate::fixnum::Vector2D; @@ -188,6 +189,25 @@ impl RegularMap { } } + pub fn fill_with(&mut self, vram: &mut VRamManager, tile_data: &TileData) { + assert!( + tile_data.tile_settings.len() >= 20 * 30, + "Don't have a full screen's worth of tile data" + ); + + for y in 0..20u16 { + for x in 0..30u16 { + let tile_id = y * 30 + x; + self.set_tile( + vram, + (x, y).into(), + &tile_data.tiles, + tile_data.tile_settings[tile_id as usize], + ); + } + } + } + pub fn set_tile( &mut self, vram: &mut VRamManager, From 11fe4d92acbede732ac75b4541abcc2c0f99f638 Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Wed, 30 Aug 2023 16:25:16 +0100 Subject: [PATCH 05/16] Delete the old toml file --- agb/examples/water_tiles.toml | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 agb/examples/water_tiles.toml diff --git a/agb/examples/water_tiles.toml b/agb/examples/water_tiles.toml deleted file mode 100644 index 9981e521..00000000 --- a/agb/examples/water_tiles.toml +++ /dev/null @@ -1,5 +0,0 @@ -version = "1.0" - -[image.water_tiles] -filename = "water_tiles.png" -tile_size = "8x8" \ No newline at end of file From dc0478566924648cb396f32ebe82047630f839c5 Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Wed, 30 Aug 2023 16:46:05 +0100 Subject: [PATCH 06/16] Fix doc examples --- .../display/tiled/infinite_scrolled_map.rs | 30 +++++++++---------- agb/src/lib.rs | 4 +-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/agb/src/display/tiled/infinite_scrolled_map.rs b/agb/src/display/tiled/infinite_scrolled_map.rs index 8b637a85..fa1c9e96 100644 --- a/agb/src/display/tiled/infinite_scrolled_map.rs +++ b/agb/src/display/tiled/infinite_scrolled_map.rs @@ -44,25 +44,23 @@ use crate::{ /// # 0, 1, 2]; /// pub const WIDTH: i32 = // set it to some width /// # 12; -/// pub const MAP_TILES: &[u8] = &[ // probably load this from a file -/// # 0]; /// } /// +/// agb::include_background_gfx!(water_tiles, tiles => "examples/water_tiles.png"); +/// /// # fn foo(mut gba: agb::Gba) { /// let (gfx, mut vram) = gba.display.video.tiled0(); /// -/// let tileset = TileSet::new(&tilemap::MAP_TILES, TileFormat::FourBpp); +/// let tileset = water_tiles::tiles.tiles; /// /// let mut backdrop = InfiniteScrolledMap::new( /// gfx.background(Priority::P2, RegularBackgroundSize::Background32x32, TileFormat::FourBpp), /// Box::new(|pos| { /// ( /// &tileset, -/// TileSetting::from_raw( -/// *tilemap::BACKGROUND_MAP +/// water_tiles.tile_settings[*tilemap::BACKGROUND_MAP /// .get((pos.x + tilemap::WIDTH * pos.y) as usize) -/// .unwrap_or(&0), -/// ), +/// .unwrap_or(&0)] /// ) /// }), /// ); @@ -140,21 +138,22 @@ impl<'a> InfiniteScrolledMap<'a> { /// # pub const MAP_TILES: &[u8] = &[0]; /// # } /// # + /// # agb::include_background_gfx!(water_tiles, tiles => "examples/water_tiles.png"); + /// # /// # fn foo(mut gba: agb::Gba) { /// # let (gfx, mut vram) = gba.display.video.tiled0(); /// # - /// # let tileset = TileSet::new(&tilemap::MAP_TILES, TileFormat::FourBpp); + /// # let tileset = water_tiles.tiles; /// # /// # let mut backdrop = InfiniteScrolledMap::new( /// # gfx.background(Priority::P2, RegularBackgroundSize::Background32x32, TileFormat::FourBpp), /// # Box::new(|pos| { /// # ( /// # &tileset, - /// # TileSetting::from_raw( + /// # tileset.tile_settings[ /// # *tilemap::BACKGROUND_MAP /// # .get((pos.x + tilemap::WIDTH * pos.y) as usize) - /// # .unwrap_or(&0), - /// # ), + /// # .unwrap_or(&0)] /// # ) /// # }), /// # ); @@ -215,21 +214,22 @@ impl<'a> InfiniteScrolledMap<'a> { /// # pub const MAP_TILES: &[u8] = &[0]; /// # } /// # + /// # agb::include_background_gfx!(water_tiles, tiles => "examples/water_tiles.png"); + /// # /// # fn foo(mut gba: agb::Gba) { /// # let (gfx, mut vram) = gba.display.video.tiled0(); /// # - /// # let tileset = TileSet::new(&tilemap::MAP_TILES, TileFormat::FourBpp); + /// # let tileset = water_tiles.tiles; /// # /// # let mut backdrop = InfiniteScrolledMap::new( /// # gfx.background(Priority::P2, RegularBackgroundSize::Background32x32, TileFormat::FourBpp), /// # Box::new(|pos| { /// # ( /// # &tileset, - /// # TileSetting::from_raw( + /// # tileset.tile_settings[ /// # *tilemap::BACKGROUND_MAP /// # .get((pos.x + tilemap::WIDTH * pos.y) as usize) - /// # .unwrap_or(&0), - /// # ), + /// # .unwrap_or(&0)] /// # ) /// # }), /// # ); diff --git a/agb/src/lib.rs b/agb/src/lib.rs index cd4762f6..73963fcc 100644 --- a/agb/src/lib.rs +++ b/agb/src/lib.rs @@ -77,11 +77,11 @@ /// agb::include_background_gfx!(water_tiles, tiles => "examples/water_tiles.png"); /// /// # fn load_tileset(mut gfx: Tiled0, mut vram: VRamManager) { -/// let tileset = TileSet::new(water_tiles::tiles.tiles, TileFormat::FourBpp); +/// let tileset = water_tiles::tiles.tiles; /// /// vram.set_background_palettes(water_tiles::PALETTES); /// -/// let mut bg = gfx.background(Priority::P0, RegularBackgroundSize::Background32x32, TileFormat::FourBpp); +/// let mut bg = gfx.background(Priority::P0, RegularBackgroundSize::Background32x32, tileset.format()); /// /// for y in 0..20u16 { /// for x in 0..30u16 { From 2c556f9ce893615538a8c268eb429bac2c286e72 Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Wed, 30 Aug 2023 17:02:06 +0100 Subject: [PATCH 07/16] Fix docs for real this time --- .../display/tiled/infinite_scrolled_map.rs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/agb/src/display/tiled/infinite_scrolled_map.rs b/agb/src/display/tiled/infinite_scrolled_map.rs index fa1c9e96..c9b76d4a 100644 --- a/agb/src/display/tiled/infinite_scrolled_map.rs +++ b/agb/src/display/tiled/infinite_scrolled_map.rs @@ -40,7 +40,7 @@ use crate::{ /// use agb::display::Priority; /// /// mod tilemap { -/// pub const BACKGROUND_MAP: &[u16] = &[ // Probably load this from a file +/// pub const BACKGROUND_MAP: &[usize] = &[ // Probably load this from a file /// # 0, 1, 2]; /// pub const WIDTH: i32 = // set it to some width /// # 12; @@ -51,14 +51,14 @@ use crate::{ /// # fn foo(mut gba: agb::Gba) { /// let (gfx, mut vram) = gba.display.video.tiled0(); /// -/// let tileset = water_tiles::tiles.tiles; +/// let tile_data = water_tiles::tiles; /// /// let mut backdrop = InfiniteScrolledMap::new( /// gfx.background(Priority::P2, RegularBackgroundSize::Background32x32, TileFormat::FourBpp), /// Box::new(|pos| { /// ( -/// &tileset, -/// water_tiles.tile_settings[*tilemap::BACKGROUND_MAP +/// &tile_data.tiles, +/// tile_data.tile_settings[*tilemap::BACKGROUND_MAP /// .get((pos.x + tilemap::WIDTH * pos.y) as usize) /// .unwrap_or(&0)] /// ) @@ -133,7 +133,7 @@ impl<'a> InfiniteScrolledMap<'a> { /// # use agb::display::Priority; /// # /// # mod tilemap { - /// # pub const BACKGROUND_MAP: &[u16] = &[0, 1, 2]; + /// # pub const BACKGROUND_MAP: &[usize] = &[0, 1, 2]; /// # pub const WIDTH: i32 = 12; /// # pub const MAP_TILES: &[u8] = &[0]; /// # } @@ -143,14 +143,14 @@ impl<'a> InfiniteScrolledMap<'a> { /// # fn foo(mut gba: agb::Gba) { /// # let (gfx, mut vram) = gba.display.video.tiled0(); /// # - /// # let tileset = water_tiles.tiles; + /// # let tile_data = water_tiles::tiles; /// # /// # let mut backdrop = InfiniteScrolledMap::new( /// # gfx.background(Priority::P2, RegularBackgroundSize::Background32x32, TileFormat::FourBpp), /// # Box::new(|pos| { /// # ( - /// # &tileset, - /// # tileset.tile_settings[ + /// # &tile_data.tiles, + /// # tile_data.tile_settings[ /// # *tilemap::BACKGROUND_MAP /// # .get((pos.x + tilemap::WIDTH * pos.y) as usize) /// # .unwrap_or(&0)] @@ -209,7 +209,7 @@ impl<'a> InfiniteScrolledMap<'a> { /// # use agb::display::Priority; /// # /// # mod tilemap { - /// # pub const BACKGROUND_MAP: &[u16] = &[0, 1, 2]; + /// # pub const BACKGROUND_MAP: &[usize] = &[0, 1, 2]; /// # pub const WIDTH: i32 = 12; /// # pub const MAP_TILES: &[u8] = &[0]; /// # } @@ -219,14 +219,14 @@ impl<'a> InfiniteScrolledMap<'a> { /// # fn foo(mut gba: agb::Gba) { /// # let (gfx, mut vram) = gba.display.video.tiled0(); /// # - /// # let tileset = water_tiles.tiles; + /// # let tile_data = water_tiles::tiles; /// # /// # let mut backdrop = InfiniteScrolledMap::new( /// # gfx.background(Priority::P2, RegularBackgroundSize::Background32x32, TileFormat::FourBpp), /// # Box::new(|pos| { /// # ( - /// # &tileset, - /// # tileset.tile_settings[ + /// # &tile_data.tiles, + /// # tile_data.tile_settings[ /// # *tilemap::BACKGROUND_MAP /// # .get((pos.x + tilemap::WIDTH * pos.y) as usize) /// # .unwrap_or(&0)] From 4642a74a0f8dac39f22943d5a952314bfcd46e76 Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Wed, 30 Aug 2023 17:07:14 +0100 Subject: [PATCH 08/16] Update the examples with the new tileset importing --- examples/combo/src/lib.rs | 24 +++----- examples/hyperspace-roll/src/background.rs | 60 +++++-------------- .../src/backgrounds.rs | 21 ++----- .../the-hat-chooses-the-wizard/src/lib.rs | 6 +- .../src/splash_screen.rs | 32 ++-------- examples/the-purple-night/src/lib.rs | 4 +- 6 files changed, 36 insertions(+), 111 deletions(-) diff --git a/examples/combo/src/lib.rs b/examples/combo/src/lib.rs index 33a63a14..05528f39 100644 --- a/examples/combo/src/lib.rs +++ b/examples/combo/src/lib.rs @@ -8,7 +8,7 @@ use alloc::boxed::Box; use agb::{ display::{ - tiled::{InfiniteScrolledMap, RegularBackgroundSize, TileFormat, TileSet}, + tiled::{InfiniteScrolledMap, RegularBackgroundSize, TileFormat}, Priority, }, fixnum::{Num, Vector2D}, @@ -63,20 +63,12 @@ fn get_game(gba: &mut agb::Gba) -> Game { let (tile, mut vram) = gba.display.video.tiled0(); - let hat = TileSet::new(games::hat.tiles, TileFormat::EightBpp); - let purple = TileSet::new(games::purple.tiles, TileFormat::EightBpp); - let hyperspace = TileSet::new(games::hyperspace.tiles, TileFormat::EightBpp); - let dungeon_puzzler = TileSet::new(games::dungeon_puzzler.tiles, TileFormat::EightBpp); - let amplitude = TileSet::new(games::amplitude.tiles, TileFormat::EightBpp); - - let tiles = [hat, purple, hyperspace, dungeon_puzzler, amplitude]; - - let tile_settings = &[ - games::hat.tile_settings, - games::purple.tile_settings, - games::hyperspace.tile_settings, - games::dungeon_puzzler.tile_settings, - games::amplitude.tile_settings, + let tiles = [ + games::hat, + games::purple, + games::hyperspace, + games::dungeon_puzzler, + games::amplitude, ]; vram.set_background_palettes(games::PALETTES); @@ -93,7 +85,7 @@ fn get_game(gba: &mut agb::Gba) -> Game { let game = (pos.x).rem_euclid(tiles.len() as i32 * 30) as usize / 30; let tile_id = (y * 30 + x) as usize; - (&tiles[game], tile_settings[game][tile_id]) + (&tiles[game].tiles, tiles[game].tile_settings[tile_id]) }), ); diff --git a/examples/hyperspace-roll/src/background.rs b/examples/hyperspace-roll/src/background.rs index fa0ea199..9b30c837 100644 --- a/examples/hyperspace-roll/src/background.rs +++ b/examples/hyperspace-roll/src/background.rs @@ -1,5 +1,5 @@ use agb::{ - display::tiled::{RegularMap, TileFormat, TileSet, TileSetting, TiledMap, VRamManager}, + display::tiled::{RegularMap, TileSet, TileSetting, TiledMap, VRamManager}, include_background_gfx, rng, }; @@ -23,10 +23,7 @@ pub(crate) fn load_help_text( help_text_line: u16, at_tile: (u16, u16), ) { - let help_tileset = TileSet::new( - backgrounds::help.tiles, - agb::display::tiled::TileFormat::FourBpp, - ); + let help_tiledata = backgrounds::help; for x in 0..16 { let tile_id = help_text_line * 16 + x; @@ -34,8 +31,8 @@ pub(crate) fn load_help_text( background.set_tile( vram, (x + at_tile.0, at_tile.1).into(), - &help_tileset, - backgrounds::help.tile_settings[tile_id as usize], + &help_tiledata.tiles, + help_tiledata.tile_settings[tile_id as usize], ) } } @@ -45,22 +42,10 @@ pub(crate) fn load_description( descriptions_map: &mut RegularMap, vram: &mut VRamManager, ) { - let (tileset, tile_settings) = if face_id < 10 { - ( - TileSet::new( - backgrounds::descriptions1.tiles, - agb::display::tiled::TileFormat::FourBpp, - ), - backgrounds::descriptions1.tile_settings, - ) + let description_data = if face_id < 10 { + backgrounds::descriptions1 } else { - ( - TileSet::new( - backgrounds::descriptions2.tiles, - agb::display::tiled::TileFormat::FourBpp, - ), - backgrounds::descriptions2.tile_settings, - ) + backgrounds::descriptions2 }; for y in 0..11 { @@ -69,8 +54,8 @@ pub(crate) fn load_description( descriptions_map.set_tile( vram, (x, y).into(), - &tileset, - tile_settings[tile_id as usize], + &description_data.tiles, + description_data.tile_settings[tile_id as usize], ) } } @@ -83,7 +68,7 @@ fn create_background_map(map: &mut RegularMap, vram: &mut VRamManager, stars_til let blank = rng::gen().rem_euclid(32) < 30; let tile_setting = if blank { - TileSetting::new((1 << 10) - 1, false, false, 0) + TileSetting::BLANK } else { let tile_id = rng::gen().rem_euclid(64) as u16; backgrounds::stars.tile_settings[tile_id as usize] @@ -99,26 +84,10 @@ fn create_background_map(map: &mut RegularMap, vram: &mut VRamManager, stars_til pub fn show_title_screen(background: &mut RegularMap, vram: &mut VRamManager, sfx: &mut Sfx) { background.set_scroll_pos((0i16, 0).into()); vram.set_background_palettes(backgrounds::PALETTES); - let tile_set = TileSet::new( - backgrounds::title.tiles, - agb::display::tiled::TileFormat::FourBpp, - ); + background.hide(); - for x in 0..30u16 { - for y in 0..20u16 { - let tile_id = y * 30 + x; - background.set_tile( - vram, - (x, y).into(), - &tile_set, - backgrounds::title.tile_settings[tile_id as usize], - ); - } - - sfx.frame(); - } - + background.fill_with(vram, &backgrounds::title); background.commit(vram); sfx.frame(); background.show(); @@ -138,9 +107,8 @@ impl<'a> StarBackground<'a> { background2: &'a mut RegularMap, vram: &'_ mut VRamManager, ) -> Self { - let stars_tileset = TileSet::new(backgrounds::stars.tiles, TileFormat::FourBpp); - create_background_map(background1, vram, &stars_tileset); - create_background_map(background2, vram, &stars_tileset); + create_background_map(background1, vram, &backgrounds::stars.tiles); + create_background_map(background2, vram, &backgrounds::stars.tiles); Self { background1, diff --git a/examples/the-dungeon-puzzlers-lament/src/backgrounds.rs b/examples/the-dungeon-puzzlers-lament/src/backgrounds.rs index 9d31a94e..a965c653 100644 --- a/examples/the-dungeon-puzzlers-lament/src/backgrounds.rs +++ b/examples/the-dungeon-puzzlers-lament/src/backgrounds.rs @@ -1,5 +1,5 @@ use agb::{ - display::tiled::{RegularMap, TileFormat, TileSet, VRamManager}, + display::tiled::{RegularMap, VRamManager}, include_background_gfx, }; @@ -19,7 +19,7 @@ pub fn load_palettes(vram_manager: &mut VRamManager) { } pub fn load_ui(map: &mut RegularMap, vram_manager: &mut VRamManager) { - let ui_tileset = TileSet::new(backgrounds::ui.tiles, TileFormat::FourBpp); + let ui_tileset = backgrounds::ui.tiles; for y in 0..20u16 { for x in 0..30u16 { @@ -38,7 +38,7 @@ pub fn load_level_background( ) { let level_map = &tilemaps::LEVELS_MAP[level_number]; - let level_tileset = TileSet::new(backgrounds::level.tiles, TileFormat::FourBpp); + let level_tileset = backgrounds::level.tiles; for y in 0..20u16 { for x in 0..22u16 { @@ -51,18 +51,5 @@ pub fn load_level_background( } pub fn load_ending_page(map: &mut RegularMap, vram_manager: &mut VRamManager) { - let ending_tileset = TileSet::new(backgrounds::ending.tiles, TileFormat::FourBpp); - - for y in 0..20u16 { - for x in 0..30u16 { - let tile_pos = y * 30 + x; - - map.set_tile( - vram_manager, - (x, y).into(), - &ending_tileset, - backgrounds::ending.tile_settings[tile_pos as usize], - ); - } - } + map.fill_with(vram_manager, &backgrounds::ending); } diff --git a/examples/the-hat-chooses-the-wizard/src/lib.rs b/examples/the-hat-chooses-the-wizard/src/lib.rs index 7dd67e99..f27a42c8 100644 --- a/examples/the-hat-chooses-the-wizard/src/lib.rs +++ b/examples/the-hat-chooses-the-wizard/src/lib.rs @@ -10,8 +10,8 @@ use agb::{ display::{ object::{Graphics, OamManaged, Object, Tag, TagMap}, tiled::{ - InfiniteScrolledMap, PartialUpdateStatus, RegularBackgroundSize, TileFormat, TileSet, - TiledMap, VRamManager, + InfiniteScrolledMap, PartialUpdateStatus, RegularBackgroundSize, TileFormat, TiledMap, + VRamManager, }, Priority, HEIGHT, WIDTH, }, @@ -793,7 +793,7 @@ pub fn main(mut agb: agb::Gba) -> ! { TileFormat::FourBpp, ); - let tileset = TileSet::new(tile_sheet::background.tiles, TileFormat::FourBpp); + let tileset = tile_sheet::background.tiles; for y in 0..32u16 { for x in 0..32u16 { diff --git a/examples/the-hat-chooses-the-wizard/src/splash_screen.rs b/examples/the-hat-chooses-the-wizard/src/splash_screen.rs index 2c13a1ac..a6d739bf 100644 --- a/examples/the-hat-chooses-the-wizard/src/splash_screen.rs +++ b/examples/the-hat-chooses-the-wizard/src/splash_screen.rs @@ -1,5 +1,5 @@ use super::sfx::SfxPlayer; -use agb::display::tiled::{RegularMap, TileFormat, TileSet, TiledMap, VRamManager}; +use agb::display::tiled::{RegularMap, TiledMap, VRamManager}; agb::include_background_gfx!(splash_screens, splash => deduplicate "gfx/splash.png", @@ -18,19 +18,9 @@ pub fn show_splash_screen( vram: &mut VRamManager, ) { map.set_scroll_pos((0i16, 0i16).into()); - let (tileset, settings) = match which { - SplashScreen::Start => ( - TileSet::new(splash_screens::splash.tiles, TileFormat::FourBpp), - splash_screens::splash.tile_settings, - ), - - SplashScreen::End => ( - TileSet::new( - splash_screens::thanks_for_playing.tiles, - TileFormat::FourBpp, - ), - splash_screens::thanks_for_playing.tile_settings, - ), + let tile_data = match which { + SplashScreen::Start => splash_screens::splash, + SplashScreen::End => splash_screens::thanks_for_playing, }; let vblank = agb::interrupt::VBlank::get(); @@ -40,19 +30,7 @@ pub fn show_splash_screen( sfx.frame(); vblank.wait_for_vblank(); - for y in 0..20u16 { - for x in 0..30u16 { - map.set_tile( - vram, - (x, y).into(), - &tileset, - settings[(y * 30 + x) as usize], - ); - } - - sfx.frame(); - vblank.wait_for_vblank(); - } + map.fill_with(vram, &tile_data); map.commit(vram); vram.set_background_palettes(splash_screens::PALETTES); diff --git a/examples/the-purple-night/src/lib.rs b/examples/the-purple-night/src/lib.rs index 65b75f45..4d664bb4 100644 --- a/examples/the-purple-night/src/lib.rs +++ b/examples/the-purple-night/src/lib.rs @@ -15,7 +15,7 @@ use alloc::{boxed::Box, vec::Vec}; use agb::{ display::{ object::{Graphics, OamManaged, Object, Sprite, Tag, TagMap}, - tiled::{InfiniteScrolledMap, RegularBackgroundSize, TileFormat, TileSet, VRamManager}, + tiled::{InfiniteScrolledMap, RegularBackgroundSize, TileFormat, VRamManager}, Priority, HEIGHT, WIDTH, }, fixnum::{num, FixedNum, Rect, Vector2D}, @@ -2191,7 +2191,7 @@ fn game_with_level(gba: &mut agb::Gba) { let (background, mut vram) = gba.display.video.tiled0(); vram.set_background_palettes(background::PALETTES); - let tileset = TileSet::new(background::background.tiles, TileFormat::FourBpp); + let tileset = background::background.tiles; let object = gba.display.object.get_managed(); loop { From d3c32ce35146e9be60720dca424905070496baf1 Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Thu, 31 Aug 2023 07:53:01 +0100 Subject: [PATCH 09/16] Minor optimisation for the show entire screen case --- agb/src/display/tiled/map.rs | 45 +++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/agb/src/display/tiled/map.rs b/agb/src/display/tiled/map.rs index 48ca05f5..84a52d0b 100644 --- a/agb/src/display/tiled/map.rs +++ b/agb/src/display/tiled/map.rs @@ -195,14 +195,23 @@ impl RegularMap { "Don't have a full screen's worth of tile data" ); - for y in 0..20u16 { - for x in 0..30u16 { + assert_eq!( + tile_data.tiles.format(), + self.colours(), + "Cannot set a {:?} colour tile on a {:?} colour background", + tile_data.tiles.format(), + self.colours() + ); + + for y in 0..20 { + for x in 0..30 { let tile_id = y * 30 + x; - self.set_tile( + let tile_pos = y * 32 + x; + self.set_tile_at_pos( vram, - (x, y).into(), + tile_pos, &tile_data.tiles, - tile_data.tile_settings[tile_id as usize], + tile_data.tile_settings[tile_id], ); } } @@ -215,20 +224,28 @@ impl RegularMap { tileset: &TileSet<'_>, tile_setting: TileSetting, ) { - let colours = self.colours(); - if tileset.format() != colours { - panic!( - "Cannot set a {:?} colour tile on a {:?} colour background", - tileset.format(), - colours - ); - } + assert_eq!( + tileset.format(), + self.colours(), + "Cannot set a {:?} colour tile on a {:?} colour background", + tileset.format(), + self.colours() + ); let pos = self.map_size().gba_offset(pos); + self.set_tile_at_pos(vram, pos, tileset, tile_setting); + } + fn set_tile_at_pos( + &mut self, + vram: &mut VRamManager, + pos: usize, + tileset: &TileSet<'_>, + tile_setting: TileSetting, + ) { let old_tile = self.tiles_mut()[pos]; if old_tile != Tile::default() { - vram.remove_tile(old_tile.tile_index(colours)); + vram.remove_tile(old_tile.tile_index(self.colours())); } let tile_index = tile_setting.index(); From 7431086b14781c82040059e78372c385ec74ce4e Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Thu, 31 Aug 2023 07:53:08 +0100 Subject: [PATCH 10/16] Try using memcpy4 for copying the tile data --- agb/src/agbabi/mod.rs | 8 ++++++++ agb/src/display/tiled/vram_manager.rs | 12 ++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/agb/src/agbabi/mod.rs b/agb/src/agbabi/mod.rs index a53823cf..1f3df5a1 100644 --- a/agb/src/agbabi/mod.rs +++ b/agb/src/agbabi/mod.rs @@ -4,6 +4,14 @@ global_asm!(include_str!("macros.inc")); global_asm!(include_str!("memcpy.s")); global_asm!(include_str!("memset.s")); +extern "C" { + fn __aeabi_memcpy4(dest: *mut u32, src: *const u32, n: usize); +} + +pub(crate) unsafe fn memcpy(dest: *mut u32, src: *const u32, n: usize) { + __aeabi_memcpy4(dest, src, n); +} + #[cfg(test)] mod test { mod memset { diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs index 3d8c04aa..8ef68717 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -4,6 +4,7 @@ use alloc::{slice, vec::Vec}; use crate::{ agb_alloc::{block_allocator::BlockAllocator, bump_allocator::StartEnd}, + agbabi, display::palette16, dma::dma_copy16, hash_map::{Entry, HashMap}, @@ -380,17 +381,12 @@ impl VRamManager { let tile_offset = (tile_id as usize) * tile_size; let tile_slice = &tile_set.tiles[tile_offset..(tile_offset + tile_size)]; - let tile_size_in_half_words = tile_slice.len() / 2; - + let tile_size = tile_slice.len(); let target_location = tile_reference.0.as_ptr() as *mut _; unsafe { - dma_copy16( - tile_slice.as_ptr() as *const u16, - target_location, - tile_size_in_half_words, - ); - }; + agbabi::memcpy(target_location, tile_slice.as_ptr() as *const _, tile_size); + } } /// Copies raw palettes to the background palette without any checks. From c04d674101ca0f11328d994d89ff4ee2fba7d036 Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Tue, 5 Sep 2023 23:24:53 +0100 Subject: [PATCH 11/16] Extend changelog entry to allow for tile set --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8931515e..e89a98a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Sound channel panning and volume options are now `Num` rather than `Num` for improved precision and sound quality. - Due to dependency changes, agb-gbafix is now released under MPL rather than GPL. -- `include_background_gfx!` now produces tile settings directly rather than palette assigments. +- `include_background_gfx!` now produces tile sets and tile settings directly. ### Fixed From e504b93fe35976506a6a4e5542d5b459d64c5b5a Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Tue, 5 Sep 2023 23:52:35 +0100 Subject: [PATCH 12/16] Write a custom tile copy command --- agb/src/agbabi/mod.rs | 8 -------- agb/src/display/tiled/tile_copy.s | 27 +++++++++++++++++++++++++++ agb/src/display/tiled/vram_manager.rs | 12 +++++++++--- agb/src/global_asm.rs | 1 + 4 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 agb/src/display/tiled/tile_copy.s diff --git a/agb/src/agbabi/mod.rs b/agb/src/agbabi/mod.rs index 1f3df5a1..a53823cf 100644 --- a/agb/src/agbabi/mod.rs +++ b/agb/src/agbabi/mod.rs @@ -4,14 +4,6 @@ global_asm!(include_str!("macros.inc")); global_asm!(include_str!("memcpy.s")); global_asm!(include_str!("memset.s")); -extern "C" { - fn __aeabi_memcpy4(dest: *mut u32, src: *const u32, n: usize); -} - -pub(crate) unsafe fn memcpy(dest: *mut u32, src: *const u32, n: usize) { - __aeabi_memcpy4(dest, src, n); -} - #[cfg(test)] mod test { mod memset { diff --git a/agb/src/display/tiled/tile_copy.s b/agb/src/display/tiled/tile_copy.s new file mode 100644 index 00000000..866c0af8 --- /dev/null +++ b/agb/src/display/tiled/tile_copy.s @@ -0,0 +1,27 @@ +agb_arm_func copy_tile_8bpp + @ Arguments + @ r0 - pointer to the image data beginning + @ r1 - pointer to the target in vram + push {{r4-r8}} + +.rept 2 + ldmia r0!, {{r2-r8, r12}} + stmia r1!, {{r2-r8, r12}} +.endr + + pop {{r4-r8}} + bx lr +agb_arm_end copy_tile_8bpp + +agb_arm_func copy_tile_4bpp + @ Arguments + @ r0 - pointer to the image data beginning + @ r1 - pointer to the target in vram + push {{r4-r8}} + + ldmia r0!, {{r2-r8, r12}} + stmia r1!, {{r2-r8, r12}} + + pop {{r4-r8}} + bx lr +agb_arm_end copy_tile_4bpp \ No newline at end of file diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs index 8ef68717..c2113983 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -4,7 +4,6 @@ use alloc::{slice, vec::Vec}; use crate::{ agb_alloc::{block_allocator::BlockAllocator, bump_allocator::StartEnd}, - agbabi, display::palette16, dma::dma_copy16, hash_map::{Entry, HashMap}, @@ -381,11 +380,13 @@ impl VRamManager { let tile_offset = (tile_id as usize) * tile_size; let tile_slice = &tile_set.tiles[tile_offset..(tile_offset + tile_size)]; - let tile_size = tile_slice.len(); let target_location = tile_reference.0.as_ptr() as *mut _; unsafe { - agbabi::memcpy(target_location, tile_slice.as_ptr() as *const _, tile_size); + match tile_set.format { + TileFormat::FourBpp => copy_tile_4bpp(tile_slice.as_ptr().cast(), target_location), + TileFormat::EightBpp => copy_tile_8bpp(tile_slice.as_ptr().cast(), target_location), + } } } @@ -409,3 +410,8 @@ impl VRamManager { } } } + +extern "C" { + fn copy_tile_4bpp(src: *const u32, dest: *mut u32); + fn copy_tile_8bpp(src: *const u32, dest: *mut u32); +} diff --git a/agb/src/global_asm.rs b/agb/src/global_asm.rs index b16f19b2..0af2e00e 100644 --- a/agb/src/global_asm.rs +++ b/agb/src/global_asm.rs @@ -6,3 +6,4 @@ global_asm!(include_str!("crt0.s")); global_asm!(include_str!("interrupt_handler.s")); global_asm!(include_str!("sound/mixer/mixer.s")); global_asm!(include_str!("save/asm_routines.s")); +global_asm!(include_str!("display/tiled/tile_copy.s")); From 77445b304f19c99fe77d7785ce78d8637b45e7eb Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Wed, 6 Sep 2023 00:21:27 +0100 Subject: [PATCH 13/16] Custom assembly as thumb --- agb-image-converter/src/rust_generator.rs | 2 +- agb/src/display/tiled/tile_copy.s | 27 ---------------- agb/src/display/tiled/vram_manager.rs | 38 +++++++++++++++-------- agb/src/global_asm.rs | 1 - 4 files changed, 26 insertions(+), 42 deletions(-) delete mode 100644 agb/src/display/tiled/tile_copy.s diff --git a/agb-image-converter/src/rust_generator.rs b/agb-image-converter/src/rust_generator.rs index 4d8b4d5c..a382580f 100644 --- a/agb-image-converter/src/rust_generator.rs +++ b/agb-image-converter/src/rust_generator.rs @@ -131,7 +131,7 @@ pub(crate) fn generate_code( pub bytes: Bytes, } - const ALIGNED: &AlignedAs = &AlignedAs { + const ALIGNED: &AlignedAs = &AlignedAs { _align: [], bytes: *#data, }; diff --git a/agb/src/display/tiled/tile_copy.s b/agb/src/display/tiled/tile_copy.s deleted file mode 100644 index 866c0af8..00000000 --- a/agb/src/display/tiled/tile_copy.s +++ /dev/null @@ -1,27 +0,0 @@ -agb_arm_func copy_tile_8bpp - @ Arguments - @ r0 - pointer to the image data beginning - @ r1 - pointer to the target in vram - push {{r4-r8}} - -.rept 2 - ldmia r0!, {{r2-r8, r12}} - stmia r1!, {{r2-r8, r12}} -.endr - - pop {{r4-r8}} - bx lr -agb_arm_end copy_tile_8bpp - -agb_arm_func copy_tile_4bpp - @ Arguments - @ r0 - pointer to the image data beginning - @ r1 - pointer to the target in vram - push {{r4-r8}} - - ldmia r0!, {{r2-r8, r12}} - stmia r1!, {{r2-r8, r12}} - - pop {{r4-r8}} - bx lr -agb_arm_end copy_tile_4bpp \ No newline at end of file diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs index c2113983..b92e00de 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -29,9 +29,10 @@ const fn layout_of(format: TileFormat) -> Layout { } #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[repr(C)] pub enum TileFormat { - FourBpp, - EightBpp, + FourBpp = 0, + EightBpp = 1, } impl TileFormat { @@ -376,17 +377,33 @@ impl VRamManager { tile_id: u16, tile_reference: TileReference, ) { - let tile_size = tile_set.format.tile_size(); + let tile_format = tile_set.format; + let tile_size = tile_format.tile_size(); let tile_offset = (tile_id as usize) * tile_size; - let tile_slice = &tile_set.tiles[tile_offset..(tile_offset + tile_size)]; + let tile_data_start = unsafe { tile_set.tiles.as_ptr().add(tile_offset) }; let target_location = tile_reference.0.as_ptr() as *mut _; unsafe { - match tile_set.format { - TileFormat::FourBpp => copy_tile_4bpp(tile_slice.as_ptr().cast(), target_location), - TileFormat::EightBpp => copy_tile_8bpp(tile_slice.as_ptr().cast(), target_location), - } + core::arch::asm!( + "cmp r2, #0", + "beq 1f", + "ldmia r0!, {{r2-r5}}", + "stmia r1!, {{r2-r5}}", + "ldmia r0!, {{r2-r5}}", + "stmia r1!, {{r2-r5}}", + "1:", + "ldmia r0!, {{r2-r5}}", + "stmia r1!, {{r2-r5}}", + "ldmia r0!, {{r2-r5}}", + "stmia r1!, {{r2-r5}}", + inout("r0") tile_data_start => _, + inout("r1") target_location => _, + inout("r2") tile_format as u32 => _, + out("r3") _, + out("r4") _, + out("r5") _, + ); } } @@ -410,8 +427,3 @@ impl VRamManager { } } } - -extern "C" { - fn copy_tile_4bpp(src: *const u32, dest: *mut u32); - fn copy_tile_8bpp(src: *const u32, dest: *mut u32); -} diff --git a/agb/src/global_asm.rs b/agb/src/global_asm.rs index 0af2e00e..b16f19b2 100644 --- a/agb/src/global_asm.rs +++ b/agb/src/global_asm.rs @@ -6,4 +6,3 @@ global_asm!(include_str!("crt0.s")); global_asm!(include_str!("interrupt_handler.s")); global_asm!(include_str!("sound/mixer/mixer.s")); global_asm!(include_str!("save/asm_routines.s")); -global_asm!(include_str!("display/tiled/tile_copy.s")); From bb57298c54e8aa2aac90abcea64557074e8d0462 Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Wed, 6 Sep 2023 00:37:23 +0100 Subject: [PATCH 14/16] This has better code generation --- agb/src/display/tiled/vram_manager.rs | 45 ++++++++++++++++----------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs index b92e00de..e133f4e2 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -385,25 +385,32 @@ impl VRamManager { let target_location = tile_reference.0.as_ptr() as *mut _; unsafe { - core::arch::asm!( - "cmp r2, #0", - "beq 1f", - "ldmia r0!, {{r2-r5}}", - "stmia r1!, {{r2-r5}}", - "ldmia r0!, {{r2-r5}}", - "stmia r1!, {{r2-r5}}", - "1:", - "ldmia r0!, {{r2-r5}}", - "stmia r1!, {{r2-r5}}", - "ldmia r0!, {{r2-r5}}", - "stmia r1!, {{r2-r5}}", - inout("r0") tile_data_start => _, - inout("r1") target_location => _, - inout("r2") tile_format as u32 => _, - out("r3") _, - out("r4") _, - out("r5") _, - ); + match tile_format { + TileFormat::FourBpp => core::arch::asm!( + ".rept 2", + "ldmia r0!, {{r2-r5}}", + "stmia r1!, {{r2-r5}}", + ".endr", + inout("r0") tile_data_start => _, + inout("r1") target_location => _, + out("r2") _, + out("r3") _, + out("r4") _, + out("r5") _, + ), + TileFormat::EightBpp => core::arch::asm!( + ".rept 4", + "ldmia r0!, {{r2-r5}}", + "stmia r1!, {{r2-r5}}", + ".endr", + inout("r0") tile_data_start => _, + inout("r1") target_location => _, + out("r2") _, + out("r3") _, + out("r4") _, + out("r5") _, + ), + } } } From ed2e7dec5cb44fb915b6b9c544fffcf20860deaf Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Wed, 6 Sep 2023 08:34:14 +0100 Subject: [PATCH 15/16] Let rust do the register allocation --- agb/src/display/tiled/vram_manager.rs | 32 +++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs index e133f4e2..d5526d35 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -388,27 +388,27 @@ impl VRamManager { match tile_format { TileFormat::FourBpp => core::arch::asm!( ".rept 2", - "ldmia r0!, {{r2-r5}}", - "stmia r1!, {{r2-r5}}", + "ldmia {src}!, {{{tmp1},{tmp2},{tmp3},{tmp4}}}", + "stmia {dest}!, {{{tmp1},{tmp2},{tmp3},{tmp4}}}", ".endr", - inout("r0") tile_data_start => _, - inout("r1") target_location => _, - out("r2") _, - out("r3") _, - out("r4") _, - out("r5") _, + src = inout(reg) tile_data_start => _, + dest = inout(reg) target_location => _, + tmp1 = out(reg) _, + tmp2 = out(reg) _, + tmp3 = out(reg) _, + tmp4 = out(reg) _, ), TileFormat::EightBpp => core::arch::asm!( ".rept 4", - "ldmia r0!, {{r2-r5}}", - "stmia r1!, {{r2-r5}}", + "ldmia {src}!, {{{tmp1},{tmp2},{tmp3},{tmp4}}}", + "stmia {dest}!, {{{tmp1},{tmp2},{tmp3},{tmp4}}}", ".endr", - inout("r0") tile_data_start => _, - inout("r1") target_location => _, - out("r2") _, - out("r3") _, - out("r4") _, - out("r5") _, + src = inout(reg) tile_data_start => _, + dest = inout(reg) target_location => _, + tmp1 = out(reg) _, + tmp2 = out(reg) _, + tmp3 = out(reg) _, + tmp4 = out(reg) _, ), } } From 5b3248ec5a985a753b88b59d3c63b9dff4971d21 Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Wed, 6 Sep 2023 08:51:47 +0100 Subject: [PATCH 16/16] Massively improve the code generation around tile sizes --- agb/src/display/tiled/vram_manager.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs index d5526d35..059e8a8e 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -29,19 +29,15 @@ const fn layout_of(format: TileFormat) -> Layout { } #[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[repr(C)] pub enum TileFormat { - FourBpp = 0, - EightBpp = 1, + FourBpp = 5, + EightBpp = 6, } impl TileFormat { /// Returns the size of the tile in bytes pub(crate) const fn tile_size(self) -> usize { - match self { - TileFormat::FourBpp => 8 * 8 / 2, - TileFormat::EightBpp => 8 * 8, - } + 1 << self as usize } }