object attributes in terms of three separate parameters

This commit is contained in:
Corwin Kuiper 2021-05-30 16:58:34 +01:00
parent c3b81a4585
commit 7aa213936e

View file

@ -1,15 +1,17 @@
use super::DISPLAY_CONTROL; use super::DISPLAY_CONTROL;
use crate::memory_mapped::MemoryMapped1DArray; use crate::memory_mapped::MemoryMapped1DArray;
const OBJECT_MEMORY_STANDARD: MemoryMapped1DArray<u32, 256> = const OBJECT_ATTRIBUTE_MEMORY: MemoryMapped1DArray<u16, 512> =
unsafe { MemoryMapped1DArray::new(0x0700_0000) }; unsafe { MemoryMapped1DArray::new(0x0700_0000) };
#[non_exhaustive] #[non_exhaustive]
pub struct ObjectControl {} pub struct ObjectControl {
object_count: u8,
}
pub struct ObjectStandard { pub struct ObjectStandard {
attributes: ObjectAttribute, attributes: ObjectAttribute,
id: usize, id: u8,
} }
pub enum Mode { pub enum Mode {
@ -30,7 +32,7 @@ impl ObjectStandard {
pub fn set_y(&mut self, y: u8) { pub fn set_y(&mut self, y: u8) {
self.attributes.set_y(y) self.attributes.set_y(y)
} }
pub fn set_tile_id(&mut self, id: u32) { pub fn set_tile_id(&mut self, id: u16) {
self.attributes.set_tile_id(id) self.attributes.set_tile_id(id)
} }
pub fn set_hflip(&mut self, hflip: bool) { pub fn set_hflip(&mut self, hflip: bool) {
@ -45,80 +47,78 @@ impl ObjectStandard {
} }
pub struct ObjectAttribute { pub struct ObjectAttribute {
low: u32, a0: u16,
high: u32, a1: u16,
a2: u16,
} }
impl ObjectAttribute { impl ObjectAttribute {
unsafe fn commit(&self, index: usize) { unsafe fn commit(&self, index: u8) {
OBJECT_MEMORY_STANDARD.set(index * 2, self.low); OBJECT_ATTRIBUTE_MEMORY.set(index as usize * 4, self.a0);
// preserve top set of bits OBJECT_ATTRIBUTE_MEMORY.set(index as usize * 4 + 1, self.a1);
let high_bits = OBJECT_MEMORY_STANDARD.get(index * 2 + 1); OBJECT_ATTRIBUTE_MEMORY.set(index as usize * 4 + 2, self.a2);
let new_high_bits = (high_bits & !((1 << 16) - 1)) | self.high;
OBJECT_MEMORY_STANDARD.set(index * 2 + 1, new_high_bits);
} }
pub fn set_hflip(&mut self, hflip: bool) { pub fn set_hflip(&mut self, hflip: bool) {
let mask = (1 << 0xC) << 16; let mask = 1 << 0xC;
let attr = self.low; let attr = self.a1;
let attr = attr & !mask; let attr = attr & !mask;
if hflip { if hflip {
self.low = attr | mask self.a1 = attr | mask
} else { } else {
self.low = attr self.a1 = attr
} }
} }
pub fn set_x(&mut self, x: u8) { pub fn set_x(&mut self, x: u8) {
let mask = ((1 << 8) - 1) << 16; let mask = (1 << 8) - 1;
let attr1 = self.low; let attr1 = self.a1;
let attr_without_x = attr1 & !mask; let attr_without_x = attr1 & !mask;
let attr_with_new_x = attr_without_x | ((x as u32) << 16); let attr_with_new_x = attr_without_x | x as u16;
self.low = attr_with_new_x; self.a1 = attr_with_new_x;
} }
pub fn set_y(&mut self, y: u8) { pub fn set_y(&mut self, y: u8) {
let mask = (1 << 8) - 1; let mask = (1 << 8) - 1;
let attr0 = self.low; let attr0 = self.a0;
let attr_without_y = attr0 & !mask; let attr_without_y = attr0 & !mask;
let attr_with_new_y = attr_without_y | y as u32; let attr_with_new_y = attr_without_y | y as u16;
self.low = attr_with_new_y; self.a0 = attr_with_new_y;
} }
pub fn set_tile_id(&mut self, id: u32) { pub fn set_tile_id(&mut self, id: u16) {
let mask = (1 << 9) - 1; let mask = (1 << 9) - 1;
assert!(id <= mask, "tile id is greater than 9 bits"); assert!(id <= mask, "tile id is greater than 9 bits");
let attr = self.high; let attr = self.a2;
let attr = attr & !mask; let attr = attr & !mask;
let attr = attr | id; let attr = attr | id;
self.high = attr; self.a2 = attr;
} }
pub fn set_mode(&mut self, mode: Mode) { pub fn set_mode(&mut self, mode: Mode) {
let mask = 0b11 << 0x8; let mask = 0b11 << 0x8;
self.low = (self.low & !mask) | ((mode as u32) << 0x8); self.a0 = (self.a0 & !mask) | ((mode as u16) << 0x8);
} }
} }
impl ObjectAttribute { impl ObjectAttribute {
fn new() -> Self { fn new() -> Self {
ObjectAttribute { low: 0, high: 0 } ObjectAttribute {
a0: 0,
a1: 0,
a2: 0,
}
} }
} }
impl ObjectControl { impl ObjectControl {
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
ObjectControl {}
}
/// # Safety
/// Temporary, do not call if you currently hold an object
pub unsafe fn clear_objects(&mut self) {
let mut o = ObjectAttribute::new(); let mut o = ObjectAttribute::new();
o.set_mode(Mode::Hidden); o.set_mode(Mode::Hidden);
for index in 0..128 { for index in 0..128 {
o.commit(index); unsafe { o.commit(index) };
} }
ObjectControl { object_count: 0 }
} }
pub fn enable(&mut self) { pub fn enable(&mut self) {
@ -133,9 +133,9 @@ impl ObjectControl {
DISPLAY_CONTROL.set(disp); DISPLAY_CONTROL.set(disp);
} }
/// # Safety pub fn get_object(&mut self) -> ObjectStandard {
/// Temporary function, you must not get multiple objects with the same id let id = self.object_count;
pub unsafe fn get_object(&self, id: usize) -> ObjectStandard { self.object_count += 1;
assert!(id < 128, "object id must be less than 128"); assert!(id < 128, "object id must be less than 128");
ObjectStandard { ObjectStandard {
attributes: ObjectAttribute::new(), attributes: ObjectAttribute::new(),