diff --git a/agb/examples/chicken.rs b/agb/examples/chicken.rs index bcb48aa..4d5d2e1 100644 --- a/agb/examples/chicken.rs +++ b/agb/examples/chicken.rs @@ -2,8 +2,8 @@ #![no_main] use agb::{ - display::tiled::{TileFormat, TileSet}, - display::{background::TileSetting, object::ObjectStandard, HEIGHT, WIDTH}, + display::tiled::{TileFormat, TileSet, TileSetting}, + display::{object::ObjectStandard, HEIGHT, WIDTH}, input::Button, }; use core::convert::TryInto; diff --git a/agb/src/display/background.rs b/agb/src/display/background.rs index 9d703ea..8bbafc2 100644 --- a/agb/src/display/background.rs +++ b/agb/src/display/background.rs @@ -4,196 +4,15 @@ use core::ops::{Deref, DerefMut}; use alloc::boxed::Box; pub use super::tiled::VRamManager; -use super::tiled::{TileIndex, TileSetReference}; +use super::tiled::{RegularMap, TileSetReference, TileSetting}; use crate::bitarray::Bitarray; use crate::{ display, fixnum::{Rect, Vector2D}, - memory_mapped::{MemoryMapped, MemoryMapped1DArray}, }; -use super::{ - set_graphics_mode, set_graphics_settings, DisplayMode, GraphicsSettings, Priority, - DISPLAY_CONTROL, -}; - -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -#[repr(transparent)] -struct Tile(u16); - -impl Tile { - fn new(idx: TileIndex, setting: TileSetting) -> Self { - Self(idx.index() | setting.setting()) - } - - fn tile_index(self) -> TileIndex { - TileIndex::new(self.0 & ((1 << 10) - 1)) - } -} - -#[derive(Clone, Copy, Debug, Default)] -pub struct TileSetting(u16); - -impl TileSetting { - pub const fn new(tile_id: u16, hflip: bool, vflip: bool, palette_id: u8) -> Self { - Self( - (tile_id & ((1 << 10) - 1)) - | ((hflip as u16) << 10) - | ((vflip as u16) << 11) - | ((palette_id as u16) << 12), - ) - } - - pub const fn from_raw(raw: u16) -> Self { - Self(raw) - } - - fn index(self) -> u16 { - self.0 & ((1 << 10) - 1) - } - - fn setting(self) -> u16 { - self.0 & !((1 << 10) - 1) - } -} - -pub struct RegularMap { - background_id: u8, - - screenblock: u8, - x_scroll: u16, - y_scroll: u16, - priority: Priority, - - tiles: [Tile; 32 * 32], - tiles_dirty: bool, -} - -pub const TRANSPARENT_TILE_INDEX: u16 = (1 << 10) - 1; - -impl RegularMap { - fn new(background_id: u8, screenblock: u8, priority: Priority) -> Self { - Self { - background_id, - - screenblock, - x_scroll: 0, - y_scroll: 0, - priority, - - tiles: [Tile::default(); 32 * 32], - tiles_dirty: true, - } - } - - pub fn set_tile( - &mut self, - vram: &mut VRamManager, - pos: Vector2D, - tileset_ref: TileSetReference, - tile_setting: TileSetting, - ) { - let pos = (pos.x + pos.y * 32) as usize; - - let old_tile = self.tiles[pos]; - if old_tile != Tile::default() { - vram.remove_tile(old_tile.tile_index()); - } - - let tile_index = tile_setting.index(); - - let new_tile = if tile_index != TRANSPARENT_TILE_INDEX { - let new_tile_idx = vram.add_tile(tileset_ref, tile_index); - Tile::new(new_tile_idx, tile_setting) - } else { - Tile::default() - }; - - if old_tile == new_tile { - // no need to mark as dirty if nothing changes - return; - } - - self.tiles[pos] = new_tile; - self.tiles_dirty = true; - } - - pub fn clear(&mut self, vram: &mut VRamManager) { - for tile in self.tiles.iter_mut() { - vram.remove_tile(tile.tile_index()); - - *tile = Tile::default(); - } - } - - pub fn show(&mut self) { - let mode = DISPLAY_CONTROL.get(); - let new_mode = mode | (1 << (self.background_id + 0x08)); - DISPLAY_CONTROL.set(new_mode); - } - - pub fn hide(&mut self) { - let mode = DISPLAY_CONTROL.get(); - let new_mode = mode & !(1 << (self.background_id + 0x08)); - DISPLAY_CONTROL.set(new_mode); - } - - pub fn commit(&mut self) { - let new_bg_control_value = (self.priority as u16) | ((self.screenblock as u16) << 8); - - self.bg_control_register().set(new_bg_control_value); - self.bg_h_offset().set(self.x_scroll); - self.bg_v_offset().set(self.y_scroll); - - if !self.tiles_dirty { - return; - } - - let screenblock_memory = self.screenblock_memory(); - - let scroll_pos = self.get_scroll_pos(); - let start_x = scroll_pos.x / 8; - let end_x = div_ceil(scroll_pos.x as i32 + display::WIDTH, 8) as u16 + 1; - - let start_y = scroll_pos.y / 8; - let end_y = div_ceil(scroll_pos.y as i32 + display::HEIGHT, 8) as u16 + 1; - - for y in start_y..end_y { - for x in start_x..end_x { - let id = y.rem_euclid(32) * 32 + x.rem_euclid(32); - screenblock_memory.set(id as usize, self.tiles[id as usize].0); - } - } - - self.tiles_dirty = false; - } - - pub fn set_scroll_pos(&mut self, pos: Vector2D) { - self.x_scroll = pos.x; - self.y_scroll = pos.y; - } - - pub fn get_scroll_pos(&self) -> Vector2D { - (self.x_scroll, self.y_scroll).into() - } - - const fn bg_control_register(&self) -> MemoryMapped { - unsafe { MemoryMapped::new(0x0400_0008 + 2 * self.background_id as usize) } - } - - const fn bg_h_offset(&self) -> MemoryMapped { - unsafe { MemoryMapped::new(0x0400_0010 + 4 * self.background_id as usize) } - } - - const fn bg_v_offset(&self) -> MemoryMapped { - unsafe { MemoryMapped::new(0x0400_0012 + 4 * self.background_id as usize) } - } - - const fn screenblock_memory(&self) -> MemoryMapped1DArray { - unsafe { MemoryMapped1DArray::new(0x0600_0000 + 0x1000 * self.screenblock as usize / 2) } - } -} +use super::{set_graphics_mode, set_graphics_settings, DisplayMode, GraphicsSettings, Priority}; pub struct InfiniteScrolledMap<'a> { map: MapLoan<'a, RegularMap>, diff --git a/agb/src/display/example_logo.rs b/agb/src/display/example_logo.rs index 03ba275..46db1af 100644 --- a/agb/src/display/example_logo.rs +++ b/agb/src/display/example_logo.rs @@ -1,7 +1,4 @@ -use super::{ - background::{RegularMap, TileSetting}, - tiled::{TileFormat, TileSet, VRamManager}, -}; +use super::tiled::{RegularMap, TileFormat, TileSet, TileSetting, VRamManager}; crate::include_gfx!("gfx/agb_logo.toml"); diff --git a/agb/src/display/tiled/mod.rs b/agb/src/display/tiled/mod.rs index be39b22..d88ad60 100644 --- a/agb/src/display/tiled/mod.rs +++ b/agb/src/display/tiled/mod.rs @@ -1,3 +1,45 @@ +mod map; mod vram_manager; +pub use map::RegularMap; pub use vram_manager::{TileFormat, TileIndex, TileSet, TileSetReference, VRamManager}; + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +#[repr(transparent)] +struct Tile(u16); + +impl Tile { + fn new(idx: TileIndex, setting: TileSetting) -> Self { + Self(idx.index() | setting.setting()) + } + + fn tile_index(self) -> TileIndex { + TileIndex::new(self.0 & ((1 << 10) - 1)) + } +} + +#[derive(Clone, Copy, Debug, Default)] +pub struct TileSetting(u16); + +impl TileSetting { + pub const fn new(tile_id: u16, hflip: bool, vflip: bool, palette_id: u8) -> Self { + Self( + (tile_id & ((1 << 10) - 1)) + | ((hflip as u16) << 10) + | ((vflip as u16) << 11) + | ((palette_id as u16) << 12), + ) + } + + pub const fn from_raw(raw: u16) -> Self { + Self(raw) + } + + fn index(self) -> u16 { + self.0 & ((1 << 10) - 1) + } + + fn setting(self) -> u16 { + self.0 & !((1 << 10) - 1) + } +}