chore(ppu): emu now properly handles VRAM and OAM write guards
This commit is contained in:
parent
2b7958f5f3
commit
17024c439a
17
src/bus.rs
17
src/bus.rs
|
@ -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 => {
|
||||||
|
|
33
src/ppu.rs
33
src/ppu.rs
|
@ -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]) {
|
||||||
|
|
Loading…
Reference in New Issue