going back and forth on this, let's try calling it text mode for a while

This commit is contained in:
Lokathor 2022-10-07 22:16:54 -06:00
parent 710d35e207
commit 1f79340c28
6 changed files with 36 additions and 50 deletions

View file

@ -48,11 +48,11 @@ extern "C" fn main() -> ! {
{ {
// the the tilemap set up // the the tilemap set up
let tsb = TileScreenblock::new(31); let tsb = TextScreenblock::new(31);
for row in 0..16_usize { for row in 0..16_usize {
for col in 0..16_usize { for col in 0..16_usize {
let id = row * 16 + col; let id = row * 16 + col;
let entry = TileEntry::new().with_tile_id(id as u16); let entry = TextEntry::new().with_tile_id(id as u16);
tsb.row_col(row, col).write(entry); tsb.row_col(row, col).write(entry);
} }
} }

View file

@ -32,7 +32,7 @@ use crate::{
interrupts::IrqBits, interrupts::IrqBits,
video::{ video::{
BackgroundControl, Color, DisplayControl, DisplayStatus, WindowInside, BackgroundControl, Color, DisplayControl, DisplayStatus, WindowInside,
WindowOutside, Mosaic, BlendControl, Tile4, ObjAttr0, ObjAttr1, ObjAttr2, Tile8, TileEntry WindowOutside, Mosaic, BlendControl, Tile4, ObjAttr0, ObjAttr1, ObjAttr2, Tile8, TextEntry
}, },
dma::DmaControl, dma::DmaControl,
sound::{ sound::{
@ -257,7 +257,7 @@ macro_rules! make_me_a_screenblock {
} }
} }
make_me_a_screenblock!(TileScreenblock(TileEntry), size: 32, max_index: 32); make_me_a_screenblock!(TextScreenblock(TextEntry), size: 32, max_index: 32);
make_me_a_screenblock!(AffineScreenBlock0(u8), size: 16, max_index: 32); make_me_a_screenblock!(AffineScreenBlock0(u8), size: 16, max_index: 32);
make_me_a_screenblock!(AffineScreenBlock1(u8), size: 32, max_index: 32); make_me_a_screenblock!(AffineScreenBlock1(u8), size: 32, max_index: 32);
make_me_a_screenblock!(AffineScreenBlock2(u8), size: 64, max_index: 30); make_me_a_screenblock!(AffineScreenBlock2(u8), size: 64, max_index: 30);

View file

@ -17,28 +17,40 @@
//! "sprites" within a game. Because there isn't an exact 1:1 mapping between //! "sprites" within a game. Because there isn't an exact 1:1 mapping between
//! sprites and objects, these docs will attempt to only talk about objects. //! sprites and objects, these docs will attempt to only talk about objects.
//! //!
//! ## Color And Bit Depth //! ## Color, Bit Depth, and Palettes
//! //!
//! [Color] values on the GBA are 5-bits-per-channel RGB values. They're always //! [Color] values on the GBA are 5-bits-per-channel RGB values. They're always
//! stored packed and aligned to 2, so think of them as being like a `u16`. //! bit-packed and aligned to 2, so think of them as being like a `u16`.
//! //!
//! Because of the GBA's limited memory, image data will rarely be stored with //! Because of the GBA's limited memory, most images don't use direct color (one
//! one full color value per pixel. Instead they'll be stored as //! color per pixel). Instead they use indexed color (one *palette index* per
//! 4-bits-per-pixel (4bpp) or 8-bits-per-pixel (8bpp). In both cases, each //! pixel). Indexed image data can be 4-bits-per-pixel (4bpp) or
//! pixel is an index into the PALRAM (either the [`BG_PALETTE`] or //! 8-bits-per-pixel (8bpp). In either case, the color values themselves are
//! [`OBJ_PALETTE`]), which stores the color to draw. This is known as "indexed" //! stored in the PALRAM region. When used as a background, the [`BG_PALETTE`]
//! or "paletted" color. //! is used, and when used as an object the [`OBJ_PALETTE`] is used. Both
//! palettes have 256 slots. The palettes are always indexed with 8 bits total,
//! but how those bits are determined depends on the bit depth of the image:
//! * Things drawing with 8bpp image data index into the full range of the
//! palette directly.
//! * Things drawing with 4bpp image data will also have a "palbank" setting.
//! The palbank acts as the upper 4 bits of the index, selecting which block
//! of 16 palette entries the that thing will be able to use. Then each 4-bit
//! pixel within the image indexes within the palbank.
//! //!
//! Each palette has 256 slots. The palettes are always indexed with 8 bits //! In both 8bpp and 4bpp modes, if a pixel's value is 0 then that pixel is
//! total, but how those bits are determined depends on the bit depth of the //! transparent. So 8bpp images can use 255 colors (+ transparent), and 4bpp
//! image: //! images can use 15 colors (+ transparent). Each background layer and each
//! * 8bpp images index into the full range of the palette directly. //! object can individually be set for 4bpp or 8bpp mode.
//! * 4bpp images are always associated with a "palbank". The palbank acts as //!
//! the upper 4 bits of the index, selecting which block of 16 palette entries //! ## Tiles, Screenblocks, and Charblocks
//! the image will be able to use. Then each 4-bit pixel within the image //!
//! indexes into that palbank. //! Regardless of their bit depth, a tile is always an 8x8 area. This means that
//! * In both 8bpp and 4bpp modes, if a pixel's value is 0 then that pixel is //! they're either 32 bytes (4bpp) or 64 bytes (8bpp). Since VRAM starts aligned
//! transparent. //! to 4, and since both size tiles are a multiple of 4 bytes large, we model
//! tile data as `u32` arrays rather than `u8` arrays. Having the data stay
//! aligned to 4 gives a significant speed gain when moving entire tiles around.
//!
//! The layout of tiles is a "screenblock". This is a square of entries
//! //!
//! ## Priority //! ## Priority
//! //!
@ -68,10 +80,6 @@ use crate::macros::{
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::prelude::*; use crate::prelude::*;
pub mod affine_backgrounds;
pub mod bitmap_backgrounds;
pub mod tiled_backgrounds;
/// An RGB555 color value (packed into `u16`). /// An RGB555 color value (packed into `u16`).
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)] #[repr(transparent)]
@ -241,8 +249,8 @@ pub type Tile8 = [u32; 16];
/// mode this has no effect. /// mode this has no effect.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)] #[repr(transparent)]
pub struct TileEntry(u16); pub struct TextEntry(u16);
impl TileEntry { impl TextEntry {
pub_const_fn_new_zeroed!(); pub_const_fn_new_zeroed!();
u16_int_field!(0 - 9, tile_id, with_tile_id); u16_int_field!(0 - 9, tile_id, with_tile_id);
u16_bool_field!(10, hflip, with_hflip); u16_bool_field!(10, hflip, with_hflip);

View file

@ -1,22 +0,0 @@
//! Tiled background documentation (no code).
//!
//! When in tiled mode a background shows 2D tiles. This is sometimes called
//! "text" mode because it's the same style of graphics that was once used for
//! text terminal displays. The first 64k of VRAM is treated as a collection of
//! **tiles** and **screenblocks**.
//!
//! * A tile is 8x8 pixels. Tiles can be either 4bpp (32 bytes) or 8bpp (64
//! bytes). Each background layer can use a different bit depth.
//! * A screenblock is 32x32 [`TileEntry`] values (2,048 bytes).
//! * Each background has a `size` value set by its [BackgroundControl]. This
//! determines how many tilemaps in a row are actually used to draw the
//! background:
//! * 0: one tilemap
//! * 1: two tilemaps horizontally: left then right.
//! * 2: two tilemaps vertically: top then bottom.
//! * 3: four tilemaps in a square: upper left, upper right, lower left, lower
//! right.
// this makes the doclinks work right.
#[allow(unused_imports)]
use crate::prelude::*;