mirror of
https://github.com/italicsjenga/agb.git
synced 2025-01-22 23:26:33 +11:00
refactor and add doc strings to display
This commit is contained in:
parent
9527d32521
commit
ac88468333
4 changed files with 51 additions and 19 deletions
3
Makefile
3
Makefile
|
@ -42,3 +42,6 @@ out/crt0.o: crt0.s interrupt_simple.s
|
||||||
|
|
||||||
clippy:
|
clippy:
|
||||||
rustup run nightly cargo xclippy --target=gba.json
|
rustup run nightly cargo xclippy --target=gba.json
|
||||||
|
|
||||||
|
doc:
|
||||||
|
rustup run nightly cargo xdoc --target=gba.json
|
|
@ -14,11 +14,14 @@ pub struct Bitmap3<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Bitmap3<'a> {
|
impl<'a> Bitmap3<'a> {
|
||||||
pub(crate) fn new(in_mode: SingleToken<'a>) -> Self {
|
pub(crate) unsafe fn new(in_mode: SingleToken<'a>) -> Self {
|
||||||
set_graphics_mode(DisplayMode::Bitmap3);
|
set_graphics_mode(DisplayMode::Bitmap3);
|
||||||
set_graphics_settings(GraphicsSettings::LAYER_BG2);
|
set_graphics_settings(GraphicsSettings::LAYER_BG2);
|
||||||
Bitmap3 { _in_mode: in_mode }
|
Bitmap3 { _in_mode: in_mode }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draws point to screen at (x, y) coordinates with colour and panics if
|
||||||
|
/// (x, y) is out of the bounds of the screen.
|
||||||
pub fn draw_point(&self, x: i32, y: i32, colour: u16) {
|
pub fn draw_point(&self, x: i32, y: i32, colour: u16) {
|
||||||
let x = x.try_into().unwrap();
|
let x = x.try_into().unwrap();
|
||||||
let y = y.try_into().unwrap();
|
let y = y.try_into().unwrap();
|
||||||
|
|
|
@ -31,12 +31,15 @@ pub struct Bitmap4<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Bitmap4<'a> {
|
impl<'a> Bitmap4<'a> {
|
||||||
pub(crate) fn new(in_mode: SingleToken<'a>) -> Self {
|
pub(crate) unsafe fn new(in_mode: SingleToken<'a>) -> Self {
|
||||||
set_graphics_mode(DisplayMode::Bitmap4);
|
set_graphics_mode(DisplayMode::Bitmap4);
|
||||||
set_graphics_settings(GraphicsSettings::LAYER_BG2);
|
set_graphics_settings(GraphicsSettings::LAYER_BG2);
|
||||||
Bitmap4 { _in_mode: in_mode }
|
Bitmap4 { _in_mode: in_mode }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draws point on specified page at (x, y) coordinates with colour index
|
||||||
|
/// whose colour is specified in the background palette. Panics if (x, y) is
|
||||||
|
/// out of the bounds of the screen.
|
||||||
pub fn draw_point_page(&self, x: i32, y: i32, colour: u8, page: Page) {
|
pub fn draw_point_page(&self, x: i32, y: i32, colour: u8, page: Page) {
|
||||||
let addr = match page {
|
let addr = match page {
|
||||||
Page::Front => BITMAP_PAGE_FRONT_MODE_4,
|
Page::Front => BITMAP_PAGE_FRONT_MODE_4,
|
||||||
|
@ -54,22 +57,29 @@ impl<'a> Bitmap4<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draws point on the non-current page at (x, y) coordinates with colour
|
||||||
|
/// index whose colour is specified in the background palette. Panics if (x,
|
||||||
|
/// y) is out of the bounds of the screen.
|
||||||
pub fn draw_point(&self, x: i32, y: i32, colour: u8) {
|
pub fn draw_point(&self, x: i32, y: i32, colour: u8) {
|
||||||
let disp = DISPLAY_CONTROL.get();
|
let disp = DISPLAY_CONTROL.get();
|
||||||
|
|
||||||
|
// get other page
|
||||||
let page = if disp & GraphicsSettings::PAGE_SELECT.bits() != 0 {
|
let page = if disp & GraphicsSettings::PAGE_SELECT.bits() != 0 {
|
||||||
Page::Back
|
|
||||||
} else {
|
|
||||||
Page::Front
|
Page::Front
|
||||||
|
} else {
|
||||||
|
Page::Back
|
||||||
};
|
};
|
||||||
|
|
||||||
self.draw_point_page(x, y, colour, page)
|
self.draw_point_page(x, y, colour, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the colour of colour index in the background palette.
|
||||||
pub fn set_palette_entry(&self, entry: u32, colour: u16) {
|
pub fn set_palette_entry(&self, entry: u32, colour: u16) {
|
||||||
PALETTE_BACKGROUND.set(entry as usize, colour);
|
PALETTE_BACKGROUND.set(entry as usize, colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Flips page, changing the Gameboy advance to draw the contents of the
|
||||||
|
/// other page
|
||||||
pub fn flip_page(&self) {
|
pub fn flip_page(&self) {
|
||||||
let disp = DISPLAY_CONTROL.get();
|
let disp = DISPLAY_CONTROL.get();
|
||||||
let swapped = disp ^ GraphicsSettings::PAGE_SELECT.bits();
|
let swapped = disp ^ GraphicsSettings::PAGE_SELECT.bits();
|
||||||
|
|
|
@ -15,7 +15,7 @@ const DISPLAY_STATUS: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0004
|
||||||
const VCOUNT: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0006) };
|
const VCOUNT: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0006) };
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct GraphicsSettings: u16 {
|
struct GraphicsSettings: u16 {
|
||||||
const PAGE_SELECT = 1 << 0x4;
|
const PAGE_SELECT = 1 << 0x4;
|
||||||
const OAM_HBLANK = 1 << 0x5;
|
const OAM_HBLANK = 1 << 0x5;
|
||||||
const SPRITE1_D = 1 << 0x6;
|
const SPRITE1_D = 1 << 0x6;
|
||||||
|
@ -31,10 +31,12 @@ bitflags! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Width of the Gameboy advance screen in pixels
|
||||||
pub const WIDTH: i32 = 240;
|
pub const WIDTH: i32 = 240;
|
||||||
|
/// Height of the Gameboy advance screen in pixels
|
||||||
pub const HEIGHT: i32 = 160;
|
pub const HEIGHT: i32 = 160;
|
||||||
|
|
||||||
pub enum DisplayMode {
|
enum DisplayMode {
|
||||||
Tiled0 = 0,
|
Tiled0 = 0,
|
||||||
Tiled1 = 1,
|
Tiled1 = 1,
|
||||||
Tiled2 = 2,
|
Tiled2 = 2,
|
||||||
|
@ -43,6 +45,7 @@ pub enum DisplayMode {
|
||||||
Bitmap5 = 5,
|
Bitmap5 = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Manages distribution of display modes, obtained from the gba struct
|
||||||
pub struct Display {
|
pub struct Display {
|
||||||
in_mode: Single,
|
in_mode: Single,
|
||||||
vblank: Single,
|
vblank: Single,
|
||||||
|
@ -56,20 +59,29 @@ impl Display {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Bitmap mode that provides a 16-bit colour framebuffer
|
||||||
pub fn bitmap3(&self) -> Bitmap3 {
|
pub fn bitmap3(&self) -> Bitmap3 {
|
||||||
|
unsafe {
|
||||||
Bitmap3::new(
|
Bitmap3::new(
|
||||||
self.in_mode
|
self.in_mode
|
||||||
.take()
|
.take()
|
||||||
.expect("Cannot create new mode as mode already taken"),
|
.expect("Cannot create new mode as mode already taken"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bitmap 4 provides two 8-bit paletted framebuffers with page switching
|
||||||
pub fn bitmap4(&self) -> Bitmap4 {
|
pub fn bitmap4(&self) -> Bitmap4 {
|
||||||
|
unsafe {
|
||||||
bitmap4::Bitmap4::new(
|
bitmap4::Bitmap4::new(
|
||||||
self.in_mode
|
self.in_mode
|
||||||
.take()
|
.take()
|
||||||
.expect("Cannot create new mode as mode already taken"),
|
.expect("Cannot create new mode as mode already taken"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets a vblank handle where only one can be obtained at a time
|
||||||
pub fn get_vblank(&self) -> VBlank {
|
pub fn get_vblank(&self) -> VBlank {
|
||||||
unsafe {
|
unsafe {
|
||||||
VBlank::new(
|
VBlank::new(
|
||||||
|
@ -81,7 +93,7 @@ impl Display {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_graphics_mode(mode: DisplayMode) {
|
unsafe fn set_graphics_mode(mode: DisplayMode) {
|
||||||
let current = DISPLAY_CONTROL.get();
|
let current = DISPLAY_CONTROL.get();
|
||||||
let current = current & (!0b111);
|
let current = current & (!0b111);
|
||||||
let s = current | (mode as u16 & 0b111);
|
let s = current | (mode as u16 & 0b111);
|
||||||
|
@ -89,7 +101,7 @@ fn set_graphics_mode(mode: DisplayMode) {
|
||||||
DISPLAY_CONTROL.set(s);
|
DISPLAY_CONTROL.set(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_graphics_settings(settings: GraphicsSettings) {
|
unsafe fn set_graphics_settings(settings: GraphicsSettings) {
|
||||||
let current = DISPLAY_CONTROL.get();
|
let current = DISPLAY_CONTROL.get();
|
||||||
// preserve display mode
|
// preserve display mode
|
||||||
let current = current & 0b111;
|
let current = current & 0b111;
|
||||||
|
@ -107,6 +119,8 @@ pub fn busy_wait_for_VBlank() {
|
||||||
while VCOUNT.get() < 160 {}
|
while VCOUNT.get() < 160 {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Once obtained, this guarentees that interrupts are enabled and set up to
|
||||||
|
/// allow for waiting for vblank
|
||||||
pub struct VBlank<'a> {
|
pub struct VBlank<'a> {
|
||||||
_got: SingleToken<'a>,
|
_got: SingleToken<'a>,
|
||||||
}
|
}
|
||||||
|
@ -120,6 +134,8 @@ impl<'a> VBlank<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
/// Waits for VBlank using interrupts. This is the preferred method for
|
||||||
|
/// waiting until the next frame.
|
||||||
pub fn wait_for_VBlank(&self) {
|
pub fn wait_for_VBlank(&self) {
|
||||||
crate::syscall::wait_for_VBlank();
|
crate::syscall::wait_for_VBlank();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue