Skip to main content

rubidium/vram/
mode3.rs

1#![cfg(feature = "unsafe_addresses")]
2
3use super::*;
4
5/// A ZST for namespacing VideoMode3 stuff into one place.
6///
7/// In Mode 3 the majority of VRAM is occupied with a single bitmap as large as
8/// the GBA's physical display. Each color contains a [`Color`] to display at
9/// that location in the bitmap.
10///
11/// You can access the address of a location by `row` and then `col` or by `x`
12/// and then `y`. It will give equivalent results.
13///
14/// ```rust
15/// # use rubidium::*;
16/// let p = Mode3.row(8).col(5);
17/// let q = Mode3.x(5).y(8);
18/// assert_eq!(p, q);
19/// ```
20///
21/// See Also: [`VideoMode`]
22#[derive(Debug, Clone, Copy)]
23pub struct Mode3;
24
25impl Mode3 {
26  /// In Mode3 the screen is 240 wide.
27  pub const WIDTH: usize = 240;
28
29  /// In Mode3 the screen is 160 tall.
30  pub const HEIGHT: usize = 160;
31
32  /// Index by `row` to get a particular row within the Mode 3 bitmap.
33  /// ## Panics
34  /// If the index is out of bounds.
35  #[must_use]
36  #[inline(always)]
37  pub fn row(self, row: usize) -> Mode3Row {
38    assert!(row < Mode3::HEIGHT);
39    let addr = VRAM + (row * Mode3::WIDTH * size_of::<Color>());
40    Mode3Row { addr }
41  }
42
43  /// Index by `x` to get a particular column within the Mode 3 bitmap.
44  /// ## Panics
45  /// If the index is out of bounds.
46  #[must_use]
47  #[inline(always)]
48  pub fn x(self, x: usize) -> Mode3Col {
49    assert!(x < Mode3::WIDTH);
50    let addr = VRAM + (x * size_of::<Color>());
51    Mode3Col { addr }
52  }
53}
54
55/// A particular row within the Mode 3 bitmap.
56#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
57#[repr(transparent)]
58pub struct Mode3Row {
59  addr: usize,
60}
61
62impl Mode3Row {
63  /// Index by `col` to get a location within this row.
64  /// ## Panics
65  /// If the index is out of bounds.
66  #[must_use]
67  #[inline(always)]
68  pub fn col(self, col: usize) -> SimpleVolAddr<Color> {
69    assert!(col < Mode3::WIDTH);
70    unsafe { SimpleVolAddr::new(self.addr + col * size_of::<Color>()) }
71  }
72}
73
74/// A particular column within the Mode 3 bitmap.
75#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
76#[repr(transparent)]
77pub struct Mode3Col {
78  addr: usize,
79}
80
81impl Mode3Col {
82  /// Index by `y` to get a location within this column.
83  /// ## Panics
84  /// If the index is out of bounds.
85  #[must_use]
86  #[inline(always)]
87  pub fn y(self, y: usize) -> SimpleVolAddr<Color> {
88    assert!(y < Mode3::HEIGHT);
89    unsafe {
90      SimpleVolAddr::new(self.addr + (y * Mode3::WIDTH * size_of::<Color>()))
91    }
92  }
93}
94
95// TODO: 0x0601_4000 is the start of OBJ tile memory
96// TODO: 256 tiles at 8bpp (32 bytes / tile)
97// TODO: 512 tiles at 4bpp (64 bytes / tile)