mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-24 00:31:34 +11:00
objects now exist and work
This commit is contained in:
parent
a1b67e107f
commit
2a7b350f57
28
agb/Cargo.lock
generated
28
agb/Cargo.lock
generated
|
@ -25,6 +25,7 @@ dependencies = [
|
|||
"bare-metal",
|
||||
"bitflags",
|
||||
"hashbrown",
|
||||
"modular-bitfield",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -192,6 +193,27 @@ dependencies = [
|
|||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "modular-bitfield"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74"
|
||||
dependencies = [
|
||||
"modular-bitfield-impl",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "modular-bitfield-impl"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
|
@ -289,6 +311,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.86"
|
||||
|
|
|
@ -27,6 +27,7 @@ agb_macros = { version = "0.1.0", path = "../agb-macros" }
|
|||
agb_fixnum = { version = "0.1.0", path = "../agb-fixnum" }
|
||||
bare-metal = "1.0"
|
||||
hashbrown = "0.12.0"
|
||||
modular-bitfield = "0.11.2"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
default-target = "thumbv6m-none-eabi"
|
||||
|
|
|
@ -2,7 +2,12 @@
|
|||
#![no_main]
|
||||
|
||||
use agb::{
|
||||
display::{background::Map, object::ObjectStandard, HEIGHT, WIDTH},
|
||||
display::{
|
||||
background::Map,
|
||||
object::{Object, ObjectController, Size, Sprite},
|
||||
palette16::Palette16,
|
||||
HEIGHT, WIDTH,
|
||||
},
|
||||
input::Button,
|
||||
};
|
||||
use core::convert::TryInto;
|
||||
|
@ -15,7 +20,7 @@ enum State {
|
|||
}
|
||||
|
||||
struct Character<'a> {
|
||||
object: ObjectStandard<'a>,
|
||||
object: Object<'a, 'a>,
|
||||
position: Vector2D,
|
||||
velocity: Vector2D,
|
||||
}
|
||||
|
@ -30,8 +35,8 @@ fn tile_is_collidable(tile: u16) -> bool {
|
|||
masked == 0 || masked == 4
|
||||
}
|
||||
|
||||
fn frame_ranger(count: u32, start: u32, end: u32, delay: u32) -> u16 {
|
||||
(((count / delay) % (end + 1 - start)) + start) as u16
|
||||
fn frame_ranger(count: u32, start: u32, end: u32, delay: u32) -> usize {
|
||||
(((count / delay) % (end + 1 - start)) + start) as usize
|
||||
}
|
||||
|
||||
#[agb::entry]
|
||||
|
@ -54,14 +59,11 @@ fn main(mut gba: agb::Gba) -> ! {
|
|||
background.show();
|
||||
background.commit();
|
||||
|
||||
let mut object = gba.display.object.get();
|
||||
let object = gba.display.object.get();
|
||||
|
||||
object.set_sprite_palette_raw(&CHICKEN_PALETTE);
|
||||
object.set_sprite_tilemap(&CHICKEN_TILES);
|
||||
|
||||
object.enable();
|
||||
let sprite = object.get_sprite(&ChickenSprites[0]).unwrap();
|
||||
let mut chicken = Character {
|
||||
object: object.get_object_standard(),
|
||||
object: object.get_object(sprite).unwrap(),
|
||||
position: Vector2D {
|
||||
x: (6 * 8) << 8,
|
||||
y: ((7 * 8) - 4) << 8,
|
||||
|
@ -69,7 +71,6 @@ fn main(mut gba: agb::Gba) -> ! {
|
|||
velocity: Vector2D { x: 0, y: 0 },
|
||||
};
|
||||
|
||||
chicken.object.set_tile_id(0);
|
||||
chicken
|
||||
.object
|
||||
.set_x((chicken.position.x >> 8).try_into().unwrap());
|
||||
|
@ -120,14 +121,19 @@ fn main(mut gba: agb::Gba) -> ! {
|
|||
}
|
||||
|
||||
restrict_to_screen(&mut chicken);
|
||||
update_chicken_object(&mut chicken, state, frame_count);
|
||||
update_chicken_object(&mut chicken, &object, state, frame_count);
|
||||
|
||||
// Commit the chicken to vram
|
||||
chicken.object.commit();
|
||||
}
|
||||
}
|
||||
|
||||
fn update_chicken_object(chicken: &mut Character, state: State, frame_count: u32) {
|
||||
fn update_chicken_object<'a>(
|
||||
chicken: &'_ mut Character<'a>,
|
||||
object: &'a ObjectController,
|
||||
state: State,
|
||||
frame_count: u32,
|
||||
) {
|
||||
if chicken.velocity.x > 1 {
|
||||
chicken.object.set_hflip(false);
|
||||
} else if chicken.velocity.x < -1 {
|
||||
|
@ -136,18 +142,24 @@ fn update_chicken_object(chicken: &mut Character, state: State, frame_count: u32
|
|||
match state {
|
||||
State::Ground => {
|
||||
if chicken.velocity.x.abs() > 1 << 4 {
|
||||
chicken.object.set_sprite(
|
||||
object
|
||||
.get_sprite(&ChickenSprites[frame_ranger(frame_count, 1, 3, 10)])
|
||||
.unwrap(),
|
||||
);
|
||||
} else {
|
||||
chicken
|
||||
.object
|
||||
.set_tile_id(frame_ranger(frame_count, 1, 3, 10));
|
||||
} else {
|
||||
chicken.object.set_tile_id(0);
|
||||
.set_sprite(object.get_sprite(&ChickenSprites[0]).unwrap());
|
||||
}
|
||||
}
|
||||
State::Upwards => {}
|
||||
State::Flapping => {
|
||||
chicken
|
||||
.object
|
||||
.set_tile_id(frame_ranger(frame_count, 4, 5, 5));
|
||||
chicken.object.set_sprite(
|
||||
object
|
||||
.get_sprite(&ChickenSprites[frame_ranger(frame_count, 4, 5, 5)])
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,16 +244,65 @@ fn handle_collision(
|
|||
|
||||
// Below is the data for the sprites
|
||||
|
||||
static CHICKEN_TILES: [u32; 8 * 6] = [
|
||||
0x01100000, 0x11100000, 0x01100010, 0x01111110, 0x01111110, 0x00001000, 0x00001000, 0x00011000,
|
||||
0x01100000, 0x11100000, 0x01100010, 0x01111110, 0x01111110, 0x00010100, 0x00100100, 0x00000010,
|
||||
0x01100000, 0x11100000, 0x01100010, 0x01111110, 0x01111110, 0x00011000, 0x00100110, 0x00100000,
|
||||
0x01100000, 0x11100000, 0x01100010, 0x01111110, 0x01111110, 0x00011000, 0x00011100, 0x00001000,
|
||||
0x01100000, 0x11111100, 0x01111010, 0x01111110, 0x01111110, 0x00011000, 0x00010000, 0x00000000,
|
||||
0x01100000, 0x11100000, 0x01111110, 0x01111110, 0x01111110, 0x00011000, 0x00010000, 0x00000000,
|
||||
];
|
||||
static ChickenPalette: Palette16 =
|
||||
Palette16::new([0x7C1E, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
static CHICKEN_PALETTE: [u16; 1] = [0x7C1E];
|
||||
static ChickenSprites: &[Sprite] = &[
|
||||
Sprite {
|
||||
palette: &ChickenPalette,
|
||||
data: &[
|
||||
0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x10, 0x11, 0x10, 0x00, 0x10, 0x01, 0x10, 0x11,
|
||||
0x11, 0x01, 0x10, 0x11, 0x11, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
|
||||
0x00, 0x10, 0x01, 0x00,
|
||||
],
|
||||
size: Size::S8x8,
|
||||
},
|
||||
Sprite {
|
||||
palette: &ChickenPalette,
|
||||
data: &[
|
||||
0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x10, 0x11, 0x10, 0x00, 0x10, 0x01, 0x10, 0x11,
|
||||
0x11, 0x01, 0x10, 0x11, 0x11, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x10, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00,
|
||||
],
|
||||
size: Size::S8x8,
|
||||
},
|
||||
Sprite {
|
||||
palette: &ChickenPalette,
|
||||
data: &[
|
||||
0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x10, 0x11, 0x10, 0x00, 0x10, 0x01, 0x10, 0x11,
|
||||
0x11, 0x01, 0x10, 0x11, 0x11, 0x01, 0x00, 0x10, 0x01, 0x00, 0x10, 0x01, 0x10, 0x00,
|
||||
0x00, 0x00, 0x10, 0x00,
|
||||
],
|
||||
size: Size::S8x8,
|
||||
},
|
||||
Sprite {
|
||||
palette: &ChickenPalette,
|
||||
data: &[
|
||||
0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x10, 0x11, 0x10, 0x00, 0x10, 0x01, 0x10, 0x11,
|
||||
0x11, 0x01, 0x10, 0x11, 0x11, 0x01, 0x00, 0x10, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00,
|
||||
0x00, 0x10, 0x00, 0x00,
|
||||
],
|
||||
size: Size::S8x8,
|
||||
},
|
||||
Sprite {
|
||||
palette: &ChickenPalette,
|
||||
data: &[
|
||||
0x00, 0x00, 0x10, 0x01, 0x00, 0x11, 0x11, 0x11, 0x10, 0x10, 0x11, 0x01, 0x10, 0x11,
|
||||
0x11, 0x01, 0x10, 0x11, 0x11, 0x01, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
],
|
||||
size: Size::S8x8,
|
||||
},
|
||||
Sprite {
|
||||
palette: &ChickenPalette,
|
||||
data: &[
|
||||
0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x10, 0x11, 0x10, 0x11, 0x11, 0x01, 0x10, 0x11,
|
||||
0x11, 0x01, 0x10, 0x11, 0x11, 0x01, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
],
|
||||
size: Size::S8x8,
|
||||
},
|
||||
];
|
||||
|
||||
static MAP_TILES: [u32; 8 * 17] = [
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use crate::memory_mapped::MemoryMapped;
|
||||
use bitflags::bitflags;
|
||||
|
||||
use modular_bitfield::BitfieldSpecifier;
|
||||
use video::Video;
|
||||
|
||||
use self::object::ObjectControl;
|
||||
use self::object::ObjectController;
|
||||
|
||||
/// Graphics mode 0. Four regular backgrounds.
|
||||
pub mod background;
|
||||
|
@ -69,8 +70,8 @@ pub struct Display {
|
|||
pub struct ObjectDistribution {}
|
||||
|
||||
impl ObjectDistribution {
|
||||
pub fn get(&mut self) -> ObjectControl {
|
||||
ObjectControl::new()
|
||||
pub fn get(&mut self) -> ObjectController {
|
||||
ObjectController::new()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,6 +110,7 @@ pub fn busy_wait_for_vblank() {
|
|||
while VCOUNT.get() < 160 {}
|
||||
}
|
||||
|
||||
#[derive(BitfieldSpecifier)]
|
||||
pub enum Priority {
|
||||
P0 = 0,
|
||||
P1 = 1,
|
||||
|
|
|
@ -2,6 +2,8 @@ use alloc::vec::Vec;
|
|||
use core::alloc::Layout;
|
||||
use core::cell::RefCell;
|
||||
use core::ptr::NonNull;
|
||||
use modular_bitfield::prelude::{B10, B2, B3, B4, B5, B8, B9};
|
||||
use modular_bitfield::{bitfield, BitfieldSpecifier};
|
||||
|
||||
use hashbrown::{hash_map::Entry, HashMap};
|
||||
|
||||
|
@ -13,6 +15,8 @@ use crate::agb_alloc::block_allocator::BlockAllocator;
|
|||
use crate::agb_alloc::bump_allocator::StartEnd;
|
||||
use crate::fixnum::Vector2D;
|
||||
|
||||
use attributes::*;
|
||||
|
||||
static SPRITE_ALLOCATOR: BlockAllocator = unsafe {
|
||||
BlockAllocator::new(StartEnd {
|
||||
start: || TILE_SPRITE,
|
||||
|
@ -73,6 +77,9 @@ impl Size {
|
|||
Size::S32x64 => 32,
|
||||
}
|
||||
}
|
||||
const fn shape_size(self) -> (u8, u8) {
|
||||
(self as u8 >> 2, self as u8 & 0b11)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SpriteBorrow<'a> {
|
||||
|
@ -104,11 +111,33 @@ impl Storage {
|
|||
fn as_palette_ptr(&self) -> *mut u8 {
|
||||
(self.location as usize * Palette16::layout().size() + PALETTE_SPRITE) as *mut u8
|
||||
}
|
||||
fn as_sprite_ptr(&self) -> *mut u8 {
|
||||
(self.location as usize * BYTES_PER_TILE_4BPP + TILE_SPRITE) as *mut u8
|
||||
}
|
||||
}
|
||||
|
||||
struct Attributes {
|
||||
a0: ObjectAttribute0,
|
||||
a1s: ObjectAttribute1Standard,
|
||||
a1a: ObjectAttribute1Affine,
|
||||
a2: ObjectAttribute2,
|
||||
}
|
||||
|
||||
impl Attributes {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
a0: ObjectAttribute0::new(),
|
||||
a1s: ObjectAttribute1Standard::new(),
|
||||
a1a: ObjectAttribute1Affine::new(),
|
||||
a2: ObjectAttribute2::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Object<'a, 'b> {
|
||||
sprite: SpriteBorrow<'a>,
|
||||
loan: Loan<'b>,
|
||||
attrs: Attributes,
|
||||
}
|
||||
|
||||
struct SpriteControllerInner {
|
||||
|
@ -140,6 +169,17 @@ pub struct ObjectController {
|
|||
|
||||
impl ObjectController {
|
||||
pub(crate) fn new() -> Self {
|
||||
DISPLAY_CONTROL.set_bits(1, 1, 0x6);
|
||||
DISPLAY_CONTROL.set_bits(1, 1, 0xC);
|
||||
|
||||
for i in 0..128 {
|
||||
unsafe {
|
||||
(OBJECT_ATTRIBUTE_MEMORY as *mut u16)
|
||||
.add(i * 4)
|
||||
.write_volatile(0b10 << 8)
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
free_objects: RefCell::new((0..128).collect()),
|
||||
free_affine_matricies: RefCell::new((0..32).collect()),
|
||||
|
@ -153,7 +193,11 @@ impl ObjectController {
|
|||
index: inner.pop()?,
|
||||
free_list: &self.free_objects,
|
||||
};
|
||||
Some(Object { sprite, loan })
|
||||
Some(Object {
|
||||
sprite,
|
||||
loan,
|
||||
attrs: Attributes::new(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_sprite(&self, sprite: &'static Sprite) -> Option<SpriteBorrow> {
|
||||
|
@ -161,10 +205,80 @@ impl ObjectController {
|
|||
}
|
||||
}
|
||||
|
||||
impl Drop for Object<'_, '_> {
|
||||
fn drop(&mut self) {
|
||||
self.attrs.a0.set_object_mode(ObjectMode::Disabled);
|
||||
self.commit();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> Object<'a, 'b> {
|
||||
pub fn set_sprite(&'a mut self, sprite: SpriteBorrow<'a>) {
|
||||
pub fn set_sprite(&'_ mut self, sprite: SpriteBorrow<'a>) {
|
||||
self.attrs.a2.set_tile_index(sprite.sprite_location);
|
||||
let shape_size = sprite.id.get_sprite().size.shape_size();
|
||||
self.attrs.a0.set_shape(shape_size.0);
|
||||
self.attrs.a1a.set_size(shape_size.1);
|
||||
self.attrs.a1s.set_size(shape_size.1);
|
||||
self.sprite = sprite;
|
||||
}
|
||||
|
||||
pub fn show(&mut self) -> &mut Self {
|
||||
self.attrs.a0.set_object_mode(ObjectMode::Normal);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_hflip(&mut self, flip: bool) -> &mut Self {
|
||||
self.attrs.a1s.set_horizontal_flip(flip);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_vflip(&mut self, flip: bool) -> &mut Self {
|
||||
self.attrs.a1s.set_vertical_flip(flip);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_x(&mut self, x: u16) -> &mut Self {
|
||||
self.attrs.a1a.set_x(x as u16);
|
||||
self.attrs.a1s.set_x(x as u16);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_y(&mut self, y: u16) -> &mut Self {
|
||||
self.attrs.a0.set_y(y as u8);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_position(&mut self, position: Vector2D<i32>) -> &mut Self {
|
||||
self.attrs.a0.set_y(position.y as u8);
|
||||
self.attrs.a1a.set_x(position.x as u16);
|
||||
self.attrs.a1s.set_x(position.x as u16);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn commit(&self) {
|
||||
let mode = self.attrs.a0.object_mode();
|
||||
let attrs: [[u8; 2]; 3] = match mode {
|
||||
ObjectMode::Normal => [
|
||||
self.attrs.a0.into_bytes(),
|
||||
self.attrs.a1s.into_bytes(),
|
||||
self.attrs.a2.into_bytes(),
|
||||
],
|
||||
_ => [
|
||||
self.attrs.a0.into_bytes(),
|
||||
self.attrs.a1a.into_bytes(),
|
||||
self.attrs.a2.into_bytes(),
|
||||
],
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let attrs: [u8; 6] = core::mem::transmute(attrs);
|
||||
(OBJECT_ATTRIBUTE_MEMORY as *mut u8)
|
||||
.add(self.loan.index as usize * (4 * 2))
|
||||
.copy_from(attrs.as_ptr(), attrs.len())
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// The Sprite Id is a thin wrapper around the pointer to the sprite in
|
||||
|
@ -288,6 +402,26 @@ impl SpriteControllerInner {
|
|||
}
|
||||
}
|
||||
|
||||
fn return_sprite(&mut self, sprite: &'static Sprite) {
|
||||
let entry = self
|
||||
.sprite
|
||||
.entry(sprite.get_id())
|
||||
.and_replace_entry_with(|_, mut storage| {
|
||||
storage.count -= 1;
|
||||
if storage.count == 0 {
|
||||
unsafe { SPRITE_ALLOCATOR.dealloc(storage.as_sprite_ptr(), sprite.layout()) }
|
||||
None
|
||||
} else {
|
||||
Some(storage)
|
||||
}
|
||||
});
|
||||
|
||||
match entry {
|
||||
Entry::Occupied(_) => {}
|
||||
Entry::Vacant(_) => self.return_palette(sprite.palette),
|
||||
}
|
||||
}
|
||||
|
||||
fn return_palette(&mut self, palette: &'static Palette16) {
|
||||
let id = palette.get_id();
|
||||
self.palette
|
||||
|
@ -309,21 +443,70 @@ impl SpriteControllerInner {
|
|||
impl<'a> Drop for SpriteBorrow<'a> {
|
||||
fn drop(&mut self) {
|
||||
let mut inner = self.controller.borrow_mut();
|
||||
let entry = inner
|
||||
.sprite
|
||||
.entry(self.id)
|
||||
.and_replace_entry_with(|_, mut storage| {
|
||||
storage.count -= 1;
|
||||
if storage.count == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(storage)
|
||||
}
|
||||
});
|
||||
|
||||
match entry {
|
||||
Entry::Occupied(_) => {}
|
||||
Entry::Vacant(_) => inner.return_palette(self.id.get_sprite().palette),
|
||||
}
|
||||
inner.return_sprite(self.id.get_sprite())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(BitfieldSpecifier, Clone, Copy)]
|
||||
enum ObjectMode {
|
||||
Normal,
|
||||
Affine,
|
||||
Disabled,
|
||||
AffineDouble,
|
||||
}
|
||||
|
||||
#[derive(BitfieldSpecifier, Clone, Copy)]
|
||||
#[bits = 2]
|
||||
enum GraphicsMode {
|
||||
Normal,
|
||||
AlphaBlending,
|
||||
Window,
|
||||
}
|
||||
|
||||
#[derive(BitfieldSpecifier, Clone, Copy)]
|
||||
enum ColourMode {
|
||||
Four,
|
||||
Eight,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod attributes {
|
||||
use super::*;
|
||||
#[bitfield]
|
||||
#[derive(Clone, Copy)]
|
||||
pub(super) struct ObjectAttribute0 {
|
||||
pub y: B8,
|
||||
pub object_mode: ObjectMode,
|
||||
pub graphics_mode: GraphicsMode,
|
||||
pub mosaic: bool,
|
||||
pub colour_mode: ColourMode,
|
||||
pub shape: B2,
|
||||
}
|
||||
|
||||
#[bitfield]
|
||||
#[derive(Clone, Copy)]
|
||||
pub(super) struct ObjectAttribute1Standard {
|
||||
pub x: B9,
|
||||
#[skip]
|
||||
__: B3,
|
||||
pub horizontal_flip: bool,
|
||||
pub vertical_flip: bool,
|
||||
pub size: B2,
|
||||
}
|
||||
|
||||
#[bitfield]
|
||||
#[derive(Clone, Copy)]
|
||||
pub(super) struct ObjectAttribute1Affine {
|
||||
pub x: B9,
|
||||
pub affine_index: B5,
|
||||
pub size: B2,
|
||||
}
|
||||
|
||||
#[bitfield]
|
||||
#[derive(Clone, Copy)]
|
||||
pub(super) struct ObjectAttribute2 {
|
||||
pub tile_index: B10,
|
||||
pub priority: Priority,
|
||||
pub palete_bank: B4,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use core::arch::asm;
|
||||
|
||||
use crate::display::object::AffineMatrixAttributes;
|
||||
// use crate::display::object::AffineMatrixAttributes;
|
||||
use crate::fixnum::Num;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
|
@ -113,55 +113,55 @@ pub fn arc_tan2(x: i16, y: i32) -> i16 {
|
|||
result
|
||||
}
|
||||
|
||||
pub fn affine_matrix(
|
||||
x_scale: Num<i16, 8>,
|
||||
y_scale: Num<i16, 8>,
|
||||
rotation: u8,
|
||||
) -> AffineMatrixAttributes {
|
||||
let mut result = AffineMatrixAttributes {
|
||||
p_a: 0,
|
||||
p_b: 0,
|
||||
p_c: 0,
|
||||
p_d: 0,
|
||||
};
|
||||
// pub fn affine_matrix(
|
||||
// x_scale: Num<i16, 8>,
|
||||
// y_scale: Num<i16, 8>,
|
||||
// rotation: u8,
|
||||
// ) -> AffineMatrixAttributes {
|
||||
// let mut result = AffineMatrixAttributes {
|
||||
// p_a: 0,
|
||||
// p_b: 0,
|
||||
// p_c: 0,
|
||||
// p_d: 0,
|
||||
// };
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(C, packed)]
|
||||
struct Input {
|
||||
x_scale: i16,
|
||||
y_scale: i16,
|
||||
rotation: u16,
|
||||
}
|
||||
// #[allow(dead_code)]
|
||||
// #[repr(C, packed)]
|
||||
// struct Input {
|
||||
// x_scale: i16,
|
||||
// y_scale: i16,
|
||||
// rotation: u16,
|
||||
// }
|
||||
|
||||
let input = Input {
|
||||
y_scale: x_scale.to_raw(),
|
||||
x_scale: y_scale.to_raw(),
|
||||
rotation: rotation as u16,
|
||||
};
|
||||
// let input = Input {
|
||||
// y_scale: x_scale.to_raw(),
|
||||
// x_scale: y_scale.to_raw(),
|
||||
// rotation: rotation as u16,
|
||||
// };
|
||||
|
||||
unsafe {
|
||||
asm!("swi 0x0F",
|
||||
in("r0") &input as *const Input as usize,
|
||||
in("r1") &mut result as *mut AffineMatrixAttributes as usize,
|
||||
in("r2") 1,
|
||||
in("r3") 2,
|
||||
)
|
||||
}
|
||||
// unsafe {
|
||||
// asm!("swi 0x0F",
|
||||
// in("r0") &input as *const Input as usize,
|
||||
// in("r1") &mut result as *mut AffineMatrixAttributes as usize,
|
||||
// in("r2") 1,
|
||||
// in("r3") 2,
|
||||
// )
|
||||
// }
|
||||
|
||||
result
|
||||
}
|
||||
// result
|
||||
// }
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use super::*;
|
||||
|
||||
#[test_case]
|
||||
fn affine(_gba: &mut crate::Gba) {
|
||||
// expect identity matrix
|
||||
let one: Num<i16, 8> = 1.into();
|
||||
// #[test_case]
|
||||
// fn affine(_gba: &mut crate::Gba) {
|
||||
// // expect identity matrix
|
||||
// let one: Num<i16, 8> = 1.into();
|
||||
|
||||
let aff = affine_matrix(one, one, 0);
|
||||
assert_eq!(aff.p_a, one.to_raw());
|
||||
assert_eq!(aff.p_d, one.to_raw());
|
||||
}
|
||||
}
|
||||
// let aff = affine_matrix(one, one, 0);
|
||||
// assert_eq!(aff.p_a, one.to_raw());
|
||||
// assert_eq!(aff.p_d, one.to_raw());
|
||||
// }
|
||||
// }
|
||||
|
|
Loading…
Reference in a new issue