fix: reimplement some ppu structs as bitfield macros
This commit is contained in:
parent
ef4cc8c3b6
commit
bfde24cc8d
193
src/ppu.rs
193
src/ppu.rs
|
@ -1,4 +1,5 @@
|
||||||
use crate::instruction::Cycles;
|
use crate::instruction::Cycles;
|
||||||
|
use bitfield::bitfield;
|
||||||
|
|
||||||
const GB_WIDTH: usize = 160;
|
const GB_WIDTH: usize = 160;
|
||||||
const GB_HEIGHT: usize = 144;
|
const GB_HEIGHT: usize = 144;
|
||||||
|
@ -90,37 +91,65 @@ enum Mode {
|
||||||
VBlank,
|
VBlank,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
bitfield! {
|
||||||
pub struct LCDStatus {
|
pub struct LCDStatus(u8);
|
||||||
lyc_eq_ly: bool,
|
impl Debug;
|
||||||
mode2_stat: bool,
|
pub lyc_ly_intr, set_lyc_ly_intr: 6;
|
||||||
mode1_stat: bool,
|
pub oam_intr, set_oam_intr: 5;
|
||||||
mode0_stat: bool,
|
pub vblank_intr, set_vblank_intr: 4;
|
||||||
coincidence: bool,
|
pub hblank_intr, set_hblank_intr: 3;
|
||||||
ppu_mode: u8,
|
pub lyc_ly_flag, _: 2;
|
||||||
|
pub from into LCDMode, mode, _: 1, 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Copy for LCDStatus {}
|
||||||
|
impl Clone for LCDStatus {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for LCDStatus {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u8> for LCDStatus {
|
impl From<u8> for LCDStatus {
|
||||||
fn from(byte: u8) -> Self {
|
fn from(byte: u8) -> Self {
|
||||||
Self {
|
Self(byte)
|
||||||
lyc_eq_ly: (byte >> 6) & 0x01 == 0x01,
|
|
||||||
mode2_stat: (byte >> 5) & 0x01 == 0x01,
|
|
||||||
mode1_stat: (byte >> 4) & 0x01 == 0x01,
|
|
||||||
mode0_stat: (byte >> 3) & 0x01 == 0x01,
|
|
||||||
coincidence: (byte >> 2) & 0x01 == 0x01,
|
|
||||||
ppu_mode: byte & 0x03,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LCDStatus> for u8 {
|
impl From<LCDStatus> for u8 {
|
||||||
fn from(status: LCDStatus) -> Self {
|
fn from(status: LCDStatus) -> Self {
|
||||||
0x80 | (status.lyc_eq_ly as u8) << 6
|
status.0
|
||||||
| (status.mode2_stat as u8) << 5
|
}
|
||||||
| (status.mode1_stat as u8) << 4
|
}
|
||||||
| (status.mode0_stat as u8) << 3
|
|
||||||
| (status.coincidence as u8) << 2
|
#[derive(Debug, Clone, Copy)]
|
||||||
| (status.ppu_mode & 0x03)
|
pub enum LCDMode {
|
||||||
|
HBlank = 0,
|
||||||
|
VBlank = 1,
|
||||||
|
OAM = 2,
|
||||||
|
Transfer = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for LCDMode {
|
||||||
|
fn from(byte: u8) -> Self {
|
||||||
|
match byte {
|
||||||
|
0b00 => Self::HBlank,
|
||||||
|
0b01 => Self::VBlank,
|
||||||
|
0b10 => Self::OAM,
|
||||||
|
0b11 => Self::Transfer,
|
||||||
|
_ => unreachable!("{:#04X} is not a valid value for LCDMode", byte),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for LCDMode {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::HBlank
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,43 +165,107 @@ pub struct Monochrome {
|
||||||
pub bg_palette: BackgroundPalette,
|
pub bg_palette: BackgroundPalette,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy)]
|
bitfield! {
|
||||||
pub struct LCDControl {
|
pub struct LCDControl(u8);
|
||||||
lcd_enable: bool, // Bit 7
|
impl Debug;
|
||||||
window_tile_map_select: bool,
|
lcd_enabled, set_lcd_enabled: 7;
|
||||||
window_enable: bool,
|
from into TileMapRegister, win_tile_map_area, set_win_tile_map_area: 6;
|
||||||
tile_data_select: bool,
|
window_enabled, set_window_enabled: 5;
|
||||||
bg_tile_map_select: bool,
|
from into TileDataRegister, tile_data_area, set_tile_data_area: 4;
|
||||||
sprite_size: bool,
|
from into TileMapRegister, gb_tile_map_area, set_gb_tile_map_area: 3;
|
||||||
sprite_enable: bool,
|
from into OBJSize, obg_size, set_obj_size: 2;
|
||||||
display_priority: bool, // Bit 0
|
obj_enabled, set_obj_enabled: 1;
|
||||||
|
bg_win_enabled, set_bg_win_enabled: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Copy for LCDControl {}
|
||||||
|
impl Clone for LCDControl {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for LCDControl {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u8> for LCDControl {
|
impl From<u8> for LCDControl {
|
||||||
fn from(byte: u8) -> Self {
|
fn from(byte: u8) -> Self {
|
||||||
Self {
|
Self(byte)
|
||||||
lcd_enable: (byte >> 7) == 0x01,
|
|
||||||
window_tile_map_select: ((byte >> 6) & 0x01) == 0x01,
|
|
||||||
window_enable: ((byte >> 5) & 0x01) == 0x01,
|
|
||||||
tile_data_select: ((byte >> 4) & 0x01) == 0x01,
|
|
||||||
bg_tile_map_select: ((byte >> 3) & 0x01) == 0x01,
|
|
||||||
sprite_size: ((byte >> 2) & 0x01) == 0x01,
|
|
||||||
sprite_enable: ((byte >> 1) & 0x01) == 0x01,
|
|
||||||
display_priority: (byte & 0x01) == 0x01,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LCDControl> for u8 {
|
impl From<LCDControl> for u8 {
|
||||||
fn from(ctrl: LCDControl) -> Self {
|
fn from(ctrl: LCDControl) -> Self {
|
||||||
(ctrl.lcd_enable as u8) << 7
|
ctrl.0
|
||||||
| (ctrl.window_tile_map_select as u8) << 6
|
}
|
||||||
| (ctrl.window_enable as u8) << 5
|
}
|
||||||
| (ctrl.tile_data_select as u8) << 4
|
|
||||||
| (ctrl.bg_tile_map_select as u8) << 3
|
#[derive(Debug, Clone, Copy)]
|
||||||
| (ctrl.sprite_size as u8) << 2
|
enum TileMapRegister {
|
||||||
| (ctrl.sprite_enable as u8) << 1
|
X9800 = 0,
|
||||||
| ctrl.display_priority as u8
|
X9C00 = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for TileMapRegister {
|
||||||
|
fn from(byte: u8) -> Self {
|
||||||
|
match byte {
|
||||||
|
0b00 => Self::X9800,
|
||||||
|
0b01 => Self::X9C00,
|
||||||
|
_ => unreachable!("{:#04X} is not a valid value for TileMapRegister", byte),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TileMapRegister {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::X9800
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum TileDataRegister {
|
||||||
|
X8800 = 0,
|
||||||
|
X8000 = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for TileDataRegister {
|
||||||
|
fn from(byte: u8) -> Self {
|
||||||
|
match byte {
|
||||||
|
0b00 => Self::X8800,
|
||||||
|
0b01 => Self::X8000,
|
||||||
|
_ => unreachable!("{:#04X} is not a valid value for TileDataRegister", byte),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TileDataRegister {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::X8800
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum ObjSize {
|
||||||
|
EightByEight = 0,
|
||||||
|
EightBySixteen = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for ObjSize {
|
||||||
|
fn from(byte: u8) -> Self {
|
||||||
|
match byte {
|
||||||
|
0b00 => Self::EightByEight,
|
||||||
|
0b01 => Self::EightBySixteen,
|
||||||
|
_ => unreachable!("{:#04X} is not a valid value for ObjSize", byte),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ObjSize {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::EightByEight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue