chore(ppu): emu now properly handles VRAM and OAM write guards

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-06-09 22:02:39 -05:00
parent 2b7958f5f3
commit 17024c439a
2 changed files with 22 additions and 28 deletions

View File

@ -1,6 +1,5 @@
use crate::cartridge::Cartridge; use crate::cartridge::Cartridge;
use crate::high_ram::HighRam; use crate::high_ram::HighRam;
use crate::instruction::Cycle;
use crate::interrupt::{Interrupt, InterruptFlag}; use crate::interrupt::{Interrupt, InterruptFlag};
use crate::joypad::Joypad; use crate::joypad::Joypad;
use crate::ppu::{Ppu, PpuMode}; use crate::ppu::{Ppu, PpuMode};
@ -159,7 +158,7 @@ impl BusIo for Bus {
0x8000..=0x9FFF => { 0x8000..=0x9FFF => {
// 8KB Video RAM // 8KB Video RAM
match self.ppu.stat.mode() { match self.ppu.stat.mode() {
PpuMode::VBlank => 0xFF, PpuMode::Drawing => 0xFF,
_ => self.ppu.read_byte(addr), _ => self.ppu.read_byte(addr),
} }
} }
@ -266,14 +265,10 @@ impl BusIo for Bus {
} }
0x8000..=0x9FFF => { 0x8000..=0x9FFF => {
// 8KB Video RAM // 8KB Video RAM
match self.ppu.stat.mode() {
// TODO: Fix timing issues in the PPU PpuMode::Drawing => {}
// match self.ppu.stat.mode() { _ => self.ppu.write_byte(addr, byte),
// PpuMode::VBlank => {} }
// _ => self.ppu.write_byte(addr, byte),
// }
self.ppu.write_byte(addr, byte)
} }
0xA000..=0xBFFF => { 0xA000..=0xBFFF => {
// 8KB External RAM // 8KB External RAM
@ -365,7 +360,7 @@ impl BusIo for Bus {
self.boot = None; self.boot = None;
} }
} }
_ => {} // unimplemented!("Unable to write to {:#06X} in I/O Registers", addr), _ => unimplemented!("Unable to write to {:#06X} in I/O Registers", addr),
}; };
} }
0xFF80..=0xFFFE => { 0xFF80..=0xFFFE => {

View File

@ -67,6 +67,10 @@ impl BusIo for Ppu {
impl Ppu { impl Ppu {
pub(crate) fn clock(&mut self) { pub(crate) fn clock(&mut self) {
if !self.ctrl.lcd_enabled() {
return;
}
self.cycle += 1; self.cycle += 1;
match self.stat.mode() { match self.stat.mode() {
@ -78,7 +82,14 @@ impl Ppu {
self.scan_oam(); self.scan_oam();
} }
PpuMode::Drawing => { PpuMode::Drawing => {
if self.x_pos >= 160 { if self.ctrl.lcd_enabled() {
// Only Draw when the LCD Is Enabled
self.draw(self.cycle.into());
} else {
self.reset();
}
if self.x_pos == 160 {
if self.stat.hblank_int() { if self.stat.hblank_int() {
// Enable HBlank LCDStat Interrupt // Enable HBlank LCDStat Interrupt
self.int.set_lcd_stat(true); self.int.set_lcd_stat(true);
@ -103,11 +114,6 @@ impl Ppu {
self.fifo.obj.clear(); self.fifo.obj.clear();
self.stat.set_mode(PpuMode::HBlank); self.stat.set_mode(PpuMode::HBlank);
} else if self.ctrl.lcd_enabled() {
// Only Draw when the LCD Is Enabled
self.draw(self.cycle.into());
} else {
self.reset();
} }
} }
PpuMode::HBlank => { PpuMode::HBlank => {
@ -413,19 +419,12 @@ impl Ppu {
} }
fn reset(&mut self) { fn reset(&mut self) {
// FIXME: Discover what actually is supposed to be reset here
self.scan_state = Default::default();
self.cycle = Cycle::new(0);
self.x_pos = 0;
self.window_stat = Default::default();
self.stat.set_mode(PpuMode::OamScan);
self.pos.line_y = 0; self.pos.line_y = 0;
self.stat.set_mode(PpuMode::HBlank);
self.fetch.back.reset(); // TODO: Is this an unnecessary performance hit?
self.fetch.obj.reset(); let mut blank = WHITE.repeat(self.frame_buf.len() / 4);
self.obj_buffer.clear(); self.frame_buf.swap_with_slice(&mut blank);
} }
pub fn copy_to_gui(&self, frame: &mut [u8]) { pub fn copy_to_gui(&self, frame: &mut [u8]) {