From d2dceeb656edfba8b3dc320263f26e48b8d00fc8 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Sun, 27 Mar 2022 21:32:37 +0100 Subject: [PATCH 1/4] Add super simple animated tiles --- agb/examples/animated_background.rs | 48 ++++++++++++++++++++++++++ agb/examples/water_tiles.png | Bin 0 -> 209 bytes agb/examples/water_tiles.toml | 5 +++ agb/src/display/tiled/vram_manager.rs | 39 +++++++++++++++++++++ 4 files changed, 92 insertions(+) create mode 100644 agb/examples/animated_background.rs create mode 100644 agb/examples/water_tiles.png create mode 100644 agb/examples/water_tiles.toml diff --git a/agb/examples/animated_background.rs b/agb/examples/animated_background.rs new file mode 100644 index 00000000..d0dab120 --- /dev/null +++ b/agb/examples/animated_background.rs @@ -0,0 +1,48 @@ +#![no_std] +#![no_main] + +use agb::{ + display::{ + tiled::{TileFormat, TileSet, TileSetting}, + Priority, + }, + include_gfx, +}; + +include_gfx!("examples/water_tiles.toml"); + +#[agb::entry] +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_ref = vram.add_tileset(tileset); + + vram.set_background_palettes(water_tiles::water_tiles.palettes); + + let mut bg = gfx.background(Priority::P0); + + for y in 0..20u16 { + for x in 0..30u16 { + bg.set_tile( + &mut vram, + (x, y).into(), + tileset_ref, + TileSetting::new(0, false, false, 0), + ); + } + } + + bg.commit(); + bg.show(); + + let mut i = 0; + loop { + i = (i + 1) % 8; + + vram.replace_tile(tileset_ref, 0, tileset_ref, i); + + vblank.wait_for_vblank(); + } +} diff --git a/agb/examples/water_tiles.png b/agb/examples/water_tiles.png new file mode 100644 index 0000000000000000000000000000000000000000..ce846ee63efc2d24a9342323cc85e604ee9d31ec GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^4nWMo!3HEflYZU@QjEnx?oJHr&dIz4a=JZT978-h z?@qqR+n~VX;?I6Saz@M2JJ%%(82>7ni8}KiT=7?F>2+=WRF1@Z3<_24nURH}ORJYn zdwKPi`}1QZ9w%SKel^$?o*R+A;^V|wFYYoP(E202K$yYzgj76h$~^|nq~0a(avL@= z1UYuwAA2>A%_YCV VRamManager<'a> { TileReference(NonNull::new(ptr as *mut _).unwrap()) } + pub fn replace_tile( + &mut self, + source_tile_set_ref: TileSetReference, + source_tile: u16, + target_tile_set_ref: TileSetReference, + target_tile: u16, + ) { + if let Some(&reference) = self + .tile_set_to_vram + .get(&(source_tile_set_ref.id, source_tile)) + { + let tile_slice = if let ArenaStorageItem::Data(data, generation) = + &self.tilesets[target_tile_set_ref.id as usize] + { + debug_assert_eq!( + *generation, target_tile_set_ref.generation, + "Stale tile data requested" + ); + + let tile_offset = (target_tile as usize) * data.format.tile_size(); + &data.tiles[tile_offset..(tile_offset + data.format.tile_size())] + } else { + panic!("Target tile set ref must point to an existing tile set reference") + }; + + let tile_size_in_half_words = tile_slice.len() / 2; + + let target_location = reference.0.as_ptr() as *mut _; + + unsafe { + dma_copy16( + tile_slice.as_ptr() as *const u16, + target_location, + tile_size_in_half_words, + ) + }; + } + } + pub(crate) fn add_tile(&mut self, tile_set_ref: TileSetReference, tile: u16) -> TileIndex { let reference = self.tile_set_to_vram.get(&(tile_set_ref.id, tile)); From 4b8f41140e1c367928cea97aa151f45208bb5fb3 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Sun, 27 Mar 2022 21:37:14 +0100 Subject: [PATCH 2/4] Extract method for copying a tile to location --- agb/src/display/tiled/vram_manager.rs | 59 +++++++++++++++------------ 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs index d5110982..89551a15 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -177,6 +177,39 @@ impl<'a> VRamManager<'a> { TileReference(NonNull::new(ptr as *mut _).unwrap()) } + fn copy_tile_to_location( + &self, + tile_set_ref: TileSetReference, + tile_id: u16, + tile_reference: TileReference, + ) { + let tile_slice = if let ArenaStorageItem::Data(data, generation) = + &self.tilesets[tile_set_ref.id as usize] + { + debug_assert_eq!( + *generation, tile_set_ref.generation, + "Stale tile data requested" + ); + + let tile_offset = (tile_id as usize) * data.format.tile_size(); + &data.tiles[tile_offset..(tile_offset + data.format.tile_size())] + } else { + panic!("Target tile set ref must point to an existing tile set reference") + }; + + let tile_size_in_half_words = tile_slice.len() / 2; + + 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, + ) + }; + } + pub fn replace_tile( &mut self, source_tile_set_ref: TileSetReference, @@ -188,31 +221,7 @@ impl<'a> VRamManager<'a> { .tile_set_to_vram .get(&(source_tile_set_ref.id, source_tile)) { - let tile_slice = if let ArenaStorageItem::Data(data, generation) = - &self.tilesets[target_tile_set_ref.id as usize] - { - debug_assert_eq!( - *generation, target_tile_set_ref.generation, - "Stale tile data requested" - ); - - let tile_offset = (target_tile as usize) * data.format.tile_size(); - &data.tiles[tile_offset..(tile_offset + data.format.tile_size())] - } else { - panic!("Target tile set ref must point to an existing tile set reference") - }; - - let tile_size_in_half_words = tile_slice.len() / 2; - - let target_location = reference.0.as_ptr() as *mut _; - - unsafe { - dma_copy16( - tile_slice.as_ptr() as *const u16, - target_location, - tile_size_in_half_words, - ) - }; + self.copy_tile_to_location(target_tile_set_ref, target_tile, reference); } } From c1cbb442a111e258acc0091ebf123b4971290bf6 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Sun, 27 Mar 2022 21:37:49 +0100 Subject: [PATCH 3/4] Also use the new method in add_tile --- agb/src/display/tiled/vram_manager.rs | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs index 89551a15..41c85b06 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -236,33 +236,10 @@ impl<'a> VRamManager<'a> { let new_reference: NonNull = unsafe { TILE_ALLOCATOR.alloc(TILE_LAYOUT) }.unwrap().cast(); - - let tile_slice = if let ArenaStorageItem::Data(data, generation) = - &self.tilesets[tile_set_ref.id as usize] - { - debug_assert_eq!( - *generation, tile_set_ref.generation, - "Stale tile data requested" - ); - - let tile_offset = (tile as usize) * data.format.tile_size(); - &data.tiles[tile_offset..(tile_offset + data.format.tile_size())] - } else { - panic!("Tile set ref must point to existing tile set"); - }; - - let tile_size_in_half_words = tile_slice.len() / 2; - - unsafe { - dma_copy16( - tile_slice.as_ptr() as *const u16, - new_reference.as_ptr() as *mut u16, - tile_size_in_half_words, - ); - } - let tile_reference = TileReference(new_reference); + self.copy_tile_to_location(tile_set_ref, tile, tile_reference); + let index = Self::index_from_reference(tile_reference); self.tile_set_to_vram From 9e8318cdf9c77f68bfcdb79818635bc71d457763 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Sun, 27 Mar 2022 21:38:12 +0100 Subject: [PATCH 4/4] Rearrange methods to make a bit more sense --- agb/src/display/tiled/vram_manager.rs | 96 +++++++++++++-------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs index 41c85b06..3b4aa57a 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -177,54 +177,6 @@ impl<'a> VRamManager<'a> { TileReference(NonNull::new(ptr as *mut _).unwrap()) } - fn copy_tile_to_location( - &self, - tile_set_ref: TileSetReference, - tile_id: u16, - tile_reference: TileReference, - ) { - let tile_slice = if let ArenaStorageItem::Data(data, generation) = - &self.tilesets[tile_set_ref.id as usize] - { - debug_assert_eq!( - *generation, tile_set_ref.generation, - "Stale tile data requested" - ); - - let tile_offset = (tile_id as usize) * data.format.tile_size(); - &data.tiles[tile_offset..(tile_offset + data.format.tile_size())] - } else { - panic!("Target tile set ref must point to an existing tile set reference") - }; - - let tile_size_in_half_words = tile_slice.len() / 2; - - 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, - ) - }; - } - - pub fn replace_tile( - &mut self, - source_tile_set_ref: TileSetReference, - source_tile: u16, - target_tile_set_ref: TileSetReference, - target_tile: u16, - ) { - if let Some(&reference) = self - .tile_set_to_vram - .get(&(source_tile_set_ref.id, source_tile)) - { - self.copy_tile_to_location(target_tile_set_ref, target_tile, reference); - } - } - pub(crate) fn add_tile(&mut self, tile_set_ref: TileSetReference, tile: u16) -> TileIndex { let reference = self.tile_set_to_vram.get(&(tile_set_ref.id, tile)); @@ -277,6 +229,54 @@ impl<'a> VRamManager<'a> { self.reference_counts[index].1 = None; } + pub fn replace_tile( + &mut self, + source_tile_set_ref: TileSetReference, + source_tile: u16, + target_tile_set_ref: TileSetReference, + target_tile: u16, + ) { + if let Some(&reference) = self + .tile_set_to_vram + .get(&(source_tile_set_ref.id, source_tile)) + { + self.copy_tile_to_location(target_tile_set_ref, target_tile, reference); + } + } + + fn copy_tile_to_location( + &self, + tile_set_ref: TileSetReference, + tile_id: u16, + tile_reference: TileReference, + ) { + let tile_slice = if let ArenaStorageItem::Data(data, generation) = + &self.tilesets[tile_set_ref.id as usize] + { + debug_assert_eq!( + *generation, tile_set_ref.generation, + "Stale tile data requested" + ); + + let tile_offset = (tile_id as usize) * data.format.tile_size(); + &data.tiles[tile_offset..(tile_offset + data.format.tile_size())] + } else { + panic!("Target tile set ref must point to an existing tile set reference") + }; + + let tile_size_in_half_words = tile_slice.len() / 2; + + 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, + ) + }; + } + /// Copies raw palettes to the background palette without any checks. pub fn set_background_palette_raw(&mut self, palette: &[u16]) { unsafe {