mirror of
https://github.com/italicsjenga/agb.git
synced 2025-01-26 00:56:38 +11:00
move display modes to own file
This commit is contained in:
parent
9b0bdb17e5
commit
cc48605f4a
4 changed files with 207 additions and 192 deletions
192
src/display.rs
192
src/display.rs
|
@ -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<u16> = unsafe { MemoryMapped::new(0x0400_0000) };
|
|
||||||
const DISPLAY_STATUS: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0004) };
|
|
||||||
const VCOUNT: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0006) };
|
|
||||||
|
|
||||||
const PALETTE_BACKGROUND: MemoryMapped1DArray<u16, 256> =
|
|
||||||
unsafe { MemoryMapped1DArray::new(0x0500_0000) };
|
|
||||||
const PALETTE_SPRITE: MemoryMapped1DArray<u16, 256> =
|
|
||||||
unsafe { MemoryMapped1DArray::new(0x0500_0200) };
|
|
||||||
|
|
||||||
const BITMAP_MODE_3: MemoryMapped2DArray<u16, { WIDTH as usize }, { HEIGHT as usize }> =
|
|
||||||
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();
|
|
||||||
}
|
|
27
src/display/bitmap3.rs
Normal file
27
src/display/bitmap3.rs
Normal file
|
@ -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<u16, { WIDTH as usize }, { HEIGHT as usize }> =
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
78
src/display/bitmap4.rs
Normal file
78
src/display/bitmap4.rs
Normal file
|
@ -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<u16, 256> =
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
102
src/display/mod.rs
Normal file
102
src/display/mod.rs
Normal file
|
@ -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<u16> = unsafe { MemoryMapped::new(0x0400_0000) };
|
||||||
|
const DISPLAY_STATUS: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0004) };
|
||||||
|
const VCOUNT: MemoryMapped<u16> = 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();
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue