mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 16:21:33 +11:00
add abstraction over windows
This commit is contained in:
parent
10423d0752
commit
a188e7ba66
|
@ -121,6 +121,7 @@ macro_rules! fixed_width_signed_integer_impl {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fixed_width_unsigned_integer_impl!(u8);
|
||||||
fixed_width_unsigned_integer_impl!(i16);
|
fixed_width_unsigned_integer_impl!(i16);
|
||||||
fixed_width_unsigned_integer_impl!(u16);
|
fixed_width_unsigned_integer_impl!(u16);
|
||||||
fixed_width_unsigned_integer_impl!(i32);
|
fixed_width_unsigned_integer_impl!(i32);
|
||||||
|
|
|
@ -4,7 +4,7 @@ use bitflags::bitflags;
|
||||||
use modular_bitfield::BitfieldSpecifier;
|
use modular_bitfield::BitfieldSpecifier;
|
||||||
use video::Video;
|
use video::Video;
|
||||||
|
|
||||||
use self::object::ObjectController;
|
use self::{object::ObjectController, window::Windows};
|
||||||
|
|
||||||
/// Graphics mode 3. Bitmap mode that provides a 16-bit colour framebuffer.
|
/// Graphics mode 3. Bitmap mode that provides a 16-bit colour framebuffer.
|
||||||
pub mod bitmap3;
|
pub mod bitmap3;
|
||||||
|
@ -23,6 +23,8 @@ pub mod tiled;
|
||||||
/// Giving out graphics mode.
|
/// Giving out graphics mode.
|
||||||
pub mod video;
|
pub mod video;
|
||||||
|
|
||||||
|
pub mod window;
|
||||||
|
|
||||||
mod font;
|
mod font;
|
||||||
pub use font::{Font, FontLetter};
|
pub use font::{Font, FontLetter};
|
||||||
|
|
||||||
|
@ -67,6 +69,7 @@ enum DisplayMode {
|
||||||
pub struct Display {
|
pub struct Display {
|
||||||
pub video: Video,
|
pub video: Video,
|
||||||
pub object: ObjectDistribution,
|
pub object: ObjectDistribution,
|
||||||
|
pub window: WindowDist,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
@ -78,11 +81,21 @@ impl ObjectDistribution {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub struct WindowDist {}
|
||||||
|
|
||||||
|
impl WindowDist {
|
||||||
|
pub fn get(&mut self) -> Windows {
|
||||||
|
Windows::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display {
|
impl Display {
|
||||||
pub(crate) const unsafe fn new() -> Self {
|
pub(crate) const unsafe fn new() -> Self {
|
||||||
Display {
|
Display {
|
||||||
video: Video {},
|
video: Video {},
|
||||||
object: ObjectDistribution {},
|
object: ObjectDistribution {},
|
||||||
|
window: WindowDist {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
152
agb/src/display/window.rs
Normal file
152
agb/src/display/window.rs
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
use agb_fixnum::Rect;
|
||||||
|
|
||||||
|
use crate::memory_mapped::MemoryMapped;
|
||||||
|
|
||||||
|
use super::tiled::BackgroundID;
|
||||||
|
|
||||||
|
pub struct Windows {
|
||||||
|
wins: [MovableWindow; 2],
|
||||||
|
out: Window,
|
||||||
|
obj: Window,
|
||||||
|
}
|
||||||
|
|
||||||
|
const REG_HORIZONTAL_BASE: *mut u16 = 0x0400_0040 as *mut _;
|
||||||
|
const REG_VERTICAL_BASE: *mut u16 = 0x0400_0044 as *mut _;
|
||||||
|
|
||||||
|
const REG_WINDOW_CONTROL_BASE: *mut u16 = 0x0400_0048 as *mut _;
|
||||||
|
|
||||||
|
pub enum WinIn {
|
||||||
|
Win0,
|
||||||
|
Win1,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Windows {
|
||||||
|
pub(crate) fn new() -> Self {
|
||||||
|
let s = Self {
|
||||||
|
wins: [MovableWindow::new(), MovableWindow::new()],
|
||||||
|
out: Window::new(),
|
||||||
|
obj: Window::new(),
|
||||||
|
};
|
||||||
|
s.commit();
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enable(&self) {}
|
||||||
|
|
||||||
|
pub fn disable(&self) {}
|
||||||
|
|
||||||
|
pub fn win_out(&mut self) -> &mut Window {
|
||||||
|
&mut self.out
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn win_in(&mut self, id: WinIn) -> &mut MovableWindow {
|
||||||
|
&mut self.wins[id as usize]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn win_obj(&mut self) -> &mut Window {
|
||||||
|
&mut self.obj
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn commit(&self) {
|
||||||
|
for (id, win) in self.wins.iter().enumerate() {
|
||||||
|
win.commit(id);
|
||||||
|
}
|
||||||
|
self.obj.commit(3);
|
||||||
|
self.out.commit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Window {
|
||||||
|
window_bits: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MovableWindow {
|
||||||
|
inner: Window,
|
||||||
|
rect: Rect<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Window {
|
||||||
|
fn new() -> Window {
|
||||||
|
Self { window_bits: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_bit(&mut self, bit: usize, value: bool) {
|
||||||
|
self.window_bits &= u8::MAX ^ (1 << bit);
|
||||||
|
self.window_bits |= (value as u8) << bit;
|
||||||
|
}
|
||||||
|
pub fn set_blend_enable(&mut self, blnd: bool) -> &mut Self {
|
||||||
|
self.set_bit(5, blnd);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn set_background_enable(&mut self, back: BackgroundID, enable: bool) -> &mut Self {
|
||||||
|
self.set_bit(back.0 as usize, enable);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn set_object_enable(&mut self, obj: bool) -> &mut Self {
|
||||||
|
self.set_bit(4, obj);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn commit(&self, id: usize) {
|
||||||
|
let base_reg = id / 2;
|
||||||
|
let offset_in_reg = (id % 2) * 8;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let reg = MemoryMapped::new(REG_WINDOW_CONTROL_BASE.add(base_reg) as usize);
|
||||||
|
reg.set_bits(self.window_bits as u16, 8, offset_in_reg as u16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MovableWindow {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: Window::new(),
|
||||||
|
rect: Rect::new((0, 0).into(), (0, 0).into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_blend_enable(&mut self, blnd: bool) -> &mut Self {
|
||||||
|
self.inner.set_blend_enable(blnd);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn set_background_enable(&mut self, back: BackgroundID, enable: bool) -> &mut Self {
|
||||||
|
self.inner.set_background_enable(back, enable);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn set_object_enable(&mut self, obj: bool) -> &mut Self {
|
||||||
|
self.inner.set_object_enable(obj);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn commit(&self, id: usize) {
|
||||||
|
self.inner.commit(id);
|
||||||
|
|
||||||
|
let left_right =
|
||||||
|
(self.rect.position.x as u16) << 8 | (self.rect.position.x + self.rect.size.x) as u16;
|
||||||
|
|
||||||
|
let top_bottom =
|
||||||
|
(self.rect.position.y as u16) << 8 | (self.rect.position.y + self.rect.size.y) as u16;
|
||||||
|
unsafe {
|
||||||
|
REG_HORIZONTAL_BASE.add(id).write_volatile(left_right);
|
||||||
|
REG_VERTICAL_BASE.add(id).write_volatile(top_bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_position_byte(&mut self, rect: Rect<u8>) -> &mut Self {
|
||||||
|
self.rect = rect;
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_position(&mut self, rect: &Rect<i32>) -> &mut Self {
|
||||||
|
let new_rect = Rect::new(
|
||||||
|
(rect.position.x as u8, rect.position.y as u8).into(),
|
||||||
|
(rect.size.x as u8, rect.size.y as u8).into(),
|
||||||
|
);
|
||||||
|
self.set_position_byte(new_rect)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue