From c03c1664cb9642836609596f36a9d5fd77a6d91a Mon Sep 17 00:00:00 2001 From: Corwin Date: Sun, 2 Apr 2023 16:34:51 +0100 Subject: [PATCH] move static sprite loader into managed oam --- agb/examples/chicken.rs | 16 +++--- agb/examples/sprites.rs | 20 +++---- agb/src/display/mod.rs | 4 +- agb/src/display/object/managed.rs | 54 ++++++++++++++++--- .../object/sprites/sprite_allocator.rs | 2 +- 5 files changed, 67 insertions(+), 29 deletions(-) diff --git a/agb/examples/chicken.rs b/agb/examples/chicken.rs index 9bc7bfee..e0fb6757 100644 --- a/agb/examples/chicken.rs +++ b/agb/examples/chicken.rs @@ -4,7 +4,7 @@ use agb::{ display::tiled::{TileFormat, TileSet, TileSetting, TiledMap}, display::{ - object::{Object, Size, Sprite, StaticSpriteLoader}, + object::{OAMManager, Object, Size, Sprite, StaticSpriteLoader}, palette16::Palette16, tiled::RegularBackgroundSize, HEIGHT, WIDTH, @@ -74,9 +74,9 @@ fn main(mut gba: agb::Gba) -> ! { background.show(); background.commit(&mut vram); - let (object, mut sprites) = gba.display.object.get_managed(); + let object = gba.display.object.get_managed(); - let sprite = sprites.get_vram_sprite(&CHICKEN_SPRITES[0]); + let sprite = object.get_vram_sprite(&CHICKEN_SPRITES[0]); let mut chicken = Character { object: object.add_object(sprite), position: Vector2D { @@ -137,7 +137,7 @@ fn main(mut gba: agb::Gba) -> ! { } restrict_to_screen(&mut chicken); - update_chicken_object(&mut chicken, &mut sprites, state, frame_count); + update_chicken_object(&mut chicken, &object, state, frame_count); object.commit(); } @@ -145,7 +145,7 @@ fn main(mut gba: agb::Gba) -> ! { fn update_chicken_object( chicken: &'_ mut Character<'_>, - sprites: &mut StaticSpriteLoader, + gfx: &OAMManager, state: State, frame_count: u32, ) { @@ -158,18 +158,18 @@ fn update_chicken_object( State::Ground => { if chicken.velocity.x.abs() > 1 << 4 { chicken.object.set_sprite( - sprites.get_vram_sprite(&CHICKEN_SPRITES[frame_ranger(frame_count, 1, 3, 10)]), + gfx.get_vram_sprite(&CHICKEN_SPRITES[frame_ranger(frame_count, 1, 3, 10)]), ); } else { chicken .object - .set_sprite(sprites.get_vram_sprite(&CHICKEN_SPRITES[0])); + .set_sprite(gfx.get_vram_sprite(&CHICKEN_SPRITES[0])); } } State::Upwards => {} State::Flapping => { chicken.object.set_sprite( - sprites.get_vram_sprite(&CHICKEN_SPRITES[frame_ranger(frame_count, 4, 5, 5)]), + gfx.get_vram_sprite(&CHICKEN_SPRITES[frame_ranger(frame_count, 4, 5, 5)]), ); } } diff --git a/agb/examples/sprites.rs b/agb/examples/sprites.rs index 41c4247c..4ff1fb7b 100644 --- a/agb/examples/sprites.rs +++ b/agb/examples/sprites.rs @@ -3,7 +3,7 @@ extern crate alloc; -use agb::display::object::{Graphics, OAMManager, Sprite, StaticSpriteLoader, TagMap}; +use agb::display::object::{Graphics, OAMManager, Sprite, TagMap}; use alloc::vec::Vec; const GRAPHICS: &Graphics = agb::include_aseprite!( @@ -15,13 +15,13 @@ const GRAPHICS: &Graphics = agb::include_aseprite!( const SPRITES: &[Sprite] = GRAPHICS.sprites(); const TAG_MAP: &TagMap = GRAPHICS.tags(); -fn all_sprites(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) { +fn all_sprites(gfx: &OAMManager) { let mut input = agb::input::ButtonController::new(); let mut objs = Vec::new(); for y in 0..9 { for x in 0..14 { - let mut obj = gfx.add_object(sprites.get_vram_sprite(&SPRITES[0])); + let mut obj = gfx.add_object_static_sprite(&SPRITES[0]); obj.show(); obj.set_position((x * 16 + 8, y * 16 + 8).into()); objs.push(obj); @@ -48,14 +48,14 @@ fn all_sprites(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) { image %= SPRITES.len(); for (i, obj) in objs.iter_mut().enumerate() { let this_image = (image + i) % SPRITES.len(); - obj.set_sprite(sprites.get_vram_sprite(&SPRITES[this_image])); + obj.set_sprite(gfx.get_vram_sprite(&SPRITES[this_image])); } gfx.commit(); } } } -fn all_tags(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) { +fn all_tags(gfx: &OAMManager) { let mut input = agb::input::ButtonController::new(); let mut objs = Vec::new(); @@ -65,7 +65,7 @@ fn all_tags(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) { let sprite = v.sprite(0); let (size_x, size_y) = sprite.size().to_width_height(); let (size_x, size_y) = (size_x as i32, size_y as i32); - let mut obj = gfx.add_object(sprites.get_vram_sprite(sprite)); + let mut obj = gfx.add_object_static_sprite(sprite); obj.show(); obj.set_position((x * 32 + 16 - size_x / 2, y * 32 + 16 - size_y / 2).into()); objs.push((obj, v)); @@ -90,7 +90,7 @@ fn all_tags(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) { if count % 5 == 0 { image += 1; for (obj, tag) in objs.iter_mut() { - obj.set_sprite(sprites.get_vram_sprite(tag.animation_sprite(image))); + obj.set_sprite(gfx.get_vram_sprite(tag.animation_sprite(image))); } gfx.commit(); } @@ -99,12 +99,12 @@ fn all_tags(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) { #[agb::entry] fn main(mut gba: agb::Gba) -> ! { - let (gfx, mut ssl) = gba.display.object.get_managed(); + let gfx = gba.display.object.get_managed(); loop { - all_tags(&gfx, &mut ssl); + all_tags(&gfx); gfx.commit(); - all_sprites(&gfx, &mut ssl); + all_sprites(&gfx); gfx.commit(); } } diff --git a/agb/src/display/mod.rs b/agb/src/display/mod.rs index 5c30e9d0..cf0923fb 100644 --- a/agb/src/display/mod.rs +++ b/agb/src/display/mod.rs @@ -89,9 +89,9 @@ impl ObjectDistribution { (UnmanagedOAM::new(), StaticSpriteLoader::new()) } - pub fn get_managed(&mut self) -> (OAMManager<'_>, StaticSpriteLoader) { + pub fn get_managed(&mut self) -> OAMManager<'_> { unsafe { initilise_oam() }; - (OAMManager::new(), StaticSpriteLoader::new()) + OAMManager::new() } } diff --git a/agb/src/display/object/managed.rs b/agb/src/display/object/managed.rs index 9c4d889d..861ffa53 100644 --- a/agb/src/display/object/managed.rs +++ b/agb/src/display/object/managed.rs @@ -4,11 +4,12 @@ use core::{ }; use agb_fixnum::Vector2D; +use alloc::vec::Vec; use slotmap::{new_key_type, SlotMap}; -use crate::display::Priority; +use crate::{display::Priority, sync::Static}; -use super::{AffineMode, SpriteVram, UnmanagedOAM, UnmanagedObject}; +use super::{AffineMode, Sprite, SpriteVram, StaticSpriteLoader, UnmanagedOAM, UnmanagedObject}; new_key_type! {struct ObjectKey; } @@ -26,6 +27,7 @@ struct ObjectItem { struct Store { store: UnsafeCell>, + removal_list: UnsafeCell>, first_z: Cell>, } @@ -111,12 +113,24 @@ impl Store { } fn remove_object(&self, object: ObjectKey) { - remove_from_linked_list(self, object); - let data = unsafe { &mut *self.store.get() }; data.remove(object); } + fn remove_all_in_removal_list(&self) { + let removal_list = unsafe { &mut *self.removal_list.get() }; + for object in removal_list.drain(..) { + self.remove_object(object); + } + } + + fn mark_for_removal(&self, object: ObjectKey) { + let removal_list = unsafe { &mut *self.removal_list.get() }; + removal_list.push(object); + + remove_from_linked_list(self, object); + } + fn get_object(&self, key: ObjectKey) -> &ObjectItem { &(unsafe { &*self.store.get() }[key]) } @@ -125,6 +139,7 @@ impl Store { pub struct OAMManager<'gba> { phantom: PhantomData<&'gba ()>, object_store: Store, + sprite_loader: UnsafeCell, } impl OAMManager<'_> { @@ -133,16 +148,29 @@ impl OAMManager<'_> { phantom: PhantomData, object_store: Store { store: UnsafeCell::new(SlotMap::with_key()), + removal_list: UnsafeCell::new(Vec::new()), first_z: Cell::new(None), }, + sprite_loader: UnsafeCell::new(StaticSpriteLoader::new()), } } + pub fn do_work_with_sprite_loader(&self, c: C) -> T + where + C: Fn(&mut StaticSpriteLoader) -> T, + { + let sprite_loader = unsafe { &mut *self.sprite_loader.get() }; + + c(sprite_loader) + } + pub fn commit(&self) { let mut count = 0; let mut unmanaged = UnmanagedOAM::new(); + // do interactions with OAM + for (object, mut slot) in unsafe { self.object_store.iter() } .map(|item| unsafe { &*item.object.get() }) .filter(|object| object.is_visible()) @@ -151,16 +179,26 @@ impl OAMManager<'_> { slot.set(object); count += 1; } - - crate::println!("{}", count); - unmanaged.clear_from(count); + + // finished OAM interactions + + self.object_store.remove_all_in_removal_list(); + self.do_work_with_sprite_loader(StaticSpriteLoader::garbage_collect); } pub fn add_object(&self, sprite: SpriteVram) -> Object<'_> { self.object_store .insert_object(UnmanagedObject::new(sprite)) } + + pub fn get_vram_sprite(&self, sprite: &'static Sprite) -> SpriteVram { + self.do_work_with_sprite_loader(|sprite_loader| sprite_loader.get_vram_sprite(sprite)) + } + + pub fn add_object_static_sprite(&self, sprite: &'static Sprite) -> Object<'_> { + self.add_object(self.get_vram_sprite(sprite)) + } } pub struct Object<'controller> { @@ -170,7 +208,7 @@ pub struct Object<'controller> { impl Drop for Object<'_> { fn drop(&mut self) { - self.store.remove_object(self.me); + self.store.mark_for_removal(self.me); } } diff --git a/agb/src/display/object/sprites/sprite_allocator.rs b/agb/src/display/object/sprites/sprite_allocator.rs index 072a190a..207186ac 100644 --- a/agb/src/display/object/sprites/sprite_allocator.rs +++ b/agb/src/display/object/sprites/sprite_allocator.rs @@ -231,7 +231,7 @@ impl StaticSpriteLoader { } } - fn gc(&mut self) { + pub fn garbage_collect(&mut self) { self.static_sprite_map .retain(|_, v| Weak::strong_count(v) != 0); self.static_palette_map