fix: have the PPU use the CPU-writable Display Mode enum

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-03-16 02:35:01 -05:00
parent 8c25e6f976
commit 8af434da07
1 changed files with 46 additions and 37 deletions

View File

@ -13,7 +13,6 @@ pub struct Ppu {
frame_buf: [u8; GB_WIDTH * GB_HEIGHT * 4], frame_buf: [u8; GB_WIDTH * GB_HEIGHT * 4],
pub stat: LCDStatus, pub stat: LCDStatus,
cycles: Cycles, cycles: Cycles,
mode: Mode,
} }
impl Ppu { impl Ppu {
@ -23,38 +22,46 @@ impl Ppu {
// let tmp: u32 = self.cycles.into(); // let tmp: u32 = self.cycles.into();
// println!("Mode: {:?} | Cycles: {}", self.mode, tmp); // println!("Mode: {:?} | Cycles: {}", self.mode, tmp);
match self.mode { match self.stat.mode() {
Mode::OAMScan => { Mode::OamScan => {
if self.cycles >= 80.into() { if self.cycles >= 80.into() {
self.cycles %= 80; self.stat.set_mode(Mode::Drawing);
self.mode = Mode::Draw;
} }
} }
Mode::Draw => { Mode::Drawing => {
// This mode can take from 172 -> 289 Cycles
// Remember: There's no guarantee that we start this mode
// with self.cycles == 80, since we aren't going for an accurate
// emulator
// TODO: This 172 needs to be variable somehow?
if self.cycles >= 172.into() { if self.cycles >= 172.into() {
// 172 -> 129 Cycles self.stat.set_mode(Mode::HBlank);
// self.cycles %= 172;
self.mode = Mode::HBlank;
} }
} }
Mode::HBlank => { Mode::HBlank => {
// The 80 comes from the 80 cycles we made disappear in OAMScan above. // We've reached the end of a scanline
if self.cycles >= (456 - 80).into() { if self.cycles >= 456.into() {
self.cycles %= 456 - 80;
self.pos.line_y += 1; self.pos.line_y += 1;
if self.pos.line_y >= 144 { let next_mode = if self.pos.line_y >= 143 {
self.mode = Mode::VBlank; Mode::VBlank
} } else {
Mode::OamScan
};
self.stat.set_mode(next_mode);
} }
} }
Mode::VBlank => { Mode::VBlank => {
// We've reached the end of the screen
if self.cycles >= 456.into() { if self.cycles >= 456.into() {
self.cycles %= 456; self.cycles %= 456;
self.pos.line_y += 1; self.pos.line_y += 1;
if self.pos.line_y == 154 { if self.pos.line_y >= 153 {
self.mode = Mode::OAMScan; self.stat.set_mode(Mode::OamScan);
self.pos.line_y = 0; self.pos.line_y = 0;
} }
} }
@ -78,19 +85,9 @@ impl Default for Ppu {
oam: vec![0; 160].into_boxed_slice(), oam: vec![0; 160].into_boxed_slice(),
cycles: 0.into(), cycles: 0.into(),
frame_buf: [0; GB_WIDTH * GB_HEIGHT * 4], frame_buf: [0; GB_WIDTH * GB_HEIGHT * 4],
mode: Mode::OAMScan,
} }
} }
} }
#[derive(Debug, Clone, Copy)]
enum Mode {
OAMScan,
Draw,
HBlank,
VBlank,
}
bitfield! { bitfield! {
pub struct LCDStatus(u8); pub struct LCDStatus(u8);
impl Debug; impl Debug;
@ -98,8 +95,14 @@ bitfield! {
pub oam_intr, set_oam_intr: 5; pub oam_intr, set_oam_intr: 5;
pub vblank_intr, set_vblank_intr: 4; pub vblank_intr, set_vblank_intr: 4;
pub hblank_intr, set_hblank_intr: 3; pub hblank_intr, set_hblank_intr: 3;
pub lyc_ly_flag, _: 2; pub coincidence, _: 2; // LYC == LY Flag
pub from into LCDMode, mode, _: 1, 0; from into Mode, _mode, set_mode: 1, 0;
}
impl LCDStatus {
pub fn mode(&self) -> Mode {
self._mode()
}
} }
impl Copy for LCDStatus {} impl Copy for LCDStatus {}
@ -128,26 +131,32 @@ impl From<LCDStatus> for u8 {
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum LCDMode { pub enum Mode {
HBlank = 0, HBlank = 0,
VBlank = 1, VBlank = 1,
Oam = 2, OamScan = 2,
Transfer = 3, Drawing = 3,
} }
impl From<u8> for LCDMode { impl From<u8> for Mode {
fn from(byte: u8) -> Self { fn from(byte: u8) -> Self {
match byte { match byte {
0b00 => Self::HBlank, 0b00 => Self::HBlank,
0b01 => Self::VBlank, 0b01 => Self::VBlank,
0b10 => Self::Oam, 0b10 => Self::OamScan,
0b11 => Self::Transfer, 0b11 => Self::Drawing,
_ => unreachable!("{:#04X} is not a valid value for LCDMode", byte), _ => unreachable!("{:#04X} is not a valid value for LCDMode", byte),
} }
} }
} }
impl Default for LCDMode { impl From<Mode> for u8 {
fn from(mode: Mode) -> Self {
mode as u8
}
}
impl Default for Mode {
fn default() -> Self { fn default() -> Self {
Self::HBlank Self::HBlank
} }
@ -270,7 +279,7 @@ impl Default for ObjSize {
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
enum GrayShade { pub enum GrayShade {
White = 0, White = 0,
LightGray = 1, LightGray = 1,
DarkGray = 2, DarkGray = 2,