fix: have the PPU use the CPU-writable Display Mode enum
This commit is contained in:
parent
8c25e6f976
commit
8af434da07
83
src/ppu.rs
83
src/ppu.rs
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue