From cc48605f4a4d7ddc2ed02d9bd49fb718b6e298db Mon Sep 17 00:00:00 2001 From: Corwin Kuiper Date: Sat, 6 Mar 2021 22:46:55 +0000 Subject: [PATCH] move display modes to own file --- src/display.rs | 192 ----------------------------------------- src/display/bitmap3.rs | 27 ++++++ src/display/bitmap4.rs | 78 +++++++++++++++++ src/display/mod.rs | 102 ++++++++++++++++++++++ 4 files changed, 207 insertions(+), 192 deletions(-) delete mode 100644 src/display.rs create mode 100644 src/display/bitmap3.rs create mode 100644 src/display/bitmap4.rs create mode 100644 src/display/mod.rs diff --git a/src/display.rs b/src/display.rs deleted file mode 100644 index ca42ca77..00000000 --- a/src/display.rs +++ /dev/null @@ -1,192 +0,0 @@ -use crate::{ - memory_mapped::{MemoryMapped, MemoryMapped1DArray, MemoryMapped2DArray}, - single::{Single, SingleToken}, -}; -use bitflags::bitflags; -use core::convert::TryInto; - -const DISPLAY_CONTROL: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0000) }; -const DISPLAY_STATUS: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0004) }; -const VCOUNT: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0006) }; - -const PALETTE_BACKGROUND: MemoryMapped1DArray = - unsafe { MemoryMapped1DArray::new(0x0500_0000) }; -const PALETTE_SPRITE: MemoryMapped1DArray = - unsafe { MemoryMapped1DArray::new(0x0500_0200) }; - -const BITMAP_MODE_3: MemoryMapped2DArray = - unsafe { MemoryMapped2DArray::new(0x600_0000) }; - -const BITMAP_PAGE_FRONT_MODE_4: MemoryMapped2DArray< - u16, - { (WIDTH / 2) as usize }, - { HEIGHT as usize }, -> = unsafe { MemoryMapped2DArray::new(0x600_0000) }; -const BITMAP_PAGE_BACK_MODE_4: MemoryMapped2DArray< - u16, - { (WIDTH / 2) as usize }, - { HEIGHT as usize }, -> = unsafe { MemoryMapped2DArray::new(0x600_A000) }; - -pub const WIDTH: i32 = 240; -pub const HEIGHT: i32 = 160; - -pub enum DisplayMode { - Tiled0 = 0, - Tiled1 = 1, - Tiled2 = 2, - Bitmap3 = 3, - Bitmap4 = 4, - Bitmap5 = 5, -} - -pub enum Page { - Front = 0, - Back = 1, -} - -bitflags! { - pub struct GraphicsSettings: u16 { - const PAGE_SELECT = 1 << 0x4; - const OAM_HBLANK = 1 << 0x5; - const SPRITE1_D = 1 << 0x6; - const SCREEN_BLANK = 1 << 0x7; - const LAYER_BG0 = 1 << 0x8; - const LAYER_BG1 = 1 << 0x9; - const LAYER_BG2 = 1 << 0xA; - const LAYER_BG3 = 1 << 0xB; - const LAYER_OBJ = 1 << 0xC; - const WINDOW0 = 1 << 0xD; - const WINDOW1 = 1 << 0xE; - const WINDOW_OBJECT = 1 << 0xF; - } -} - -pub struct Display { - in_mode: Single, -} - -impl Display { - pub(crate) const unsafe fn new() -> Self { - Display { - in_mode: Single::new(), - } - } - - pub fn bitmap3(&self) -> Bitmap3 { - Bitmap3::new( - self.in_mode - .take() - .expect("Cannot create new mode as mode already taken"), - ) - } - pub fn bitmap4(&self) -> Bitmap4 { - Bitmap4::new( - self.in_mode - .take() - .expect("Cannot create new mode as mode already taken"), - ) - } -} - -pub struct Bitmap3<'a> { - _in_mode: SingleToken<'a>, -} - -impl<'a> Bitmap3<'a> { - fn new(in_mode: SingleToken<'a>) -> Self { - set_graphics_mode(DisplayMode::Bitmap3); - set_graphics_settings(GraphicsSettings::LAYER_BG2); - Bitmap3 { _in_mode: in_mode } - } - pub fn draw_point(&self, x: i32, y: i32, colour: u16) { - let x = x.try_into().unwrap(); - let y = y.try_into().unwrap(); - BITMAP_MODE_3.set(x, y, colour) - } -} - -pub struct Bitmap4<'a> { - _in_mode: SingleToken<'a>, -} - -impl<'a> Bitmap4<'a> { - fn new(in_mode: SingleToken<'a>) -> Self { - set_graphics_mode(DisplayMode::Bitmap4); - set_graphics_settings(GraphicsSettings::LAYER_BG2); - Bitmap4 { _in_mode: in_mode } - } - - pub fn draw_point_page(&self, x: i32, y: i32, colour: u8, page: Page) { - let addr = match page { - Page::Front => BITMAP_PAGE_FRONT_MODE_4, - Page::Back => BITMAP_PAGE_BACK_MODE_4, - }; - - let x_in_screen = (x / 2) as usize; - let y_in_screen = y as usize; - - let c = addr.get(x_in_screen, y_in_screen); - if x & 0b1 != 0 { - addr.set(x_in_screen, y_in_screen, c | (colour as u16) << 8); - } else { - addr.set(x_in_screen, y_in_screen, c | colour as u16); - } - } - - pub fn draw_point(&self, x: i32, y: i32, colour: u8) { - let disp = DISPLAY_CONTROL.get(); - - let page = if disp & GraphicsSettings::PAGE_SELECT.bits() != 0 { - Page::Back - } else { - Page::Front - }; - - self.draw_point_page(x, y, colour, page) - } - - pub fn set_palette_entry(&self, entry: u32, colour: u16) { - PALETTE_BACKGROUND.set(entry as usize, colour); - } - - pub fn flip_page(&self) { - let disp = DISPLAY_CONTROL.get(); - let swapped = disp ^ GraphicsSettings::PAGE_SELECT.bits(); - DISPLAY_CONTROL.set(swapped); - } -} - -fn set_graphics_mode(mode: DisplayMode) { - let current = DISPLAY_CONTROL.get(); - let current = current & (!0b111); - let s = current | (mode as u16 & 0b111); - - DISPLAY_CONTROL.set(s); -} - -pub fn set_graphics_settings(settings: GraphicsSettings) { - let current = DISPLAY_CONTROL.get(); - // preserve display mode - let current = current & 0b111; - let s = settings.bits() | current; - - DISPLAY_CONTROL.set(s); -} - -#[allow(non_snake_case)] -pub fn busy_wait_for_VBlank() { - while VCOUNT.get() >= 160 {} - while VCOUNT.get() < 160 {} -} - -#[allow(non_snake_case)] -pub fn enable_VBlank_interrupt() { - let status = DISPLAY_STATUS.get() | (1 << 3); - DISPLAY_STATUS.set(status); -} - -#[allow(non_snake_case)] -pub fn wait_for_VBlank() { - crate::syscall::wait_for_VBlank(); -} diff --git a/src/display/bitmap3.rs b/src/display/bitmap3.rs new file mode 100644 index 00000000..b72b60a9 --- /dev/null +++ b/src/display/bitmap3.rs @@ -0,0 +1,27 @@ +use crate::{memory_mapped::MemoryMapped2DArray, single::SingleToken}; + +use super::{ + set_graphics_mode, set_graphics_settings, DisplayMode, GraphicsSettings, HEIGHT, WIDTH, +}; + +use core::convert::TryInto; + +const BITMAP_MODE_3: MemoryMapped2DArray = + unsafe { MemoryMapped2DArray::new(0x600_0000) }; + +pub struct Bitmap3<'a> { + _in_mode: SingleToken<'a>, +} + +impl<'a> Bitmap3<'a> { + pub(crate) fn new(in_mode: SingleToken<'a>) -> Self { + set_graphics_mode(DisplayMode::Bitmap3); + set_graphics_settings(GraphicsSettings::LAYER_BG2); + Bitmap3 { _in_mode: in_mode } + } + pub fn draw_point(&self, x: i32, y: i32, colour: u16) { + let x = x.try_into().unwrap(); + let y = y.try_into().unwrap(); + BITMAP_MODE_3.set(x, y, colour) + } +} diff --git a/src/display/bitmap4.rs b/src/display/bitmap4.rs new file mode 100644 index 00000000..90a01740 --- /dev/null +++ b/src/display/bitmap4.rs @@ -0,0 +1,78 @@ +use crate::{ + memory_mapped::{MemoryMapped1DArray, MemoryMapped2DArray}, + single::SingleToken, +}; + +use super::{ + set_graphics_mode, set_graphics_settings, DisplayMode, GraphicsSettings, DISPLAY_CONTROL, + HEIGHT, WIDTH, +}; + +const BITMAP_PAGE_FRONT_MODE_4: MemoryMapped2DArray< + u16, + { (WIDTH / 2) as usize }, + { HEIGHT as usize }, +> = unsafe { MemoryMapped2DArray::new(0x600_0000) }; +const BITMAP_PAGE_BACK_MODE_4: MemoryMapped2DArray< + u16, + { (WIDTH / 2) as usize }, + { HEIGHT as usize }, +> = unsafe { MemoryMapped2DArray::new(0x600_A000) }; +const PALETTE_BACKGROUND: MemoryMapped1DArray = + unsafe { MemoryMapped1DArray::new(0x0500_0000) }; + +pub enum Page { + Front = 0, + Back = 1, +} + +pub struct Bitmap4<'a> { + _in_mode: SingleToken<'a>, +} + +impl<'a> Bitmap4<'a> { + pub(crate) fn new(in_mode: SingleToken<'a>) -> Self { + set_graphics_mode(DisplayMode::Bitmap4); + set_graphics_settings(GraphicsSettings::LAYER_BG2); + Bitmap4 { _in_mode: in_mode } + } + + pub fn draw_point_page(&self, x: i32, y: i32, colour: u8, page: Page) { + let addr = match page { + Page::Front => BITMAP_PAGE_FRONT_MODE_4, + Page::Back => BITMAP_PAGE_BACK_MODE_4, + }; + + let x_in_screen = (x / 2) as usize; + let y_in_screen = y as usize; + + let c = addr.get(x_in_screen, y_in_screen); + if x & 0b1 != 0 { + addr.set(x_in_screen, y_in_screen, c | (colour as u16) << 8); + } else { + addr.set(x_in_screen, y_in_screen, c | colour as u16); + } + } + + pub fn draw_point(&self, x: i32, y: i32, colour: u8) { + let disp = DISPLAY_CONTROL.get(); + + let page = if disp & GraphicsSettings::PAGE_SELECT.bits() != 0 { + Page::Back + } else { + Page::Front + }; + + self.draw_point_page(x, y, colour, page) + } + + pub fn set_palette_entry(&self, entry: u32, colour: u16) { + PALETTE_BACKGROUND.set(entry as usize, colour); + } + + pub fn flip_page(&self) { + let disp = DISPLAY_CONTROL.get(); + let swapped = disp ^ GraphicsSettings::PAGE_SELECT.bits(); + DISPLAY_CONTROL.set(swapped); + } +} diff --git a/src/display/mod.rs b/src/display/mod.rs new file mode 100644 index 00000000..2bbcb8db --- /dev/null +++ b/src/display/mod.rs @@ -0,0 +1,102 @@ +use crate::{memory_mapped::MemoryMapped, single::Single}; +use bitflags::bitflags; + +use bitmap3::Bitmap3; +use bitmap4::Bitmap4; + +mod bitmap3; +mod bitmap4; + +const DISPLAY_CONTROL: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0000) }; +const DISPLAY_STATUS: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0004) }; +const VCOUNT: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0006) }; + +bitflags! { + pub struct GraphicsSettings: u16 { + const PAGE_SELECT = 1 << 0x4; + const OAM_HBLANK = 1 << 0x5; + const SPRITE1_D = 1 << 0x6; + const SCREEN_BLANK = 1 << 0x7; + const LAYER_BG0 = 1 << 0x8; + const LAYER_BG1 = 1 << 0x9; + const LAYER_BG2 = 1 << 0xA; + const LAYER_BG3 = 1 << 0xB; + const LAYER_OBJ = 1 << 0xC; + const WINDOW0 = 1 << 0xD; + const WINDOW1 = 1 << 0xE; + const WINDOW_OBJECT = 1 << 0xF; + } +} + +pub const WIDTH: i32 = 240; +pub const HEIGHT: i32 = 160; + +pub enum DisplayMode { + Tiled0 = 0, + Tiled1 = 1, + Tiled2 = 2, + Bitmap3 = 3, + Bitmap4 = 4, + Bitmap5 = 5, +} + +pub struct Display { + in_mode: Single, +} + +impl Display { + pub(crate) const unsafe fn new() -> Self { + Display { + in_mode: Single::new(), + } + } + + pub fn bitmap3(&self) -> Bitmap3 { + Bitmap3::new( + self.in_mode + .take() + .expect("Cannot create new mode as mode already taken"), + ) + } + pub fn bitmap4(&self) -> Bitmap4 { + bitmap4::Bitmap4::new( + self.in_mode + .take() + .expect("Cannot create new mode as mode already taken"), + ) + } +} + +fn set_graphics_mode(mode: DisplayMode) { + let current = DISPLAY_CONTROL.get(); + let current = current & (!0b111); + let s = current | (mode as u16 & 0b111); + + DISPLAY_CONTROL.set(s); +} + +pub fn set_graphics_settings(settings: GraphicsSettings) { + let current = DISPLAY_CONTROL.get(); + // preserve display mode + let current = current & 0b111; + let s = settings.bits() | current; + + DISPLAY_CONTROL.set(s); +} + +#[allow(non_snake_case)] +pub fn busy_wait_for_VBlank() { + while VCOUNT.get() >= 160 {} + while VCOUNT.get() < 160 {} +} + +#[allow(non_snake_case)] +pub fn enable_VBlank_interrupt() { + let status = DISPLAY_STATUS.get() | (1 << 3); + DISPLAY_STATUS.set(status); +} + +#[allow(non_snake_case)] +pub fn wait_for_VBlank() { + crate::syscall::wait_for_VBlank(); +}