use super::*;
use voladdress::{Safe, VolAddress};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u16)]
pub enum ObjDisplayStyle {
#[default]
Normal = 0 << 8,
Affine = 1 << 8,
NotDisplayed = 2 << 8,
DoubleSizeAffine = 3 << 8,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u16)]
pub enum ObjEffectMode {
#[default]
Normal = 0 << 10,
SemiTransparent = 1 << 10,
Window = 2 << 10,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u16)]
#[allow(missing_docs)]
pub enum ObjShape {
#[default]
Square = 0 << 14,
Horizontal = 1 << 14,
Vertical = 2 << 14,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct ObjAttr0(u16);
impl ObjAttr0 {
pub_const_fn_new_zeroed!();
u16_int_field!(0 - 7, y, with_y);
u16_enum_field!(8 - 9: ObjDisplayStyle, style, with_style);
u16_enum_field!(10 - 11: ObjEffectMode, mode, with_mode);
u16_bool_field!(12, mosaic, with_mosaic);
u16_bool_field!(13, bpp8, with_bpp8);
u16_enum_field!(14 - 15: ObjShape, shape, with_shape);
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct ObjAttr1(u16);
impl ObjAttr1 {
pub_const_fn_new_zeroed!();
u16_int_field!(0 - 8, x, with_x);
u16_int_field!(9 - 13, affine_index, with_affine_index);
u16_bool_field!(12, hflip, with_hflip);
u16_bool_field!(13, vflip, with_vflip);
u16_int_field!(14 - 15, size, with_size);
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct ObjAttr2(u16);
impl ObjAttr2 {
pub_const_fn_new_zeroed!();
u16_int_field!(0 - 9, tile_id, with_tile_id);
u16_int_field!(10 - 11, priority, with_priority);
u16_int_field!(12 - 15, palbank, with_palbank);
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct ObjAttr(pub ObjAttr0, pub ObjAttr1, pub ObjAttr2);
#[allow(missing_docs)]
impl ObjAttr {
#[inline]
pub const fn new() -> Self {
Self(ObjAttr0::new(), ObjAttr1::new(), ObjAttr2::new())
}
#[inline]
pub fn set_y(&mut self, y: u16) {
self.0 = self.0.with_y(y);
}
#[inline]
pub fn set_style(&mut self, style: ObjDisplayStyle) {
self.0 = self.0.with_style(style);
}
#[inline]
pub fn set_x(&mut self, x: u16) {
self.1 = self.1.with_x(x);
}
#[inline]
pub fn set_tile_id(&mut self, id: u16) {
self.2 = self.2.with_tile_id(id);
}
#[inline]
pub fn set_palbank(&mut self, palbank: u16) {
self.2 = self.2.with_palbank(palbank);
}
#[inline]
pub fn write(&self, addr: VolAddress<ObjAttr, Safe, ()>) {
unsafe {
let addr: *mut u16 = addr.as_usize() as *mut u16;
core::ptr::write_volatile(addr.add(0), self.0 .0);
core::ptr::write_volatile(addr.add(1), self.1 .0);
core::ptr::write_volatile(addr.add(2), self.2 .0);
}
}
}
pub trait ObjAttrWriteExt {
fn write(&self, attr: ObjAttr);
}
impl ObjAttrWriteExt for VolAddress<ObjAttr, Safe, ()> {
#[inline]
fn write(&self, attr: ObjAttr) {
attr.write(*self);
}
}