Correctly allocate screenblocks

This commit is contained in:
Gwilym Kuiper 2022-05-03 23:23:25 +01:00
parent ae65af4ca2
commit be650779e6
4 changed files with 61 additions and 9 deletions

View file

@ -164,7 +164,10 @@ impl RegularMap {
pub struct MapLoan<'a, T> { pub struct MapLoan<'a, T> {
map: T, map: T,
background_id: u8, background_id: u8,
screenblock_id: u8,
screenblock_length: u8,
regular_map_list: &'a RefCell<Bitarray<1>>, regular_map_list: &'a RefCell<Bitarray<1>>,
screenblock_list: &'a RefCell<Bitarray<1>>,
} }
impl<'a, T> Deref for MapLoan<'a, T> { impl<'a, T> Deref for MapLoan<'a, T> {
@ -185,12 +188,18 @@ impl<'a, T> MapLoan<'a, T> {
pub(crate) fn new( pub(crate) fn new(
map: T, map: T,
background_id: u8, background_id: u8,
screenblock_id: u8,
screenblock_length: u8,
regular_map_list: &'a RefCell<Bitarray<1>>, regular_map_list: &'a RefCell<Bitarray<1>>,
screenblock_list: &'a RefCell<Bitarray<1>>,
) -> Self { ) -> Self {
MapLoan { MapLoan {
map, map,
background_id, background_id,
screenblock_id,
screenblock_length,
regular_map_list, regular_map_list,
screenblock_list,
} }
} }
} }
@ -200,5 +209,11 @@ impl<'a, T> Drop for MapLoan<'a, T> {
self.regular_map_list self.regular_map_list
.borrow_mut() .borrow_mut()
.set(self.background_id as usize, false); .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);
}
} }
} }

View file

@ -48,6 +48,10 @@ impl RegularBackgroundSize {
(self.width() * self.height()) as usize (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 { pub(crate) fn rem_euclid_width(&self, x: i32) -> u16 {
((x as u32) & (self.width() - 1)) as u16 ((x as u32) & (self.width() - 1)) as u16
} }

View file

@ -9,6 +9,7 @@ use super::{MapLoan, RegularBackgroundSize, RegularMap};
pub struct Tiled0 { pub struct Tiled0 {
regular: RefCell<Bitarray<1>>, regular: RefCell<Bitarray<1>>,
screenblocks: RefCell<Bitarray<1>>,
} }
impl Tiled0 { impl Tiled0 {
@ -17,6 +18,7 @@ impl Tiled0 {
Self { Self {
regular: Default::default(), regular: Default::default(),
screenblocks: Default::default(),
} }
} }
@ -31,15 +33,46 @@ impl Tiled0 {
panic!("can only have 4 active backgrounds"); panic!("can only have 4 active backgrounds");
} }
let bg = RegularMap::new( let num_screenblocks = size.num_screen_blocks();
new_background as u8, let mut screenblocks = self.screenblocks.borrow_mut();
(new_background + 16) as u8,
priority, let screenblock = find_screenblock_gap(&screenblocks, num_screenblocks);
size, 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); 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
);
}

View file

@ -846,7 +846,7 @@ fn main(mut agb: agb::Gba) -> ! {
let map_current_level = current_level; let map_current_level = current_level;
let mut background = InfiniteScrolledMap::new( let mut background = InfiniteScrolledMap::new(
tiled.background(Priority::P2, RegularBackgroundSize::Background32x32), tiled.background(Priority::P2, RegularBackgroundSize::Background64x64),
Box::new(|pos: Vector2D<i32>| { Box::new(|pos: Vector2D<i32>| {
let level = &map_tiles::LEVELS[map_current_level as usize]; 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( let mut foreground = InfiniteScrolledMap::new(
tiled.background(Priority::P0, RegularBackgroundSize::Background32x32), tiled.background(Priority::P0, RegularBackgroundSize::Background64x64),
Box::new(|pos: Vector2D<i32>| { Box::new(|pos: Vector2D<i32>| {
let level = &map_tiles::LEVELS[map_current_level as usize]; let level = &map_tiles::LEVELS[map_current_level as usize];
( (