diff --git a/agb/examples/chicken.rs b/agb/examples/chicken.rs index 8650730..55a7f08 100644 --- a/agb/examples/chicken.rs +++ b/agb/examples/chicken.rs @@ -48,18 +48,23 @@ pub fn main() -> ! { let vblank = agb::interrupt::VBlank::get(); let mut input = agb::input::ButtonController::new(); - gfx.set_sprite_palette_raw(&CHICKEN_PALETTE); - gfx.set_sprite_tilemap(&CHICKEN_TILES); - gfx.set_background_palette_raw(&MAP_PALETTE); gfx.set_background_tilemap(0, &MAP_TILES); let mut background = gfx.get_background().unwrap(); - background.draw_full_map(&MAP_MAP, (32_u32, 32_u32).into(), 0); + background.set_map(agb::display::tiled0::Map { + store: &MAP_MAP, + dimensions: (32_u32, 32_u32).into(), + default: 0, + }); background.show(); + background.commit(); let mut object = gba.display.object.get(); + object.set_sprite_palette_raw(&CHICKEN_PALETTE); + object.set_sprite_tilemap(&CHICKEN_TILES); + object.enable(); let mut chicken = Character { object: object.get_object_standard(), diff --git a/agb/src/display/example_logo.rs b/agb/src/display/example_logo.rs index 4653c00..ec56af3 100644 --- a/agb/src/display/example_logo.rs +++ b/agb/src/display/example_logo.rs @@ -17,7 +17,7 @@ pub fn display_logo(gfx: &mut Tiled0) { } back.set_map(Map { - store: &mut entries, + store: &entries, dimensions: (30_u32, 20_u32).into(), default: 0, }); diff --git a/agb/src/display/object.rs b/agb/src/display/object.rs index 2e1b670..1cefa2a 100644 --- a/agb/src/display/object.rs +++ b/agb/src/display/object.rs @@ -1,12 +1,16 @@ use core::cell::RefCell; -use super::{Priority, DISPLAY_CONTROL}; +use super::{palette16, Priority, DISPLAY_CONTROL}; use crate::bitarray::Bitarray; use crate::memory_mapped::MemoryMapped1DArray; use crate::number::Vector2D; const OBJECT_ATTRIBUTE_MEMORY: MemoryMapped1DArray = unsafe { MemoryMapped1DArray::new(0x0700_0000) }; +const PALETTE_SPRITE: MemoryMapped1DArray = + unsafe { MemoryMapped1DArray::new(0x0500_0200) }; +const TILE_SPRITE: MemoryMapped1DArray = + unsafe { MemoryMapped1DArray::new(0x06010000) }; /// Handles distributing objects and matricies along with operations that effect all objects. pub struct ObjectControl { @@ -310,6 +314,39 @@ impl ObjectControl { } } + fn set_sprite_tilemap_entry(&self, index: usize, data: u32) { + TILE_SPRITE.set(index, data); + } + + /// Copies raw palettes to the background palette without any checks. + pub fn set_sprite_palette_raw(&self, colour: &[u16]) { + for (index, &entry) in colour.iter().enumerate() { + self.set_sprite_palette_entry(index, entry) + } + } + fn set_sprite_palette_entry(&self, index: usize, colour: u16) { + PALETTE_SPRITE.set(index, colour) + } + + fn set_sprite_palette(&self, pal_index: u8, palette: &palette16::Palette16) { + for (colour_index, &colour) in palette.colours.iter().enumerate() { + PALETTE_SPRITE.set(pal_index as usize * 16 + colour_index, colour); + } + } + + pub fn set_sprite_palettes(&self, palettes: &[palette16::Palette16]) { + for (palette_index, entry) in palettes.iter().enumerate() { + self.set_sprite_palette(palette_index as u8, entry) + } + } + + /// Copies tiles to the sprite tilemap without any checks. + pub fn set_sprite_tilemap(&self, tiles: &[u32]) { + for (index, &tile) in tiles.iter().enumerate() { + self.set_sprite_tilemap_entry(index, tile) + } + } + /// Enable objects on the GBA. pub fn enable(&mut self) { let disp = DISPLAY_CONTROL.get(); diff --git a/agb/src/display/tiled0.rs b/agb/src/display/tiled0.rs index 64fb5a9..0811a68 100644 --- a/agb/src/display/tiled0.rs +++ b/agb/src/display/tiled0.rs @@ -1,3 +1,5 @@ +use core::ops::{Deref, Index}; + use crate::{ memory_mapped::{MemoryMapped, MemoryMapped1DArray}, number::{Rect, Vector2D}, @@ -31,23 +33,26 @@ pub enum BackgroundSize { /// The map background is the method of drawing game maps to the screen. It /// automatically handles copying the correct portion of a provided map to the /// assigned block depending on given coordinates. -pub struct Background<'a> { +pub struct Background + ?Sized, D: Deref> { background: u8, block: u8, commited_position: Vector2D, shadowed_position: Vector2D, poisoned: bool, shadowed_register: u16, - map: Option>, + map: Option>, } -pub struct Map<'a> { - pub store: &'a mut [u16], +pub struct Map> +where + S: Index + ?Sized, +{ + pub store: D, pub dimensions: Vector2D, pub default: u16, } -impl<'a> Map<'a> { +impl<'a, S: Index + ?Sized, D: Deref> Map { fn get_position(&self, x: i32, y: i32) -> u16 { if x < 0 || x as u32 >= self.dimensions.x { self.default @@ -59,8 +64,8 @@ impl<'a> Map<'a> { } } -impl<'a> Background<'a> { - unsafe fn new(background: u8, block: u8) -> Background<'a> { +impl<'a, S: Index + ?Sized, D: Deref> Background { + unsafe fn new(background: u8, block: u8) -> Background { let mut b = Background { background, block, @@ -129,12 +134,13 @@ impl<'a> Background<'a> { self.shadowed_position = position; } - pub fn get_map(&mut self) -> &mut Option> { + pub fn get_map(&mut self) -> Option<&mut Map> { self.poisoned = true; - &mut self.map + self.map.as_mut() } - pub fn set_map(&mut self, map: Map<'a>) { + pub fn set_map(&mut self, map: Map) { + self.poisoned = true; self.map = Some(map); } @@ -259,7 +265,9 @@ impl Tiled0 { } /// Gets a map background if possible and assigns an unused block to it. - pub fn get_background(&mut self) -> Result { + pub fn get_background + ?Sized, D: Deref>( + &mut self, + ) -> Result, &'static str> { if self.num_backgrounds >= 4 { return Err("too many backgrounds created, maximum is 4"); }