breaking: put object stuff in a sub-module

This commit is contained in:
Lokathor 2022-12-09 12:08:30 -07:00
parent b8f19602cf
commit 2ebe3cc510
3 changed files with 174 additions and 85 deletions

View file

@ -1,7 +1,19 @@
//! A module that just re-exports all the other modules of the crate.
pub use crate::{
asm_runtime::*, bios::*, builtin_art::*, dma::*, fixed::*, gba_cell::*,
include_aligned_bytes, interrupts::*, keys::*, mgba::*, mmio::*, sound::*,
timers::*, video::*, Align4,
asm_runtime::*,
bios::*,
builtin_art::*,
dma::*,
fixed::*,
gba_cell::*,
include_aligned_bytes,
interrupts::*,
keys::*,
mgba::*,
mmio::*,
sound::*,
timers::*,
video::{obj::*, *},
Align4,
};

View file

@ -103,11 +103,14 @@ use crate::macros::{
#[allow(unused_imports)]
use crate::prelude::*;
pub mod obj;
/// An RGB555 color value (packed into `u16`).
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Color(pub u16);
#[allow(clippy::unusual_byte_groupings)]
#[allow(missing_docs)]
impl Color {
pub const BLACK: Color = Color(0b0_00000_00000_00000);
pub const RED: Color = Color(0b0_00000_00000_11111);
@ -305,85 +308,3 @@ impl TextEntry {
Self(id & 0b11_1111_1111)
}
}
#[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 ObjDisplayMode {
#[default]
Normal = 0 << 10,
SemiTransparent = 1 << 10,
Window = 2 << 10,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u16)]
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: ObjDisplayMode, 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);
impl ObjAttr {
#[inline]
pub const fn new() -> Self {
Self(ObjAttr0(0), ObjAttr1(0), ObjAttr2(0))
}
pub fn set_x(&mut self, x: u16) {
self.1 = self.1.with_x(x);
}
pub fn set_y(&mut self, y: u16) {
self.0 = self.0.with_y(y);
}
pub fn set_tile_id(&mut self, id: u16) {
self.2 = self.2.with_tile_id(id);
}
}

156
src/video/obj.rs Normal file
View file

@ -0,0 +1,156 @@
//! Module for object (OBJ) entry data.
//!
//! The GBA's object drawing allows for hardware drawing that is independent of
//! the background layers. Another common term for objects is "sprites", but
//! within the GBA community they're called objects, so this crate calls them
//! objects too.
//!
//! The GBA has 128 object entries within the Object Attribute Memory (OAM)
//! region. The object entries are also interspersed with the memory for the
//! affine entries, so OAM should not be thought of as being an array of just
//! one or the other types of data.
//!
//! A few of the GBA's controls will affect all objects at once, particularly
//! the Display Control (which can control if the objects are visible at all),
//! but in general each object can be controlled independently.
//!
//! Each object entry consists of a number of bit-packed "attributes". The
//! object's attributes are stored in three 16-bit fields. The [ObjAttr] struct
//! has one field for each 16-bit group of attributes: [ObjAttr0], [ObjAttr1],
//! [ObjAttr2].
//!
//! When you've got an object's data configured how you want, use either the
//! [`OBJ_ATTR_ALL`] control (to write all fields at once) or the [`OBJ_ATTR0`],
//! [`OBJ_ATTR1`], and/or [`OBJ_ATTR2`] controls (to write just some of the
//! fields).
//!
//! **Note:** When the GBA first boots, the object layer will be off but the
//! object entries in OAM will *not* be set to prevent individual objects from
//! being displayed. Before enabling the object layer you should generally set
//! the [ObjDisplayStyle] of all [ObjAttr0] fields so that any objects you're
//! not using don't appear on the screen. Otherwise, you'll end up with
//! un-configured objects appearing in the upper left corner of the display.
use super::*;
/// How the object should be displayed.
///
/// Bit 9 of Attr0 changes meaning depending on Bit 8, so this merges the two
/// bits into a single property.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u16)]
pub enum ObjDisplayStyle {
/// The default, non-affine display
#[default]
Normal = 0 << 8,
/// Affine display
Affine = 1 << 8,
/// The object is *not* displayed at all.
NotDisplayed = 2 << 8,
/// Shows the object using Affine style but double sized.
DoubleSizeAffine = 3 << 8,
}
/// What special effect the object interacts with
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u16)]
pub enum ObjEffectMode {
/// The default, no special effect interaction
#[default]
Normal = 0 << 10,
/// The object counts as a potential 1st target for alpha blending,
/// regardless of the actual blend control settings register configuration.
SemiTransparent = 1 << 10,
/// The object is not displayed. Instead, all non-transparent pixels in this
/// object become part of the "OBJ Window" mask.
Window = 2 << 10,
}
/// The shape of an object.
///
/// The object's actual display area also depends on its `size` setting:
///
/// | Size | Square | Horizontal | Vertical |
/// |:-:|:-:|:-:|:-:|
/// | 0 | 8x8 | 16x8 | 8x16 |
/// | 1 | 16x16 | 32x8 | 8x32 |
/// | 2 | 32x32 | 32x16 | 16x32 |
/// | 3 | 64x64 | 64x32 | 32x64 |
#[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,
}
/// Object Attributes, field 0 of the entry.
#[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);
}
/// Object Attributes, field 1 of the entry.
#[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);
}
/// Object Attributes, field 2 of the entry.
#[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);
}
/// Object Attributes.
///
/// The fields of this struct are all `pub` so that you can simply alter them as
/// you wish. Some "setter" methods are also provided as a shorthand.
#[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);
}
}