Merge pull request #37 from corwinkuiper/documentation

Documentation for objects and other
This commit is contained in:
Corwin 2021-06-03 19:23:25 +01:00 committed by GitHub
commit acee8351b9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 10 deletions

View file

@ -4,13 +4,21 @@ use bitflags::bitflags;
use vblank::VBlankGiver; use vblank::VBlankGiver;
use video::Video; use video::Video;
/// Graphics mode 3. Bitmap mode that provides a 16-bit colour framebuffer.
pub mod bitmap3; pub mod bitmap3;
/// Graphics mode 4. Bitmap 4 provides two 8-bit paletted framebuffers with page switching.
pub mod bitmap4; pub mod bitmap4;
/// Test logo of agb.
pub mod example_logo; pub mod example_logo;
/// Implements sprites.
pub mod object; pub mod object;
/// Palette type.
pub mod palette16; pub mod palette16;
/// Graphics mode 0. Four regular backgrounds.
pub mod tiled0; pub mod tiled0;
/// Syscall for waiting for vblank.
pub mod vblank; pub mod vblank;
/// Giving out graphics mode.
pub mod video; pub mod video;
const DISPLAY_CONTROL: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0000) }; const DISPLAY_CONTROL: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0000) };

View file

@ -4,28 +4,35 @@ use crate::memory_mapped::MemoryMapped1DArray;
const OBJECT_ATTRIBUTE_MEMORY: MemoryMapped1DArray<u16, 512> = const OBJECT_ATTRIBUTE_MEMORY: MemoryMapped1DArray<u16, 512> =
unsafe { MemoryMapped1DArray::new(0x0700_0000) }; unsafe { MemoryMapped1DArray::new(0x0700_0000) };
#[non_exhaustive] /// Handles distributing objects and matricies along with operations that effect all objects.
pub struct ObjectControl { pub struct ObjectControl {
object_count: u8, object_count: u8,
affine_count: u8, affine_count: u8,
} }
/// The standard object, without rotation.
pub struct ObjectStandard { pub struct ObjectStandard {
attributes: ObjectAttribute, attributes: ObjectAttribute,
id: u8, id: u8,
} }
/// The affine object, with potential for using a transformation matrix to alter
/// how the sprite is rendered to screen.
pub struct ObjectAffine { pub struct ObjectAffine {
attributes: ObjectAttribute, attributes: ObjectAttribute,
id: u8, id: u8,
aff_id: Option<u8>, aff_id: Option<u8>,
} }
/// Refers to an affine matrix in the OAM. Includes both an index and the
/// components of the affine matrix.
pub struct AffineMatrix { pub struct AffineMatrix {
pub attributes: AffineMatrixAttributes, pub attributes: AffineMatrixAttributes,
id: u8, id: u8,
} }
/// The components of the affine matrix. The components are fixed point 8:8.
/// TODO is a type that can handle fixed point arithmetic.
pub struct AffineMatrixAttributes { pub struct AffineMatrixAttributes {
pub p_a: i16, pub p_a: i16,
pub p_b: i16, pub p_b: i16,
@ -33,7 +40,7 @@ pub struct AffineMatrixAttributes {
pub p_d: i16, pub p_d: i16,
} }
pub enum Mode { enum Mode {
Normal = 0, Normal = 0,
Affine = 1, Affine = 1,
Hidden = 2, Hidden = 2,
@ -41,54 +48,71 @@ pub enum Mode {
} }
impl ObjectStandard { impl ObjectStandard {
/// Commits the object to OAM such that the updated version is displayed on
/// screen. Recommend to do this during VBlank.
pub fn commit(&self) { pub fn commit(&self) {
unsafe { self.attributes.commit(self.id) } unsafe { self.attributes.commit(self.id) }
} }
/// Sets the x coordinate of the sprite on screen.
pub fn set_x(&mut self, x: u8) { pub fn set_x(&mut self, x: u8) {
self.attributes.set_x(x) self.attributes.set_x(x)
} }
/// Sets the y coordinate of the sprite on screen.
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)
} }
/// Sets the index of the tile to use as the sprite. Potentially a temporary function.
pub fn set_tile_id(&mut self, id: u16) { pub fn set_tile_id(&mut self, id: u16) {
self.attributes.set_tile_id(id) self.attributes.set_tile_id(id)
} }
/// Sets whether the sprite is horizontally mirrored or not.
pub fn set_hflip(&mut self, hflip: bool) { pub fn set_hflip(&mut self, hflip: bool) {
self.attributes.set_hflip(hflip) self.attributes.set_hflip(hflip)
} }
/// Show the object on screen.
pub fn show(&mut self) { pub fn show(&mut self) {
self.attributes.set_mode(Mode::Normal) self.attributes.set_mode(Mode::Normal)
} }
/// Hide the object and do not render.
pub fn hide(&mut self) { pub fn hide(&mut self) {
self.attributes.set_mode(Mode::Hidden) self.attributes.set_mode(Mode::Hidden)
} }
} }
impl ObjectAffine { impl ObjectAffine {
/// Commits the object to OAM such that the updated version is displayed on
/// screen. Recommend to do this during VBlank.
pub fn commit(&self) { pub fn commit(&self) {
unsafe { self.attributes.commit(self.id) } unsafe { self.attributes.commit(self.id) }
} }
/// Sets the x coordinate of the sprite on screen.
pub fn set_x(&mut self, x: u8) { pub fn set_x(&mut self, x: u8) {
self.attributes.set_x(x) self.attributes.set_x(x)
} }
/// Sets the y coordinate of the sprite on screen.
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)
} }
/// Sets the index of the tile to use as the sprite. Potentially a temporary function.
pub fn set_tile_id(&mut self, id: u16) { pub fn set_tile_id(&mut self, id: u16) {
self.attributes.set_tile_id(id) self.attributes.set_tile_id(id)
} }
/// Show the object on screen. Panics if affine matrix has not been set.
pub fn show(&mut self) { pub fn show(&mut self) {
if self.aff_id.is_none() { if self.aff_id.is_none() {
panic!("affine matrix should be set") panic!("affine matrix should be set")
} }
self.attributes.set_mode(Mode::Affine) self.attributes.set_mode(Mode::Affine)
} }
/// Hide the object and do not render the sprite.
pub fn hide(&mut self) { pub fn hide(&mut self) {
self.attributes.set_mode(Mode::Hidden) self.attributes.set_mode(Mode::Hidden)
} }
/// Sets the affine matrix to use. Changing the affine matrix will change
/// how the sprite is rendered.
pub fn set_affine_mat(&mut self, aff: &AffineMatrix) { pub fn set_affine_mat(&mut self, aff: &AffineMatrix) {
self.attributes.set_affine(aff.id); self.attributes.set_affine(aff.id);
self.aff_id = Some(aff.id); self.aff_id = Some(aff.id);
@ -100,7 +124,7 @@ fn set_bits(current: u16, value: u16, length: u16, shift: u16) -> u16 {
(current & !(mask << shift)) | ((value & mask) << shift) (current & !(mask << shift)) | ((value & mask) << shift)
} }
pub struct ObjectAttribute { struct ObjectAttribute {
a0: u16, a0: u16,
a1: u16, a1: u16,
a2: u16, a2: u16,
@ -113,33 +137,34 @@ impl ObjectAttribute {
OBJECT_ATTRIBUTE_MEMORY.set(index as usize * 4 + 2, self.a2); OBJECT_ATTRIBUTE_MEMORY.set(index as usize * 4 + 2, self.a2);
} }
pub fn set_hflip(&mut self, hflip: bool) { fn set_hflip(&mut self, hflip: bool) {
self.a1 = set_bits(self.a1, hflip as u16, 1, 0xC); self.a1 = set_bits(self.a1, hflip as u16, 1, 0xC);
} }
pub fn set_x(&mut self, x: u8) { fn set_x(&mut self, x: u8) {
self.a1 = set_bits(self.a1, x as u16, 8, 0); self.a1 = set_bits(self.a1, x as u16, 8, 0);
} }
pub fn set_y(&mut self, y: u8) { fn set_y(&mut self, y: u8) {
self.a0 = set_bits(self.a0, y as u16, 8, 0) self.a0 = set_bits(self.a0, y as u16, 8, 0)
} }
pub fn set_tile_id(&mut self, id: u16) { fn set_tile_id(&mut self, id: u16) {
self.a2 = set_bits(self.a2, id, 9, 0); self.a2 = set_bits(self.a2, id, 9, 0);
} }
pub fn set_mode(&mut self, mode: Mode) { fn set_mode(&mut self, mode: Mode) {
self.a0 = set_bits(self.a0, mode as u16, 2, 8); self.a0 = set_bits(self.a0, mode as u16, 2, 8);
} }
pub fn set_affine(&mut self, aff_id: u8) { fn set_affine(&mut self, aff_id: u8) {
self.a1 = set_bits(self.a1, aff_id as u16, 5, 8); self.a1 = set_bits(self.a1, aff_id as u16, 5, 8);
} }
} }
impl AffineMatrix { impl AffineMatrix {
#[allow(clippy::identity_op)] #[allow(clippy::identity_op)]
/// Commits matrix to OAM, will cause any objects using this matrix to be updated.
pub fn commit(&self) { pub fn commit(&self) {
let id = self.id as usize; let id = self.id as usize;
OBJECT_ATTRIBUTE_MEMORY.set((id + 0) * 4 + 3, self.attributes.p_a as u16); OBJECT_ATTRIBUTE_MEMORY.set((id + 0) * 4 + 3, self.attributes.p_a as u16);
@ -172,18 +197,24 @@ impl ObjectControl {
} }
} }
/// Enable objects on the GBA.
pub fn enable(&mut self) { pub fn enable(&mut self) {
let disp = DISPLAY_CONTROL.get(); let disp = DISPLAY_CONTROL.get();
let disp = disp | (1 << 0x0C); let disp = disp | (1 << 0x0C);
DISPLAY_CONTROL.set(disp); DISPLAY_CONTROL.set(disp);
} }
/// Disable objects, objects won't be rendered.
pub fn disable(&mut self) { pub fn disable(&mut self) {
let disp = DISPLAY_CONTROL.get(); let disp = DISPLAY_CONTROL.get();
let disp = disp & !(1 << 0x0C); let disp = disp & !(1 << 0x0C);
DISPLAY_CONTROL.set(disp); DISPLAY_CONTROL.set(disp);
} }
/// Get an unused standard object. Currently dropping an unused object will
/// not free this. You should either keep around all objects you need
/// forever or drop and reobtain ObjectControl. Panics if more than 128
/// objects are obtained.
pub fn get_object_standard(&mut self) -> ObjectStandard { pub fn get_object_standard(&mut self) -> ObjectStandard {
let id = self.object_count; let id = self.object_count;
self.object_count += 1; self.object_count += 1;
@ -194,6 +225,10 @@ impl ObjectControl {
} }
} }
/// Get an unused affine object. Currently dropping an unused object will
/// not free this. You should either keep around all objects you need
/// forever or drop and reobtain ObjectControl. Panics if more than 128
/// objects are obtained.
pub fn get_object_affine(&mut self) -> ObjectAffine { pub fn get_object_affine(&mut self) -> ObjectAffine {
let id = self.object_count; let id = self.object_count;
self.object_count += 1; self.object_count += 1;
@ -205,6 +240,10 @@ impl ObjectControl {
} }
} }
/// Get an unused affine matrix. Currently dropping an unused object will
/// not free this. You should either keep around all affine matricies you
/// need forever or drop and reobtain ObjectControl. Panics if more than 32
/// affine matricies are obtained.
pub fn get_affine(&mut self) -> AffineMatrix { pub fn get_affine(&mut self) -> AffineMatrix {
let id = self.affine_count; let id = self.affine_count;
self.affine_count += 1; self.affine_count += 1;

View file

@ -7,16 +7,27 @@
#![test_runner(crate::test_runner)] #![test_runner(crate::test_runner)]
#![reexport_test_harness_main = "test_main"] #![reexport_test_harness_main = "test_main"]
//! # agb
//! `agb` is a library for making games on the Game Boy Advance using the Rust
//! programming language. It attempts to be a high level abstraction over the
//! internal workings of the Game Boy Advance whilst still being high
//! performance and memory efficient.
/// Implements everything relating to things that are displayed on screen.
pub mod display; pub mod display;
/// Button inputs to the system.
pub mod input; pub mod input;
/// Implements sound output.
pub mod sound; pub mod sound;
mod interrupt; mod interrupt;
mod memory_mapped; mod memory_mapped;
/// Implements logging to the mgba emulator.
pub mod mgba; pub mod mgba;
pub mod number; mod number;
mod single; mod single;
/// System BIOS calls / syscalls.
pub mod syscall; pub mod syscall;
#[cfg(not(test))] #[cfg(not(test))]