From 63dd8375189dc92a081af58ed6716297410b909a Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper <gw@ilym.me> Date: Mon, 14 Feb 2022 20:57:12 +0000 Subject: [PATCH] Tiny performance improvement with dma to copy the tile data --- agb/src/display/background.rs | 39 +++++++++++++++++-- .../the-hat-chooses-the-wizard/src/main.rs | 4 +- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/agb/src/display/background.rs b/agb/src/display/background.rs index e64b5323..712450e8 100644 --- a/agb/src/display/background.rs +++ b/agb/src/display/background.rs @@ -20,7 +20,7 @@ use super::{ }; const TILE_BACKGROUND: MemoryMapped1DArray<u32, { 2048 * 8 }> = - unsafe { MemoryMapped1DArray::new(0x06000000) }; + unsafe { MemoryMapped1DArray::new(0x0600_0000) }; const PALETTE_BACKGROUND: MemoryMapped1DArray<u16, 256> = unsafe { MemoryMapped1DArray::new(0x0500_0000) }; @@ -219,10 +219,16 @@ impl<'a> VRamManager<'a> { unsafe { debug_unreachable_unchecked() }; }; - let tile_size_in_words = TileFormat::FourBpp.tile_size() / 4; + let tile_size_in_half_words = TileFormat::FourBpp.tile_size() / 2; - for (i, &word) in tile_slice.iter().enumerate() { - TILE_BACKGROUND.set(index_to_copy_into * tile_size_in_words + i, word); + const TILE_BACKGROUND_ADDRESS: usize = 0x0600_0000; + unsafe { + dma_copy( + tile_slice.as_ptr() as *const u16, + (TILE_BACKGROUND_ADDRESS as *mut u16) + .add(index_to_copy_into * tile_size_in_half_words), + tile_size_in_half_words, + ); } self.tile_set_to_vram.insert( @@ -703,3 +709,28 @@ impl<'a, T> Drop for MapLoan<'a, T> { .set(self.background_id as usize, false); } } + +const fn dma_source_addr(dma: usize) -> usize { + 0x0400_00b0 + 0x0c * dma +} + +const fn dma_dest_addr(dma: usize) -> usize { + 0x0400_00b4 + 0x0c * dma +} + +const fn dma_control_addr(dma: usize) -> usize { + 0x0400_00b8 + 0x0c * dma +} + +const DMA3_SOURCE_ADDR: MemoryMapped<u32> = unsafe { MemoryMapped::new(dma_source_addr(3)) }; +const DMA3_DEST_ADDR: MemoryMapped<u32> = unsafe { MemoryMapped::new(dma_dest_addr(3)) }; +const DMA3_CONTROL: MemoryMapped<u32> = unsafe { MemoryMapped::new(dma_control_addr(3)) }; + +unsafe fn dma_copy(src: *const u16, dest: *mut u16, count: usize) { + assert!(count < u16::MAX as usize); + + DMA3_SOURCE_ADDR.set(src as u32); + DMA3_DEST_ADDR.set(dest as u32); + + DMA3_CONTROL.set(count as u32 | (1 << 31)); +} diff --git a/examples/the-hat-chooses-the-wizard/src/main.rs b/examples/the-hat-chooses-the-wizard/src/main.rs index 73f3aa2b..5904bbc2 100644 --- a/examples/the-hat-chooses-the-wizard/src/main.rs +++ b/examples/the-hat-chooses-the-wizard/src/main.rs @@ -796,8 +796,8 @@ fn main(mut agb: agb::Gba) -> ! { object.set_sprite_palettes(object_sheet::object_sheet.palettes); object.set_sprite_tilemap(object_sheet::object_sheet.tiles); - for y in 0..20u16 { - for x in 0..30u16 { + for y in 0..32u16 { + for x in 0..32u16 { world_display.set_tile( &mut vram, (x, y).into(),