clearer module organization

This commit is contained in:
Lokathor 2018-12-26 23:13:10 -07:00
parent 6271614335
commit 72bbe412b6
13 changed files with 145 additions and 136 deletions

View file

@ -7,9 +7,10 @@ use gba::{
display::{DisplayControlSetting, DISPCNT}, display::{DisplayControlSetting, DISPCNT},
}, },
palram::index_palram_bg_4bpp, palram::index_palram_bg_4bpp,
video::tiled::{TextScreenblockEntry, Tile4bpp, VRAM_CHARBLOCKS, VRAM_TEXT_SCREENBLOCKS}, vram::text::{TextScreenblockEntry},
Color, Color,
}; };
use gba::vram::{Tile4bpp, CHAR_BASE_BLOCKS, SCREEN_BASE_BLOCKS};
#[panic_handler] #[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! { fn panic(_info: &core::panic::PanicInfo) -> ! {
@ -52,11 +53,11 @@ pub const ALL_THREES: Tile4bpp = Tile4bpp([
pub fn set_bg_tile_4bpp(charblock: usize, index: usize, tile: Tile4bpp) { pub fn set_bg_tile_4bpp(charblock: usize, index: usize, tile: Tile4bpp) {
assert!(charblock < 4); assert!(charblock < 4);
assert!(index < 512); assert!(index < 512);
unsafe { VRAM_CHARBLOCKS.index(charblock).cast::<Tile4bpp>().offset(index as isize).write(tile) } unsafe { CHAR_BASE_BLOCKS.index(charblock).cast::<Tile4bpp>().offset(index as isize).write(tile) }
} }
pub fn checker_screenblock(slot: usize, a_entry: TextScreenblockEntry, b_entry: TextScreenblockEntry) { pub fn checker_screenblock(slot: usize, a_entry: TextScreenblockEntry, b_entry: TextScreenblockEntry) {
let mut p = unsafe { VRAM_TEXT_SCREENBLOCKS.index(slot).cast::<TextScreenblockEntry>() }; let mut p = unsafe { SCREEN_BASE_BLOCKS.index(slot).cast::<TextScreenblockEntry>() };
let mut checker = true; let mut checker = true;
for _row in 0..32 { for _row in 0..32 {
for _col in 0..32 { for _col in 0..32 {

View file

@ -4,7 +4,7 @@
use gba::{ use gba::{
io::display::{DisplayControlSetting, DisplayMode, DISPCNT}, io::display::{DisplayControlSetting, DisplayMode, DISPCNT},
video::bitmap::Mode3, vram::bitmap::Mode3,
Color, Color,
}; };

View file

@ -7,7 +7,7 @@ use gba::{
display::{spin_until_vblank, spin_until_vdraw, DisplayControlSetting, DisplayMode, DISPCNT}, display::{spin_until_vblank, spin_until_vdraw, DisplayControlSetting, DisplayMode, DISPCNT},
keypad::read_key_input, keypad::read_key_input,
}, },
video::bitmap::Mode3, vram::bitmap::Mode3,
Color, Color,
}; };

View file

@ -4,7 +4,7 @@
use gba::{ use gba::{
io::display::{DisplayControlSetting, DisplayMode, DISPCNT}, io::display::{DisplayControlSetting, DisplayMode, DISPCNT},
video::bitmap::Mode3, vram::bitmap::Mode3,
Color, Color,
}; };

View file

@ -2,6 +2,8 @@
use core::{cmp::Ordering, iter::FusedIterator, marker::PhantomData, num::NonZeroUsize}; use core::{cmp::Ordering, iter::FusedIterator, marker::PhantomData, num::NonZeroUsize};
// TODO: striding block/iter
/// Abstracts the use of a volatile hardware address. /// Abstracts the use of a volatile hardware address.
/// ///
/// If you're trying to do anything other than abstract a volatile hardware /// If you're trying to do anything other than abstract a volatile hardware

View file

@ -2,13 +2,13 @@
use super::*; use super::*;
// BG0 Control. Read/Write. // BG0 Control. Read/Write. Display Mode 0/1 only.
pub const BG0CNT: VolAddress<BackgroundControlSetting> = unsafe { VolAddress::new_unchecked(0x400_0008) }; pub const BG0CNT: VolAddress<BackgroundControlSetting> = unsafe { VolAddress::new_unchecked(0x400_0008) };
// BG1 Control. Read/Write. // BG1 Control. Read/Write. Display Mode 0/1 only.
pub const BG1CNT: VolAddress<BackgroundControlSetting> = unsafe { VolAddress::new_unchecked(0x400_000A) }; pub const BG1CNT: VolAddress<BackgroundControlSetting> = unsafe { VolAddress::new_unchecked(0x400_000A) };
// BG2 Control. Read/Write. // BG2 Control. Read/Write. Display Mode 0/1/2 only.
pub const BG2CNT: VolAddress<BackgroundControlSetting> = unsafe { VolAddress::new_unchecked(0x400_000C) }; pub const BG2CNT: VolAddress<BackgroundControlSetting> = unsafe { VolAddress::new_unchecked(0x400_000C) };
// BG3 Control. Read/Write. // BG3 Control. Read/Write. Display Mode 0/2 only.
pub const BG3CNT: VolAddress<BackgroundControlSetting> = unsafe { VolAddress::new_unchecked(0x400_000E) }; pub const BG3CNT: VolAddress<BackgroundControlSetting> = unsafe { VolAddress::new_unchecked(0x400_000E) };
newtype! { newtype! {
@ -19,7 +19,7 @@ newtype! {
/// Bit 6: Mosaic mode /// Bit 6: Mosaic mode
/// Bit 7: is 8bpp /// Bit 7: is 8bpp
/// Bit 8-12: Screen Base Block (0 through 31, 2k each) /// Bit 8-12: Screen Base Block (0 through 31, 2k each)
/// Bit 13: Display area overflow wraps (otherwise transparent, affine only) /// Bit 13: Display area overflow wraps (otherwise transparent, affine BG only)
/// Bit 14-15: Screen Size /// Bit 14-15: Screen Size
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)] #[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
BackgroundControlSetting, u16 BackgroundControlSetting, u16
@ -93,7 +93,7 @@ pub const BG3HOFS: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_00
// BG3 Y-Offset. Write only. Text mode only. 9 bits. // BG3 Y-Offset. Write only. Text mode only. 9 bits.
pub const BG3VOFS: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_001E) }; pub const BG3VOFS: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_001E) };
// TODO: affine registers: // TODO: affine backgrounds
// BG2X_L // BG2X_L
// BG2X_H // BG2X_H
// BG2Y_L // BG2Y_L
@ -115,40 +115,6 @@ pub const BG3VOFS: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_00
// pub const WININ: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_0048) }; // pub const WININ: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_0048) };
// pub const WINOUT: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_004A) }; // pub const WINOUT: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_004A) };
/// Global mosaic effect control. Write-only.
pub const MOSAIC: VolAddress<MosaicSetting> = unsafe { VolAddress::new_unchecked(0x400_004C) };
newtype! {
/// Allows control of the Mosaic effect.
///
/// Values are the _increase_ for each top-left pixel to be duplicated in the
/// final result. If you want to duplicate some other pixel than the top-left,
/// you can offset the background or object by an appropriate amount.
///
/// 0) No effect (1+0)
/// 1) Each pixel becomes 2 pixels (1+1)
/// 2) Each pixel becomes 3 pixels (1+2)
/// 3) Each pixel becomes 4 pixels (1+3)
///
/// * Bits 0-3: BG mosaic horizontal increase
/// * Bits 4-7: BG mosaic vertical increase
/// * Bits 8-11: Object mosaic horizontal increase
/// * Bits 12-15: Object mosaic vertical increase
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
MosaicSetting, u16
}
impl MosaicSetting {
multi_bits!(
u16,
[
(0, 4, bg_horizontal_inc),
(4, 4, bg_vertical_inc),
(8, 4, obj_horizontal_inc),
(12, 4, obj_vertical_inc),
]
);
}
// pub const BLDCNT: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_0050) }; // pub const BLDCNT: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_0050) };
// pub const BLDALPHA: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_0052) }; // pub const BLDALPHA: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_0052) };
// pub const BLDY: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_0054) }; // pub const BLDY: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_0054) };

View file

@ -4,7 +4,7 @@ use super::*;
/// LCD Control. Read/Write. /// LCD Control. Read/Write.
/// ///
/// The "force vblank" bit is always set when your rust code first executes. /// The "force vblank" bit is always set when your Rust code first executes.
pub const DISPCNT: VolAddress<DisplayControlSetting> = unsafe { VolAddress::new_unchecked(0x400_0000) }; pub const DISPCNT: VolAddress<DisplayControlSetting> = unsafe { VolAddress::new_unchecked(0x400_0000) };
newtype!( newtype!(
@ -101,7 +101,7 @@ pub fn display_control() -> DisplayControlSetting {
DISPCNT.read() DISPCNT.read()
} }
/// Display Status and IRQ Control. /// Display Status and IRQ Control. Read/Write.
pub const DISPSTAT: VolAddress<DisplayStatusSetting> = unsafe { VolAddress::new_unchecked(0x400_0004) }; pub const DISPSTAT: VolAddress<DisplayStatusSetting> = unsafe { VolAddress::new_unchecked(0x400_0004) };
newtype!( newtype!(
@ -154,3 +154,37 @@ pub fn spin_until_vdraw() {
// TODO: make this the better version with BIOS and interrupts and such. // TODO: make this the better version with BIOS and interrupts and such.
while vcount() >= VBLANK_SCANLINE {} while vcount() >= VBLANK_SCANLINE {}
} }
/// Global mosaic effect control. Write-only.
pub const MOSAIC: VolAddress<MosaicSetting> = unsafe { VolAddress::new_unchecked(0x400_004C) };
newtype! {
/// Allows control of the Mosaic effect.
///
/// Values are the _increase_ for each top-left pixel to be duplicated in the
/// final result. If you want to duplicate some other pixel than the top-left,
/// you can offset the background or object by an appropriate amount.
///
/// 0) No effect (1+0)
/// 1) Each pixel becomes 2 pixels (1+1)
/// 2) Each pixel becomes 3 pixels (1+2)
/// 3) Each pixel becomes 4 pixels (1+3)
///
/// * Bits 0-3: BG mosaic horizontal increase
/// * Bits 4-7: BG mosaic vertical increase
/// * Bits 8-11: Object mosaic horizontal increase
/// * Bits 12-15: Object mosaic vertical increase
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
MosaicSetting, u16
}
impl MosaicSetting {
multi_bits!(
u16,
[
(0, 4, bg_horizontal_inc),
(4, 4, bg_vertical_inc),
(8, 4, obj_horizontal_inc),
(12, 4, obj_vertical_inc),
]
);
}

View file

@ -66,7 +66,7 @@ pub mod bios;
pub mod io; pub mod io;
pub mod mgba; pub mod mgba;
pub mod palram; pub mod palram;
pub mod video; pub mod vram;
newtype! { newtype! {
/// A color on the GBA is an RGB 5.5.5 within a `u16` /// A color on the GBA is an RGB 5.5.5 within a `u16`

View file

@ -1,86 +0,0 @@
//! Module for tiled mode types and operations.
use super::*;
// Note(Lokathor): We've got several newtypes here that don't use the `newtype!`
// macro because it's insufficient at parsing array types being wrapped.
newtype! {
/// An 8x8 tile with 4bpp, packed as `u32` values for proper alignment.
#[derive(Debug, Clone, Copy, Default)]
Tile4bpp, pub [u32; 8], no frills
}
newtype! {
/// An 8x8 tile with 8bpp, packed as `u32` values for proper alignment.
#[derive(Debug, Clone, Copy, Default)]
Tile8bpp, pub [u32; 16], no frills
}
newtype! {
/// A 4bpp charblock has 512 tiles in it
#[derive(Clone, Copy)]
Charblock4bpp, pub [Tile4bpp; 512], no frills
}
newtype! {
/// An 8bpp charblock has 256 tiles in it
#[derive(Clone, Copy)]
Charblock8bpp, pub [Tile4bpp; 256], no frills
}
newtype! {
/// A screenblock entry for use in Text mode.
#[derive(Debug, Clone, Copy, Default)]
TextScreenblockEntry, u16
}
impl TextScreenblockEntry {
pub const fn from_tile_index(index: u16) -> Self {
TextScreenblockEntry(index & Self::TILE_ID_MASK)
}
bool_bits!(u16, [(10, hflip), (11, vflip)]);
multi_bits!(u16, [(0, 10, tile_id), (12, 4, palbank)]);
}
newtype! {
/// A screenblock for use in Text mode.
#[derive(Clone, Copy)]
TextScreenblock, [TextScreenblockEntry; 32 * 32], no frills
}
newtype! {
/// A screenblock entry for use in Affine mode.
#[derive(Debug, Clone, Copy, Default)]
AffineScreenblockEntry, u8
}
newtype! {
/// A screenblock for use in Affine mode.
#[derive(Clone, Copy)]
AffineScreenblock16x16, [AffineScreenblockEntry; 16*16], no frills
}
newtype! {
/// A screenblock for use in Affine mode.
#[derive(Clone, Copy)]
AffineScreenblock32x32, [AffineScreenblockEntry; 32*32], no frills
}
newtype! {
/// A screenblock for use in Affine mode.
#[derive(Clone, Copy)]
AffineScreenblock64x64, [AffineScreenblockEntry; 64*64], no frills
}
newtype! {
/// A screenblock for use in Affine mode.
#[derive(Clone, Copy)]
AffineScreenblock128x128, [AffineScreenblockEntry; 128*128], no frills
}
pub const VRAM_CHARBLOCKS: VolAddressBlock<Charblock4bpp> = unsafe { VolAddressBlock::new_unchecked(VolAddress::new_unchecked(VRAM_BASE_USIZE), 6) };
pub const VRAM_TEXT_SCREENBLOCKS: VolAddressBlock<TextScreenblock> =
unsafe { VolAddressBlock::new_unchecked(VolAddress::new_unchecked(VRAM_BASE_USIZE), 32) };

View file

@ -15,8 +15,9 @@
pub(crate) use super::*; pub(crate) use super::*;
pub mod affine;
pub mod bitmap; pub mod bitmap;
pub mod tiled; pub mod text;
/// The start of VRAM. /// The start of VRAM.
/// ///
@ -25,3 +26,34 @@ pub mod tiled;
/// value as just being a `usize`. Specific video mode types then wrap this as /// value as just being a `usize`. Specific video mode types then wrap this as
/// being the correct thing. /// being the correct thing.
pub const VRAM_BASE_USIZE: usize = 0x600_0000; pub const VRAM_BASE_USIZE: usize = 0x600_0000;
pub const CHAR_BASE_BLOCKS: VolAddressBlock<[u8; 0x4000]> = unsafe { VolAddressBlock::new_unchecked(VolAddress::new_unchecked(VRAM_BASE_USIZE), 6) };
pub const SCREEN_BASE_BLOCKS: VolAddressBlock<[u8; 0x800]> =
unsafe { VolAddressBlock::new_unchecked(VolAddress::new_unchecked(VRAM_BASE_USIZE), 32) };
newtype! {
/// An 8x8 tile with 4bpp, packed as `u32` values for proper alignment.
#[derive(Debug, Clone, Copy, Default)]
Tile4bpp, pub [u32; 8], no frills
}
newtype! {
/// An 8x8 tile with 8bpp, packed as `u32` values for proper alignment.
#[derive(Debug, Clone, Copy, Default)]
Tile8bpp, pub [u32; 16], no frills
}
/*
newtype! {
/// A 4bpp charblock has 512 tiles in it
#[derive(Clone, Copy)]
Charblock4bpp, pub [Tile4bpp; 512], no frills
}
newtype! {
/// An 8bpp charblock has 256 tiles in it
#[derive(Clone, Copy)]
Charblock8bpp, pub [Tile4bpp; 256], no frills
}
*/

31
src/vram/affine.rs Normal file
View file

@ -0,0 +1,31 @@
use super::*;
newtype! {
/// A screenblock entry for use in Affine mode.
#[derive(Debug, Clone, Copy, Default)]
AffineScreenblockEntry, u8
}
newtype! {
/// A 16x16 screenblock for use in Affine mode.
#[derive(Clone, Copy)]
AffineScreenblock16x16, [AffineScreenblockEntry; 16*16], no frills
}
newtype! {
/// A 32x32 screenblock for use in Affine mode.
#[derive(Clone, Copy)]
AffineScreenblock32x32, [AffineScreenblockEntry; 32*32], no frills
}
newtype! {
/// A 64x64 screenblock for use in Affine mode.
#[derive(Clone, Copy)]
AffineScreenblock64x64, [AffineScreenblockEntry; 64*64], no frills
}
newtype! {
/// A 128x128 screenblock for use in Affine mode.
#[derive(Clone, Copy)]
AffineScreenblock128x128, [AffineScreenblockEntry; 128*128], no frills
}

29
src/vram/text.rs Normal file
View file

@ -0,0 +1,29 @@
//! Module for tiled mode types and operations.
use super::*;
newtype! {
/// A screenblock entry for use in Text mode.
#[derive(Debug, Clone, Copy, Default)]
TextScreenblockEntry, u16
}
impl TextScreenblockEntry {
pub const fn from_tile_index(index: u16) -> Self {
TextScreenblockEntry(index & Self::TILE_ID_MASK)
}
bool_bits!(u16, [(10, hflip), (11, vflip)]);
multi_bits!(u16, [(0, 10, tile_id), (12, 4, palbank)]);
}
newtype! {
/// A screenblock for use in Text mode.
#[derive(Clone, Copy)]
TextScreenblock, [TextScreenblockEntry; 32 * 32], no frills
}
#[test]
pub fn test_text_screen_block_size() {
assert_eq!(core::mem::size_of::<TextScreenblock>(), 0x800);
}