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 00000000..ce846ee6 Binary files /dev/null and b/agb/examples/water_tiles.png differ diff --git a/agb/examples/water_tiles.toml b/agb/examples/water_tiles.toml new file mode 100644 index 00000000..9981e521 --- /dev/null +++ b/agb/examples/water_tiles.toml @@ -0,0 +1,5 @@ +version = "1.0" + +[image.water_tiles] +filename = "water_tiles.png" +tile_size = "8x8" \ 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 dd71d3c9..3b4aa57a 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -188,33 +188,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 @@ -252,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 {