Update to be closer to the API I actually want but currently only works in release mode

This commit is contained in:
Gwilym Kuiper 2022-09-22 23:29:58 +01:00
parent 59673206b3
commit 83c28254a1
8 changed files with 137 additions and 199 deletions

View file

@ -570,7 +570,7 @@ impl<I: FixedWidthUnsignedInteger, const N: usize> Debug for Num<I, N> {
}
/// A vector of two points: (x, y) represened by integers or fixed point numbers
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
#[repr(C)]
pub struct Vector2D<T: Number> {
/// The x coordinate

View file

@ -56,13 +56,9 @@ fn main(mut gba: agb::Gba) -> ! {
_ => {}
}
bg.set_scroll_pos((16 * 4, 16 * 4).into());
let scroll_pos = (scroll_x as i16, scroll_y as i16);
bg.set_transform(
scroll_pos,
(1, 1),
rotation,
);
bg.set_scroll_pos(scroll_pos.into());
bg.set_transform((0, 0), (1, 1), 0);
rotation += rotation_increase;
if rotation >= num!(255.) {

View file

@ -1197,7 +1197,7 @@ enum ColourMode {
/// that can apply to objects and background layers in modes 1 and 2.
/// This can be obtained from X/Y scale and rotation angle with
/// [`agb::syscall::affine_matrix`].
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(C, packed)]
pub struct AffineMatrixAttributes {
/// Adjustment made to *X* coordinate when drawing *horizontal* lines.
@ -1218,6 +1218,17 @@ pub struct AffineMatrixAttributes {
pub p_d: Num<i16, 8>,
}
impl Default for AffineMatrixAttributes {
fn default() -> Self {
Self {
p_a: 1.into(),
p_b: Default::default(),
p_c: Default::default(),
p_d: 1.into(),
}
}
}
// this mod is not public, so the internal parts don't need documenting.
#[allow(dead_code)]
mod attributes {

View file

@ -257,13 +257,9 @@ impl<'a> InfiniteScrolledMap<'a> {
let y_end = div_ceil(self.current_pos.y + display::HEIGHT, 8) + 1;
let offset = self.current_pos - (x_start * 8, y_start * 8).into();
let offset_scroll = (
self.map.size().tile_pos_x(offset.x),
self.map.size().tile_pos_y(offset.y),
)
.into();
self.map.set_scroll_pos(offset_scroll);
self.map
.set_scroll_pos((offset.x as i16, offset.y as i16).into());
self.offset = (x_start, y_start).into();
let copy_from = self.copied_up_to;
@ -386,11 +382,7 @@ impl<'a> InfiniteScrolledMap<'a> {
}
let current_scroll = self.map.scroll_pos();
let new_scroll = (
size.px_offset_x(i32::from(current_scroll.x) + difference.x),
size.px_offset_y(i32::from(current_scroll.y) + difference.y),
)
.into();
let new_scroll = current_scroll + (difference.x as i16, difference.y as i16).into();
self.map.set_scroll_pos(new_scroll);

View file

@ -4,7 +4,7 @@ use core::ops::{Deref, DerefMut};
use crate::bitarray::Bitarray;
use crate::display::{object::AffineMatrixAttributes, Priority, DISPLAY_CONTROL};
use crate::dma::dma_copy16;
use crate::fixnum::{Num, Number, Vector2D};
use crate::fixnum::{Num, Vector2D};
use crate::memory_mapped::MemoryMapped;
use super::{
@ -16,7 +16,6 @@ use crate::syscall::BgAffineSetData;
use alloc::{vec, vec::Vec};
pub trait TiledMapTypes {
type Position: Number;
type Size: BackgroundSize + Copy;
}
@ -26,19 +25,17 @@ trait TiledMapPrivate: TiledMapTypes {
fn tiles_mut(&mut self) -> &mut [Self::TileType];
fn tiles_dirty(&mut self) -> &mut bool;
fn x_scroll_mut(&mut self) -> &mut Self::Position;
fn y_scroll_mut(&mut self) -> &mut Self::Position;
fn x_scroll(&self) -> Self::Position;
fn y_scroll(&self) -> Self::Position;
fn affine_matrix(&self) -> Self::AffineMatrix;
fn background_id(&self) -> usize;
fn screenblock(&self) -> usize;
fn priority(&self) -> Priority;
fn map_size(&self) -> Self::Size;
fn bg_x(&self) -> MemoryMapped<Self::Position>;
fn bg_y(&self) -> MemoryMapped<Self::Position>;
fn bg_affine_matrix(&self) -> MemoryMapped<Self::AffineMatrix>;
fn update_bg_registers(&self);
fn scroll_pos(&self) -> Vector2D<i16>;
fn set_scroll_pos(&mut self, new_pos: Vector2D<i16>);
fn bg_control_register(&self) -> MemoryMapped<u16> {
unsafe { MemoryMapped::new(0x0400_0008 + 2 * self.background_id()) }
}
@ -55,8 +52,8 @@ pub trait TiledMap: TiledMapTypes {
fn size(&self) -> Self::Size;
#[must_use]
fn scroll_pos(&self) -> Vector2D<Self::Position>;
fn set_scroll_pos(&mut self, pos: Vector2D<Self::Position>);
fn scroll_pos(&self) -> Vector2D<i16>;
fn set_scroll_pos(&mut self, pos: Vector2D<i16>);
}
impl<T> TiledMap for T
@ -92,9 +89,7 @@ where
| (self.map_size().size_flag() << 14);
self.bg_control_register().set(new_bg_control_value);
self.bg_x().set(self.x_scroll());
self.bg_y().set(self.y_scroll());
self.bg_affine_matrix().set(self.affine_matrix());
self.update_bg_registers();
let screenblock_memory = self.screenblock_memory();
let x: TileIndex = unsafe { *self.tiles_mut().get_unchecked(0) }.into();
@ -119,13 +114,12 @@ where
}
#[must_use]
fn scroll_pos(&self) -> Vector2D<T::Position> {
(self.x_scroll(), self.y_scroll()).into()
fn scroll_pos(&self) -> Vector2D<i16> {
TiledMapPrivate::scroll_pos(self)
}
fn set_scroll_pos(&mut self, pos: Vector2D<T::Position>) {
*self.x_scroll_mut() = pos.x;
*self.y_scroll_mut() = pos.y;
fn set_scroll_pos(&mut self, pos: Vector2D<i16>) {
TiledMapPrivate::set_scroll_pos(self, pos);
}
}
@ -135,8 +129,7 @@ pub struct RegularMap {
priority: Priority,
size: RegularBackgroundSize,
x_scroll: u16,
y_scroll: u16,
scroll: Vector2D<i16>,
tiles: Vec<Tile>,
tiles_dirty: bool,
@ -145,7 +138,6 @@ pub struct RegularMap {
pub const TRANSPARENT_TILE_INDEX: u16 = (1 << 10) - 1;
impl TiledMapTypes for RegularMap {
type Position = u16;
type Size = RegularBackgroundSize;
}
@ -159,19 +151,7 @@ impl TiledMapPrivate for RegularMap {
fn tiles_dirty(&mut self) -> &mut bool {
&mut self.tiles_dirty
}
fn x_scroll_mut(&mut self) -> &mut Self::Position {
&mut self.x_scroll
}
fn y_scroll_mut(&mut self) -> &mut Self::Position {
&mut self.y_scroll
}
fn x_scroll(&self) -> Self::Position {
self.x_scroll
}
fn y_scroll(&self) -> Self::Position {
self.y_scroll
}
fn affine_matrix(&self) -> Self::AffineMatrix {}
fn background_id(&self) -> usize {
self.background_id as usize
}
@ -184,14 +164,15 @@ impl TiledMapPrivate for RegularMap {
fn map_size(&self) -> Self::Size {
self.size
}
fn bg_x(&self) -> MemoryMapped<Self::Position> {
unsafe { MemoryMapped::new(0x0400_0010 + 4 * self.background_id as usize) }
fn update_bg_registers(&self) {
self.x_register().set(self.scroll.x);
self.y_register().set(self.scroll.y);
}
fn bg_y(&self) -> MemoryMapped<Self::Position> {
unsafe { MemoryMapped::new(0x0400_0012 + 4 * self.background_id as usize) }
fn scroll_pos(&self) -> Vector2D<i16> {
self.scroll
}
fn bg_affine_matrix(&self) -> MemoryMapped<Self::AffineMatrix> {
unsafe { MemoryMapped::new(0) }
fn set_scroll_pos(&mut self, new_pos: Vector2D<i16>) {
self.scroll = new_pos;
}
}
@ -208,8 +189,7 @@ impl RegularMap {
priority,
size,
x_scroll: 0,
y_scroll: 0,
scroll: Default::default(),
tiles: vec![Default::default(); size.num_tiles()],
tiles_dirty: true,
@ -247,6 +227,14 @@ impl RegularMap {
self.tiles_mut()[pos] = new_tile;
*self.tiles_dirty() = true;
}
fn x_register(&self) -> MemoryMapped<i16> {
unsafe { MemoryMapped::new(0x0400_0010 + 4 * self.background_id as usize) }
}
fn y_register(&self) -> MemoryMapped<i16> {
unsafe { MemoryMapped::new(0x0400_0012 + 4 * self.background_id as usize) }
}
}
pub struct AffineMap {
@ -255,7 +243,9 @@ pub struct AffineMap {
priority: Priority,
size: AffineBackgroundSize,
bg_center: Vector2D<Num<i32, 8>>,
scroll: Vector2D<i16>,
transform_origin: Vector2D<Num<i32, 8>>,
transform: BgAffineSetData,
tiles: Vec<u8>,
@ -263,7 +253,6 @@ pub struct AffineMap {
}
impl TiledMapTypes for AffineMap {
type Position = Num<i32, 8>;
type Size = AffineBackgroundSize;
}
@ -277,21 +266,6 @@ impl TiledMapPrivate for AffineMap {
fn tiles_dirty(&mut self) -> &mut bool {
&mut self.tiles_dirty
}
fn x_scroll_mut(&mut self) -> &mut Self::Position {
&mut self.bg_center.x
}
fn y_scroll_mut(&mut self) -> &mut Self::Position {
&mut self.bg_center.y
}
fn x_scroll(&self) -> Self::Position {
self.bg_center.x + self.transform.position.x
}
fn y_scroll(&self) -> Self::Position {
self.bg_center.y + self.transform.position.y
}
fn affine_matrix(&self) -> Self::AffineMatrix {
self.transform.matrix
}
fn background_id(&self) -> usize {
self.background_id as usize
}
@ -304,14 +278,23 @@ impl TiledMapPrivate for AffineMap {
fn map_size(&self) -> Self::Size {
self.size
}
fn bg_x(&self) -> MemoryMapped<Self::Position> {
unsafe { MemoryMapped::new(0x0400_0008 + 0x10 * self.background_id()) }
fn update_bg_registers(&self) {
let register_pos = self.transform.position + self.transform_origin;
self.bg_x().set(register_pos.x);
self.bg_y().set(register_pos.y);
self.bg_affine_matrix().set(self.transform.matrix);
crate::println!(
"update: {:?} {:?}",
self.transform.matrix,
self.bg_affine_matrix().get()
);
}
fn bg_y(&self) -> MemoryMapped<Self::Position> {
unsafe { MemoryMapped::new(0x0400_000c + 0x10 * self.background_id()) }
fn scroll_pos(&self) -> Vector2D<i16> {
self.scroll
}
fn bg_affine_matrix(&self) -> MemoryMapped<Self::AffineMatrix> {
unsafe { MemoryMapped::new(0x0400_0000 + 0x10 * self.background_id()) }
fn set_scroll_pos(&mut self, new_pos: Vector2D<i16>) {
self.scroll = new_pos;
}
}
@ -321,7 +304,6 @@ impl AffineMap {
screenblock: u8,
priority: Priority,
size: AffineBackgroundSize,
bg_center: Vector2D<Num<i32, 8>>,
) -> Self {
Self {
background_id,
@ -329,7 +311,9 @@ impl AffineMap {
priority,
size,
bg_center,
scroll: Default::default(),
transform_origin: Default::default(),
transform: Default::default(),
tiles: vec![Default::default(); size.num_tiles()],
@ -369,22 +353,36 @@ impl AffineMap {
*self.tiles_dirty() = true;
}
pub fn set_transform_raw(&mut self, transform: BgAffineSetData) {
self.transform = transform;
}
pub fn set_transform(
&mut self,
display_center: impl Into<Vector2D<i16>>,
transform_origin: impl Into<Vector2D<Num<i32, 8>>>,
scale: impl Into<Vector2D<Num<i16, 8>>>,
rotation: impl Into<Num<u16, 8>>,
) {
self.set_transform_raw(crate::syscall::bg_affine_matrix(
self.bg_center,
display_center.into(),
scale.into(),
rotation.into(),
));
self.transform_origin = transform_origin.into();
let scale = scale.into();
let rotation = rotation.into();
self.transform =
crate::syscall::bg_affine_matrix(self.transform_origin, self.scroll, scale, rotation);
crate::println!(
"{:?}, {:?}, {:?}, {:?}",
self.transform_origin,
self.scroll,
scale,
rotation
);
crate::println!("{:?}", self.transform.matrix);
}
fn bg_x(&self) -> MemoryMapped<Num<i32, 8>> {
unsafe { MemoryMapped::new(0x0400_0008 + 0x10 * self.background_id()) }
}
fn bg_y(&self) -> MemoryMapped<Num<i32, 8>> {
unsafe { MemoryMapped::new(0x0400_000c + 0x10 * self.background_id()) }
}
fn bg_affine_matrix(&self) -> MemoryMapped<AffineMatrixAttributes> {
unsafe { MemoryMapped::new(0x0400_0000 + 0x10 * self.background_id()) }
}
}

View file

@ -7,7 +7,7 @@ mod vram_manager;
use crate::bitarray::Bitarray;
use crate::display::Priority;
use agb_fixnum::{Num, Vector2D};
use agb_fixnum::Vector2D;
use core::cell::RefCell;
pub use infinite_scrolled_map::{InfiniteScrolledMap, PartialUpdateStatus};
pub use map::{AffineMap, MapLoan, RegularMap, TiledMap};
@ -307,16 +307,7 @@ where
screenblocks.set(id, true);
}
let center_dim = Num::new(size.width() as i32 * 8 / 2);
let default_bg_center = (center_dim, center_dim).into();
let bg = AffineMap::new(
new_background as u8,
screenblock as u8 + 16,
priority,
size,
default_bg_center,
);
let bg = AffineMap::new(new_background as u8, screenblock as u8 + 16, priority, size);
affine.set(new_background, true);

View file

@ -185,7 +185,8 @@ pub fn bg_affine_matrix(
in("r0") &input as *const Input,
in("r1") output.as_mut_ptr(),
in("r2") 1,
lateout("r3") _,
clobber_abi("C")
);
}
@ -231,7 +232,7 @@ mod tests {
use super::*;
#[test_case]
fn affine(_gba: &mut crate::Gba) {
fn affine_obj(_gba: &mut crate::Gba) {
// expect identity matrix
let one: Num<i16, 8> = 1.into();
@ -241,4 +242,22 @@ mod tests {
assert_eq!(p_a, one);
assert_eq!(p_d, one);
}
#[test_case]
fn affine_bg(_gba: &mut crate::Gba) {
// expect the identity matrix
let aff = bg_affine_matrix(
(0, 0).into(),
(0i16, 0i16).into(),
(1i16, 1i16).into(),
0.into(),
);
let matrix = aff.matrix;
let (p_a, p_b, p_c, p_d) = (matrix.p_a, matrix.p_b, matrix.p_c, matrix.p_d);
assert_eq!(p_a, 1.into());
assert_eq!(p_b, 0.into());
assert_eq!(p_c, 0.into());
assert_eq!(p_d, 1.into());
}
}

View file

@ -1,27 +1,21 @@
use agb::{
display::tiled::{RegularMap, TileFormat, TileSet, TileSetting, TiledMap, VRamManager},
display::tiled::{RegularMap, TileFormat, TileSet, TileSetting, VRamManager},
include_gfx, rng,
};
use crate::sfx::Sfx;
include_gfx!("gfx/backgrounds.toml");
include_gfx!("gfx/stars.toml");
include_gfx!("gfx/help.toml");
pub fn load_palettes(vram: &mut VRamManager) {
vram.set_background_palettes(backgrounds::stars.palettes);
}
fn description_tileset() -> (TileSet<'static>, TileSet<'static>) {
let descriptions_1_tileset = TileSet::new(
backgrounds::descriptions1.tiles,
agb::display::tiled::TileFormat::FourBpp,
);
let descriptions_2_tileset = TileSet::new(
backgrounds::descriptions2.tiles,
agb::display::tiled::TileFormat::FourBpp,
);
(descriptions_1_tileset, descriptions_2_tileset)
vram.set_background_palettes(&[
stars::stars.palettes[0].clone(),
crate::customise::DESCRIPTIONS_1_PALETTE.clone(),
crate::customise::DESCRIPTIONS_2_PALETTE.clone(),
help::help.palettes[0].clone(),
]);
}
pub(crate) fn load_help_text(
@ -30,69 +24,18 @@ pub(crate) fn load_help_text(
help_text_line: u16,
at_tile: (u16, u16),
) {
let help_tileset = TileSet::new(
backgrounds::help.tiles,
agb::display::tiled::TileFormat::FourBpp,
);
let help_tileset = TileSet::new(help::help.tiles, agb::display::tiled::TileFormat::FourBpp);
for x in 0..16 {
let tile_id = help_text_line * 16 + x;
background.set_tile(
vram,
(x + at_tile.0, at_tile.1).into(),
&help_tileset,
TileSetting::new(
tile_id,
false,
false,
backgrounds::help.palette_assignments[tile_id as usize],
),
TileSetting::new(help_text_line * 16 + x, false, false, 3),
)
}
}
pub(crate) fn load_description(
upgrade: usize,
descriptions_map: &mut RegularMap,
vram: &mut VRamManager,
) {
let (descriptions_1_tileset, descriptions_2_tileset) = description_tileset();
for y in 0..11 {
for x in 0..8 {
if upgrade < 10 {
let tile_id = y * 8 + x + 8 * 11 * upgrade as u16;
descriptions_map.set_tile(
vram,
(x, y).into(),
&descriptions_1_tileset,
TileSetting::new(
tile_id,
false,
false,
backgrounds::descriptions1.palette_assignments[tile_id as usize],
),
)
} else {
let tile_id = y * 8 + x + 8 * 11 * (upgrade as u16 - 10);
descriptions_map.set_tile(
vram,
(x, y).into(),
&descriptions_2_tileset,
TileSetting::new(
tile_id,
false,
false,
backgrounds::descriptions2.palette_assignments[tile_id as usize],
),
)
}
}
}
}
// Expects a 64x32 map
fn create_background_map(map: &mut RegularMap, vram: &mut VRamManager, stars_tileset: &TileSet) {
for x in 0..64u16 {
@ -104,16 +47,7 @@ fn create_background_map(map: &mut RegularMap, vram: &mut VRamManager, stars_til
} else {
rng::gen().rem_euclid(64) as u16
};
let tile_setting = TileSetting::new(
tile_id,
false,
false,
if blank {
0
} else {
backgrounds::stars.palette_assignments[tile_id as usize]
},
);
let tile_setting = TileSetting::new(tile_id, false, false, 0);
map.set_tile(vram, (x, y).into(), stars_tileset, tile_setting);
}
@ -124,11 +58,8 @@ fn create_background_map(map: &mut RegularMap, vram: &mut VRamManager, stars_til
pub fn show_title_screen(background: &mut RegularMap, vram: &mut VRamManager, sfx: &mut Sfx) {
background.set_scroll_pos((0_u16, 0_u16).into());
vram.set_background_palettes(backgrounds::title.palettes);
let tile_set = TileSet::new(
backgrounds::title.tiles,
agb::display::tiled::TileFormat::FourBpp,
);
vram.set_background_palettes(stars::title.palettes);
let tile_set = TileSet::new(stars::title.tiles, agb::display::tiled::TileFormat::FourBpp);
background.hide();
for x in 0..30u16 {
@ -142,7 +73,7 @@ pub fn show_title_screen(background: &mut RegularMap, vram: &mut VRamManager, sf
tile_id,
false,
false,
backgrounds::title.palette_assignments[tile_id as usize],
stars::title.palette_assignments[tile_id as usize],
),
);
}
@ -169,7 +100,7 @@ impl<'a> StarBackground<'a> {
background2: &'a mut RegularMap,
vram: &'_ mut VRamManager,
) -> Self {
let stars_tileset = TileSet::new(backgrounds::stars.tiles, TileFormat::FourBpp);
let stars_tileset = TileSet::new(stars::stars.tiles, TileFormat::FourBpp);
create_background_map(background1, vram, &stars_tileset);
create_background_map(background2, vram, &stars_tileset);