From be650779e645913f37105528179a1b13bd0a7793 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 3 May 2022 23:23:25 +0100 Subject: [PATCH] Correctly allocate screenblocks --- agb/src/display/tiled/map.rs | 15 ++++++ agb/src/display/tiled/mod.rs | 4 ++ agb/src/display/tiled/tiled0.rs | 47 ++++++++++++++++--- .../the-hat-chooses-the-wizard/src/main.rs | 4 +- 4 files changed, 61 insertions(+), 9 deletions(-) diff --git a/agb/src/display/tiled/map.rs b/agb/src/display/tiled/map.rs index c42cbeda..568091f6 100644 --- a/agb/src/display/tiled/map.rs +++ b/agb/src/display/tiled/map.rs @@ -164,7 +164,10 @@ impl RegularMap { pub struct MapLoan<'a, T> { map: T, background_id: u8, + screenblock_id: u8, + screenblock_length: u8, regular_map_list: &'a RefCell>, + screenblock_list: &'a RefCell>, } impl<'a, T> Deref for MapLoan<'a, T> { @@ -185,12 +188,18 @@ impl<'a, T> MapLoan<'a, T> { pub(crate) fn new( map: T, background_id: u8, + screenblock_id: u8, + screenblock_length: u8, regular_map_list: &'a RefCell>, + screenblock_list: &'a RefCell>, ) -> Self { MapLoan { map, background_id, + screenblock_id, + screenblock_length, regular_map_list, + screenblock_list, } } } @@ -200,5 +209,11 @@ impl<'a, T> Drop for MapLoan<'a, T> { self.regular_map_list .borrow_mut() .set(self.background_id as usize, false); + + let mut screenblock_list = self.screenblock_list.borrow_mut(); + + for i in self.screenblock_id..self.screenblock_id + self.screenblock_length { + screenblock_list.set(i as usize, false); + } } } diff --git a/agb/src/display/tiled/mod.rs b/agb/src/display/tiled/mod.rs index b09f3e6e..5a53cad6 100644 --- a/agb/src/display/tiled/mod.rs +++ b/agb/src/display/tiled/mod.rs @@ -48,6 +48,10 @@ impl RegularBackgroundSize { (self.width() * self.height()) as usize } + pub(crate) fn num_screen_blocks(&self) -> usize { + self.num_tiles() / (32 * 32) + } + pub(crate) fn rem_euclid_width(&self, x: i32) -> u16 { ((x as u32) & (self.width() - 1)) as u16 } diff --git a/agb/src/display/tiled/tiled0.rs b/agb/src/display/tiled/tiled0.rs index f6c20db8..fbc523e2 100644 --- a/agb/src/display/tiled/tiled0.rs +++ b/agb/src/display/tiled/tiled0.rs @@ -9,6 +9,7 @@ use super::{MapLoan, RegularBackgroundSize, RegularMap}; pub struct Tiled0 { regular: RefCell>, + screenblocks: RefCell>, } impl Tiled0 { @@ -17,6 +18,7 @@ impl Tiled0 { Self { regular: Default::default(), + screenblocks: Default::default(), } } @@ -31,15 +33,46 @@ impl Tiled0 { panic!("can only have 4 active backgrounds"); } - let bg = RegularMap::new( - new_background as u8, - (new_background + 16) as u8, - priority, - size, - ); + let num_screenblocks = size.num_screen_blocks(); + let mut screenblocks = self.screenblocks.borrow_mut(); + + let screenblock = find_screenblock_gap(&screenblocks, num_screenblocks); + for id in screenblock..(screenblock + num_screenblocks) { + screenblocks.set(id, true); + } + + let bg = RegularMap::new(new_background as u8, screenblock as u8 + 16, priority, size); regular.set(new_background, true); - MapLoan::new(bg, new_background as u8, &self.regular) + MapLoan::new( + bg, + new_background as u8, + screenblock as u8, + num_screenblocks as u8, + &self.regular, + &self.screenblocks, + ) } } + +fn find_screenblock_gap(screenblocks: &Bitarray<1>, gap: usize) -> usize { + let mut candidate = 0; + + 'outer: while candidate < 16 - gap { + let starting_point = candidate; + for attempt in starting_point..(starting_point + gap) { + if screenblocks.get(attempt) == Some(true) { + candidate = attempt + 1; + continue 'outer; + } + } + + return candidate; + } + + panic!( + "Failed to find screenblock gap of at least {} elements", + gap + ); +} diff --git a/examples/the-hat-chooses-the-wizard/src/main.rs b/examples/the-hat-chooses-the-wizard/src/main.rs index 57ab5ec2..cf5524dd 100644 --- a/examples/the-hat-chooses-the-wizard/src/main.rs +++ b/examples/the-hat-chooses-the-wizard/src/main.rs @@ -846,7 +846,7 @@ fn main(mut agb: agb::Gba) -> ! { let map_current_level = current_level; let mut background = InfiniteScrolledMap::new( - tiled.background(Priority::P2, RegularBackgroundSize::Background32x32), + tiled.background(Priority::P2, RegularBackgroundSize::Background64x64), Box::new(|pos: Vector2D| { let level = &map_tiles::LEVELS[map_current_level as usize]; ( @@ -861,7 +861,7 @@ fn main(mut agb: agb::Gba) -> ! { }), ); let mut foreground = InfiniteScrolledMap::new( - tiled.background(Priority::P0, RegularBackgroundSize::Background32x32), + tiled.background(Priority::P0, RegularBackgroundSize::Background64x64), Box::new(|pos: Vector2D| { let level = &map_tiles::LEVELS[map_current_level as usize]; (