From d4a12277eb8e498bba465a6a24e313a9037ca49b Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Mon, 21 Mar 2022 22:41:11 +0000 Subject: [PATCH 1/5] Generate a bytestring for the image converter rather than the array --- agb-image-converter/src/rust_generator.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/agb-image-converter/src/rust_generator.rs b/agb-image-converter/src/rust_generator.rs index f3fafa83..c223d3a9 100644 --- a/agb-image-converter/src/rust_generator.rs +++ b/agb-image-converter/src/rust_generator.rs @@ -1,6 +1,6 @@ -use crate::image_loader::Image; use crate::palette16::Palette16OptimisationResults; use crate::TileSize; +use crate::{image_loader::Image, ByteString}; use proc_macro2::TokenStream; use quote::{format_ident, quote}; @@ -45,11 +45,11 @@ pub(crate) fn generate_code( for x in 0..tiles_x { let palette_index = results.assignments[y * tiles_x + x]; let palette = &results.optimised_palettes[palette_index]; - + for inner_y in 0..tile_size / 8 { for inner_x in 0..tile_size / 8 { - for j in inner_y * 8..inner_y * 8 + 8 { - for i in (inner_x * 8..inner_x * 8 + 8).rev() { + for j in inner_y * 8..inner_y * 8 + 8 { + for i in inner_x * 8..inner_x * 8 + 8 { let colour = image.colour(x * tile_size + i, y * tile_size + j); tile_data.push(palette.colour_index(colour)); } @@ -59,8 +59,12 @@ pub(crate) fn generate_code( } } - let tile_data = tile_data.chunks(8) - .map(|chunk| chunk.iter().fold(0u32, |acc, &x| (acc << 4) | (x as u32))); + let tile_data: Vec<_> = tile_data + .chunks(2) + .map(|chunk| (chunk[1] << 4) | chunk[0]) + .collect(); + + let data = ByteString(&tile_data); let assignments = results.assignments.iter().map(|&x| x as u8); @@ -73,9 +77,7 @@ pub(crate) fn generate_code( #(#palette_data),* ]; - const TILE_DATA: &[u32] = &[ - #(#tile_data),* - ]; + const TILE_DATA: &[u8] = #data; const PALETTE_ASSIGNMENT: &[u8] = &[ #(#assignments),* From 9170acb1a85ae1168a1fafad25acfc1a977392f8 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Mon, 21 Mar 2022 22:57:17 +0000 Subject: [PATCH 2/5] Update agb to handle the new agb-image-converter output --- agb/examples/chicken.rs | 53 ++++++++++++++++++--------- agb/src/display/tile_data.rs | 4 +- agb/src/display/tiled/vram_manager.rs | 10 ++--- 3 files changed, 42 insertions(+), 25 deletions(-) diff --git a/agb/examples/chicken.rs b/agb/examples/chicken.rs index 630dd162..8df59eb5 100644 --- a/agb/examples/chicken.rs +++ b/agb/examples/chicken.rs @@ -311,24 +311,41 @@ static ChickenSprites: &[Sprite] = &[ ), ]; -static MAP_TILES: [u32; 8 * 17] = [ - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, - 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x01111111, 0x01111111, 0x01111111, - 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x00000000, 0x01010101, 0x01010101, - 0x00000000, 0x00000000, 0x11110000, 0x11100000, 0x11000100, 0x10001100, 0x00011100, 0x00111100, - 0x00000000, 0x00000000, 0x01110001, 0x01100011, 0x01000111, 0x00001111, 0x00011111, 0x00111111, - 0x00111111, 0x00111111, 0x00111111, 0x00111111, 0x00111111, 0x00111111, 0x00001111, 0x00000111, - 0x00000000, 0x00000000, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, - 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x10111111, 0x01101011, - 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x01101011, - 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11101111, 0x10110111, - 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11101111, - 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111101, 0x11111011, 0x10111011, - 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x10111011, - 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11101111, 0x11101011, - 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11011111, 0x11010111, - 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x01111111, 0x11010111, +static MAP_TILES: [u8; 8 * 17 * 4] = [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x01, 0x11, 0x11, 0x11, 0x01, 0x11, 0x11, 0x11, 0x01, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x10, 0x11, + 0x00, 0x01, 0x00, 0x11, 0x00, 0x11, 0x00, 0x10, 0x00, 0x11, 0x01, 0x00, 0x00, 0x11, 0x11, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x01, 0x11, 0x00, 0x10, 0x01, + 0x11, 0x01, 0x00, 0x01, 0x11, 0x11, 0x00, 0x00, 0x11, 0x11, 0x01, 0x00, 0x11, 0x11, 0x11, 0x00, + 0x11, 0x11, 0x11, 0x00, 0x11, 0x11, 0x11, 0x00, 0x11, 0x11, 0x11, 0x00, 0x11, 0x11, 0x11, 0x00, + 0x11, 0x11, 0x11, 0x00, 0x11, 0x11, 0x11, 0x00, 0x11, 0x11, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x10, 0x10, 0x01, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x10, 0x01, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, 0x01, 0x11, 0x10, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x01, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, 0x11, 0x10, 0x11, 0x10, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x10, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11, 0x10, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x01, 0x11, 0x11, 0x01, 0x01, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x01, 0x11, 0x01, 0x01, 0x11, ]; static MAP_MAP: [u16; 1024] = [ diff --git a/agb/src/display/tile_data.rs b/agb/src/display/tile_data.rs index a8698e82..44123697 100644 --- a/agb/src/display/tile_data.rs +++ b/agb/src/display/tile_data.rs @@ -2,14 +2,14 @@ use crate::display::palette16::Palette16; pub struct TileData { pub palettes: &'static [Palette16], - pub tiles: &'static [u32], + pub tiles: &'static [u8], pub palette_assignments: &'static [u8], } impl TileData { pub const fn new( palettes: &'static [Palette16], - tiles: &'static [u32], + tiles: &'static [u8], palette_assignments: &'static [u8], ) -> Self { TileData { diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs index b3cc2fe6..bb935997 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -51,17 +51,17 @@ impl TileFormat { } pub struct TileSet<'a> { - tiles: &'a [u32], + tiles: &'a [u8], format: TileFormat, } impl<'a> TileSet<'a> { - pub fn new(tiles: &'a [u32], format: TileFormat) -> Self { + pub fn new(tiles: &'a [u8], format: TileFormat) -> Self { Self { tiles, format } } fn num_tiles(&self) -> usize { - self.tiles.len() / self.format.tile_size() * 4 + self.tiles.len() / self.format.tile_size() } } @@ -204,8 +204,8 @@ impl<'a> VRamManager<'a> { "Stale tile data requested" ); - let tile_offset = (tile as usize) * data.format.tile_size() / 4; - &data.tiles[tile_offset..(tile_offset + data.format.tile_size() / 4)] + 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"); }; From e6d47afa310699f928acd7a719307e41c33e8cd2 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Mon, 21 Mar 2022 22:58:16 +0000 Subject: [PATCH 3/5] Use a hash map rather than an array in vram manager --- agb/src/display/tiled/vram_manager.rs | 28 +++++++++++++-------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs index bb935997..9db99db9 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -1,12 +1,12 @@ use core::{alloc::Layout, ptr::NonNull}; -use alloc::vec; use alloc::vec::Vec; use crate::{ agb_alloc::{block_allocator::BlockAllocator, bump_allocator::StartEnd}, display::palette16, dma::dma_copy16, + hash_map::HashMap, memory_mapped::MemoryMapped1DArray, }; @@ -61,7 +61,7 @@ impl<'a> TileSet<'a> { } fn num_tiles(&self) -> usize { - self.tiles.len() / self.format.tile_size() + self.tiles.len() / self.format.tile_size() * 4 } } @@ -104,18 +104,20 @@ pub struct VRamManager<'a> { generation: u16, free_pointer: Option, - tile_set_to_vram: Vec>>, + tile_set_to_vram: HashMap<(u16, u16), TileReference>, reference_counts: Vec<(u16, Option<(TileSetReference, u16)>)>, } impl<'a> VRamManager<'a> { pub(crate) fn new() -> Self { + let tile_set_to_vram: HashMap<(u16, u16), TileReference> = HashMap::with_capacity(256); + Self { tilesets: Vec::new(), generation: 0, free_pointer: None, - tile_set_to_vram: Default::default(), + tile_set_to_vram, reference_counts: Default::default(), } } @@ -124,7 +126,6 @@ impl<'a> VRamManager<'a> { let generation = self.generation; self.generation = self.generation.wrapping_add(1); - let num_tiles = tileset.num_tiles(); let tileset = ArenaStorageItem::Data(tileset, generation); let index = if let Some(ptr) = self.free_pointer.take() { @@ -145,10 +146,6 @@ impl<'a> VRamManager<'a> { self.tilesets.len() - 1 }; - self.tile_set_to_vram - .resize(self.tilesets.len(), Default::default()); - self.tile_set_to_vram[index] = vec![Default::default(); num_tiles]; - TileSetReference::new(index as u16, generation) } @@ -185,10 +182,10 @@ impl<'a> VRamManager<'a> { } pub(crate) fn add_tile(&mut self, tile_set_ref: TileSetReference, tile: u16) -> TileIndex { - let reference = self.tile_set_to_vram[tile_set_ref.id as usize][tile as usize]; + let reference = self.tile_set_to_vram.get(&(tile_set_ref.id, tile)); if let Some(reference) = reference { - let index = Self::index_from_reference(reference); + let index = Self::index_from_reference(*reference); self.reference_counts[index].0 += 1; return TileIndex::new(index); } @@ -210,7 +207,7 @@ impl<'a> VRamManager<'a> { panic!("Tile set ref must point to existing tile set"); }; - let tile_size_in_half_words = TileFormat::FourBpp.tile_size() / 2; + let tile_size_in_half_words = tile_slice.len() / 2; unsafe { dma_copy16( @@ -224,7 +221,8 @@ impl<'a> VRamManager<'a> { let index = Self::index_from_reference(tile_reference); - self.tile_set_to_vram[tile_set_ref.id as usize][tile as usize] = Some(tile_reference); + self.tile_set_to_vram + .insert((tile_set_ref.id, tile), tile_reference); self.reference_counts .resize(self.reference_counts.len().max(index + 1), (0, None)); @@ -250,11 +248,11 @@ impl<'a> VRamManager<'a> { let tile_reference = Self::reference_from_index(tile_index); unsafe { - TILE_ALLOCATOR.dealloc(tile_reference.0.cast().as_ptr(), TILE_LAYOUT); + TILE_ALLOCATOR.dealloc_no_normalise(tile_reference.0.cast().as_ptr(), TILE_LAYOUT); } let tile_ref = self.reference_counts[index].1.unwrap(); - self.tile_set_to_vram[tile_ref.0.id as usize][tile_ref.1 as usize] = None; + self.tile_set_to_vram.remove(&(tile_ref.0.id, tile_ref.1)); self.reference_counts[index].1 = None; } From 451868723fc1b639f179fe9593986f72a485f0bd Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Mon, 21 Mar 2022 23:01:38 +0000 Subject: [PATCH 4/5] Add dealloc_no_normalise --- agb/src/agb_alloc/block_allocator.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/agb/src/agb_alloc/block_allocator.rs b/agb/src/agb_alloc/block_allocator.rs index c029522e..99248e66 100644 --- a/agb/src/agb_alloc/block_allocator.rs +++ b/agb/src/agb_alloc/block_allocator.rs @@ -157,6 +157,11 @@ impl BlockAllocator { } pub unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + self.dealloc_no_normalise(ptr, layout); + self.normalise(); + } + + pub unsafe fn dealloc_no_normalise(&self, ptr: *mut u8, layout: Layout) { let new_layout = Block::either_layout(layout).pad_to_align(); free(|key| { let mut state = self.state.borrow(*key).borrow_mut(); @@ -195,7 +200,6 @@ impl BlockAllocator { } } }); - self.normalise(); } } From 1c33c8544e7f5c327eae18c11790f1e7db980a75 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Mon, 21 Mar 2022 23:16:02 +0000 Subject: [PATCH 5/5] Seems range inclusive doesn't optimise very well... --- agb/src/hash_map.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agb/src/hash_map.rs b/agb/src/hash_map.rs index a5183c72..e4688be9 100644 --- a/agb/src/hash_map.rs +++ b/agb/src/hash_map.rs @@ -657,7 +657,7 @@ impl NodeStorage { where K: Eq, { - for distance_to_initial_bucket in 0..=self.max_distance_to_initial_bucket { + for distance_to_initial_bucket in 0..(self.max_distance_to_initial_bucket + 1) { let location = fast_mod( self.nodes.len(), hash + distance_to_initial_bucket as HashType,