From 1541d514c912a27add2287b9becbcca1223973f1 Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Sun, 17 Oct 2021 21:59:57 +0100 Subject: [PATCH] possible iter for backgrounds --- agb/src/display/background.rs | 40 +++++++++++++++++------------------ agb/src/lib.rs | 1 + agb/src/number.rs | 32 ++++++++-------------------- 3 files changed, 29 insertions(+), 44 deletions(-) diff --git a/agb/src/display/background.rs b/agb/src/display/background.rs index fbe01412..b6b80437 100644 --- a/agb/src/display/background.rs +++ b/agb/src/display/background.rs @@ -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 + '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(); } } diff --git a/agb/src/lib.rs b/agb/src/lib.rs index 8864b605..d03a3bd2 100644 --- a/agb/src/lib.rs +++ b/agb/src/lib.rs @@ -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 diff --git a/agb/src/number.rs b/agb/src/number.rs index 2ff6e7e8..f046e79d 100644 --- a/agb/src/number.rs +++ b/agb/src/number.rs @@ -700,30 +700,16 @@ impl Rect { } } -impl Rect { +impl Rect { pub fn iter(self) -> impl Iterator { - 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() } }