possible iter for backgrounds

This commit is contained in:
Corwin Kuiper 2021-10-17 21:59:57 +01:00
parent 6f804d884b
commit 1541d514c9
3 changed files with 29 additions and 44 deletions

View file

@ -129,7 +129,7 @@ impl<'a> Map<'a> {
}
}
impl<'a> BackgroundRegular<'a> {
impl<'a, 'b> BackgroundRegular<'a> {
unsafe fn new(background: u8, block: u8, size: BackgroundSize) -> BackgroundRegular<'a> {
let mut b = BackgroundRegular {
background,
@ -211,29 +211,23 @@ impl<'a> BackgroundRegular<'a> {
self.map = Some(map);
}
pub fn commit(&mut self) {
pub fn commit_partial(&'b mut self) -> impl Iterator<Item = ()> + 'b {
// commit shadowed register
unsafe { self.get_register().set(self.shadowed_register) };
let map = self.map.as_ref().unwrap();
let commited_screen = Rect::new(self.commited_position, self.copy_size.change_base());
let shadowed_screen = Rect::new(self.shadowed_position, self.copy_size.change_base());
if self.poisoned || !shadowed_screen.touches(commited_screen) {
let iter = if self.poisoned || !shadowed_screen.touches(commited_screen) {
let positions_to_be_updated = Rect::new(
self.shadowed_position / 8 - (1, 1).into(),
self.copy_size.change_base() + (1, 1).into(),
)
.iter();
if let Some(map) = &self.map {
for (x, y) in positions_to_be_updated {
unsafe {
(&mut (*MAP)[self.block as usize][y.rem_euclid(32) as usize]
[x.rem_euclid(32) as usize] as *mut u16)
.write_volatile(map.get_position(x, y));
}
}
}
positions_to_be_updated.chain(Rect::new((0, 0).into(), (0, 0).into()).iter())
} else {
let commited_block = self.commited_position / 8;
let shadowed_block = self.shadowed_position / 8;
@ -264,15 +258,7 @@ impl<'a> BackgroundRegular<'a> {
)
};
if let Some(map) = &self.map {
for (x, y) in top_bottom_rect.iter().chain(left_right_rect.iter()) {
unsafe {
(&mut (*MAP)[self.block as usize][y.rem_euclid(32) as usize]
[x.rem_euclid(32) as usize] as *mut u16)
.write_volatile(map.get_position(x, y));
}
}
}
top_bottom_rect.iter().chain(left_right_rect.iter())
};
// update commited position
@ -287,6 +273,18 @@ impl<'a> BackgroundRegular<'a> {
self.set_position_x_register((self.commited_position.x % (32 * 8)) as u16);
self.set_position_y_register((self.commited_position.y % (32 * 8)) as u16);
}
let block = self.block;
iter.map(move |(x, y)| unsafe {
(&mut (*MAP)[block as usize][y.rem_euclid(32) as usize][x.rem_euclid(32) as usize]
as *mut u16)
.write_volatile(map.get_position(x, y));
})
}
pub fn commit(&mut self) {
self.commit_partial().count();
}
}

View file

@ -7,6 +7,7 @@
#![feature(alloc_error_handler)]
#![test_runner(crate::test_runner)]
#![reexport_test_harness_main = "test_main"]
#![feature(step_trait)]
//! # agb
//! `agb` is a library for making games on the Game Boy Advance using the Rust
//! programming language. It attempts to be a high level abstraction over the

View file

@ -700,30 +700,16 @@ impl<T: Number> Rect<T> {
}
}
impl<T: FixedWidthUnsignedInteger> Rect<T> {
impl<T: FixedWidthUnsignedInteger + core::iter::Step> Rect<T> {
pub fn iter(self) -> impl Iterator<Item = (T, T)> {
let mut current_x = self.position.x;
let mut current_y = self.position.y;
let mut is_done = false;
core::iter::from_fn(move || {
if is_done {
None
} else {
let (old_x, old_y) = (current_x, current_y);
current_x = current_x + T::one();
if current_x > self.position.x + self.size.x {
current_x = self.position.x;
current_y = current_y + T::one();
}
if current_y > self.position.y + self.size.y {
is_done = true;
}
Some((old_x, old_y))
}
(self.position.x..=(self.position.x + self.size.x))
.into_iter()
.map(move |x| {
(self.position.y..=(self.position.y + self.size.y))
.into_iter()
.map(move |y| (x, y))
})
.flatten()
}
}