mirror of
https://github.com/italicsjenga/gba.git
synced 2024-12-23 19:01:30 +11:00
make the tile layout during const time.
This commit is contained in:
parent
3a882fed29
commit
1af762bde6
|
@ -15,13 +15,41 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[link_section = ".ewram"]
|
||||||
static FRAME_KEYS: GbaCell<KeyInput> = GbaCell::new(KeyInput::new());
|
static FRAME_KEYS: GbaCell<KeyInput> = GbaCell::new(KeyInput::new());
|
||||||
|
|
||||||
|
#[link_section = ".iwram"]
|
||||||
extern "C" fn irq_handler(_: IrqBits) {
|
extern "C" fn irq_handler(_: IrqBits) {
|
||||||
// We'll read the keys during vblank and store it for later.
|
// We'll read the keys during vblank and store it for later.
|
||||||
FRAME_KEYS.write(KEYINPUT.read());
|
FRAME_KEYS.write(KEYINPUT.read());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TILE_LAYOUT: [u32; 512] = {
|
||||||
|
// Rust's const eval is limited at the moment, but with a bit of careful math
|
||||||
|
// we can set up `u32` values that store the right data. Tile maps are 32x32
|
||||||
|
// `u16` values, so when packing it as `u32` instead we have to throw in some
|
||||||
|
// `/2` stuff in a few places. Seperately, the tiles that we're using come
|
||||||
|
// from an image that was drawn as a 16 by 16 tile sheet, so most of the
|
||||||
|
// layout's area will be left as zero. Thankfully, tile index 0 is a blank
|
||||||
|
// tile in this tileset, so it all works out.
|
||||||
|
let mut data = [0; 512];
|
||||||
|
let mut r = 0;
|
||||||
|
while r < 16 {
|
||||||
|
let mut c = 0;
|
||||||
|
while c < 16 {
|
||||||
|
let index = r * (32 / 2) + (c / 2);
|
||||||
|
let a = r * 16 + c;
|
||||||
|
let b = r * 16 + c + 1;
|
||||||
|
data[index] = (a as u32) | ((b as u32) << 16);
|
||||||
|
//
|
||||||
|
c += 2;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
r += 1;
|
||||||
|
}
|
||||||
|
data
|
||||||
|
};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn main() -> ! {
|
extern "C" fn main() -> ! {
|
||||||
RUST_IRQ_HANDLER.write(Some(irq_handler));
|
RUST_IRQ_HANDLER.write(Some(irq_handler));
|
||||||
|
@ -47,15 +75,9 @@ extern "C" fn main() -> ! {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// the the tilemap set up
|
// get the the tilemap copied into place
|
||||||
let tsb = TextScreenblock::new(31);
|
let tsb = TextScreenblock::new(31);
|
||||||
for row in 0..16_usize {
|
tsb.write_words(&TILE_LAYOUT);
|
||||||
for col in 0..16_usize {
|
|
||||||
let id = row * 16 + col;
|
|
||||||
let entry = TextEntry::new().with_tile_id(id as u16);
|
|
||||||
tsb.row_col(row, col).write(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
15
src/mmio.rs
15
src/mmio.rs
|
@ -255,6 +255,21 @@ macro_rules! make_me_a_screenblock {
|
||||||
assert!(col < $size, concat!("`col` must be less than ", $size));
|
assert!(col < $size, concat!("`col` must be less than ", $size));
|
||||||
self.block.index(row * $size + col)
|
self.block.index(row * $size + col)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const WORD_COUNT: usize = (size_of::<$t>() * $size * $size)/4;
|
||||||
|
const _DEBUG_CHECK: () = {
|
||||||
|
assert!((size_of::<$t>() * $size * $size) % 4 == 0);
|
||||||
|
()
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Overwrites the entire screenblock with the data provided.
|
||||||
|
pub fn write_words(self, words: &[u32; Self::WORD_COUNT]) {
|
||||||
|
use crate::prelude::__aeabi_memcpy4;
|
||||||
|
let dest: *mut u32 = self.block.index(0).as_usize() as *mut u32;
|
||||||
|
let src: *const u32 = words.as_ptr();
|
||||||
|
let byte_count = size_of::<[u32; Self::WORD_COUNT]>();
|
||||||
|
unsafe { __aeabi_memcpy4(dest.cast(), src.cast(), byte_count) };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -264,7 +264,7 @@ pub type Tile8 = [u32; 16];
|
||||||
|
|
||||||
/// An entry within a tile mode tilemap.
|
/// An entry within a tile mode tilemap.
|
||||||
///
|
///
|
||||||
/// * `tile_id` is the index of the tile, offset from the `charblock` that the
|
/// * `tile` is the index of the tile, offset from the `charblock` that the
|
||||||
/// background is using. This is a 10-bit value, so indexes are in the range
|
/// background is using. This is a 10-bit value, so indexes are in the range
|
||||||
/// `0..=1023`. You *cannot* index past the end of background VRAM into object
|
/// `0..=1023`. You *cannot* index past the end of background VRAM into object
|
||||||
/// VRAM (it just won't draw properly), but you *can* index past the end of
|
/// VRAM (it just won't draw properly), but you *can* index past the end of
|
||||||
|
@ -278,10 +278,17 @@ pub type Tile8 = [u32; 16];
|
||||||
pub struct TextEntry(u16);
|
pub struct TextEntry(u16);
|
||||||
impl TextEntry {
|
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, with_tile);
|
||||||
u16_bool_field!(10, hflip, with_hflip);
|
u16_bool_field!(10, hflip, with_hflip);
|
||||||
u16_bool_field!(11, vflip, with_vflip);
|
u16_bool_field!(11, vflip, with_vflip);
|
||||||
u16_int_field!(12 - 15, palbank, with_palbank);
|
u16_int_field!(12 - 15, palbank, with_palbank);
|
||||||
|
|
||||||
|
/// Shorthand for `TextEntry::new().with_tile(id)`
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
|
pub const fn from_tile(id: u16) -> Self {
|
||||||
|
Self(id & 0b11_1111_1111)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
|
Loading…
Reference in a new issue