chore: change how bus components are clocked

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-06-09 19:41:10 -05:00
parent aa4a898a6b
commit 50efe12aec
5 changed files with 125 additions and 134 deletions

View File

@ -67,21 +67,17 @@ impl Bus {
self.cartridge.as_ref()?.title() self.cartridge.as_ref()?.title()
} }
pub(crate) fn step(&mut self, cycles: Cycle) { pub(crate) fn clock(&mut self) {
self.step_dma(cycles); self.ppu.clock();
self.ppu.step(cycles); self.timer.clock();
self.timer.step(cycles); self.sound.clock();
self.sound.step(cycles); self.clock_dma();
} }
pub(crate) fn step_dma(&mut self, pending: Cycle) { fn clock_dma(&mut self) {
let pending_cycles: u32 = pending.into(); if let Some((src_addr, dest_addr)) = self.ppu.dma.clock() {
let byte = self.oam_read_byte(src_addr);
for _ in 0..pending_cycles { self.oam_write_byte(dest_addr, byte);
if let Some((src_addr, dest_addr)) = self.ppu.dma.clock() {
let byte = self.oam_read_byte(src_addr);
self.oam_write_byte(dest_addr, byte);
}
} }
} }

View File

@ -136,8 +136,10 @@ impl Cpu {
} }
}; };
self.bus.step(cycles); let pending: u32 = cycles.into();
self.bus.step_dma(cycles); for _ in 0..pending {
self.bus.clock();
}
self.handle_interrupts(); self.handle_interrupts();

View File

@ -66,124 +66,119 @@ impl BusIo for Ppu {
} }
impl Ppu { impl Ppu {
pub(crate) fn step(&mut self, cycles: Cycle) { pub(crate) fn clock(&mut self) {
let start: u32 = self.cycle.into(); self.cycle += 1;
let end: u32 = cycles.into();
for _ in start..(start + end) { match self.stat.mode() {
self.cycle += 1; PpuMode::OamScan => {
if self.cycle >= 80.into() {
self.stat.set_mode(PpuMode::Drawing);
}
match self.stat.mode() { self.scan_oam();
PpuMode::OamScan => { }
if self.cycle >= 80.into() { PpuMode::Drawing => {
self.stat.set_mode(PpuMode::Drawing); if self.x_pos >= 160 {
if self.stat.hblank_int() {
// Enable HBlank LCDStat Interrupt
self.int.set_lcd_stat(true);
} }
self.scan_oam(); // Done with rendering this frame,
// we can reset the ppu x_pos and fetcher state now
// Increment Window line counter if scanline had any window pixels on it
// only increment once per scanline though
if self.window_stat.should_draw() {
self.fetch.back.window_line.increment();
}
self.x_pos = 0;
self.fetch.hblank_reset();
self.window_stat.hblank_reset();
self.obj_buffer.clear();
self.fifo.back.clear();
self.fifo.obj.clear();
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::Drawing => { }
if self.x_pos >= 160 { PpuMode::HBlank => {
if self.stat.hblank_int() { // This mode will always end at 456 cycles
// Enable HBlank LCDStat Interrupt
if self.cycle >= 456.into() {
self.cycle %= 456;
self.pos.line_y += 1;
// Update LY==LYC bit
let are_equal = self.pos.line_y == self.pos.ly_compare;
self.stat.set_coincidence(are_equal);
// Request LCD STAT interrupt if conditions met
if self.stat.coincidence_int() && are_equal {
self.int.set_lcd_stat(true);
}
let next_mode = if self.pos.line_y >= 144 {
// Request VBlank Interrupt
self.int.set_vblank(true);
// Reset Window Line Counter in Fetcher
self.fetch.vblank_reset();
// Reset WY=LY coincidence flag
self.window_stat.vblank_reset();
if self.stat.vblank_int() {
// Enable Vblank LCDStat Interrupt
self.int.set_lcd_stat(true); self.int.set_lcd_stat(true);
} }
// Done with rendering this frame, PpuMode::VBlank
// we can reset the ppu x_pos and fetcher state now
// Increment Window line counter if scanline had any window pixels on it
// only increment once per scanline though
if self.window_stat.should_draw() {
self.fetch.back.window_line.increment();
}
self.x_pos = 0;
self.fetch.hblank_reset();
self.window_stat.hblank_reset();
self.obj_buffer.clear();
self.fifo.back.clear();
self.fifo.obj.clear();
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 { } else {
self.reset(); if self.stat.oam_int() {
} // Enable OAM LCDStat Interrupt
}
PpuMode::HBlank => {
// This mode will always end at 456 cycles
if self.cycle >= 456.into() {
self.cycle %= 456;
self.pos.line_y += 1;
// Update LY==LYC bit
let are_equal = self.pos.line_y == self.pos.ly_compare;
self.stat.set_coincidence(are_equal);
// Request LCD STAT interrupt if conditions met
if self.stat.coincidence_int() && are_equal {
self.int.set_lcd_stat(true); self.int.set_lcd_stat(true);
} }
let next_mode = if self.pos.line_y >= 144 { self.scan_state.reset();
// Request VBlank Interrupt PpuMode::OamScan
self.int.set_vblank(true); };
// Reset Window Line Counter in Fetcher self.stat.set_mode(next_mode);
self.fetch.vblank_reset();
// Reset WY=LY coincidence flag
self.window_stat.vblank_reset();
if self.stat.vblank_int() {
// Enable Vblank LCDStat Interrupt
self.int.set_lcd_stat(true);
}
PpuMode::VBlank
} else {
if self.stat.oam_int() {
// Enable OAM LCDStat Interrupt
self.int.set_lcd_stat(true);
}
self.scan_state.reset();
PpuMode::OamScan
};
self.stat.set_mode(next_mode);
}
} }
PpuMode::VBlank => { }
if self.cycle > 456.into() { PpuMode::VBlank => {
self.cycle %= 456; if self.cycle > 456.into() {
self.pos.line_y += 1; self.cycle %= 456;
self.pos.line_y += 1;
// Update LY==LYC bit // Update LY==LYC bit
let are_equal = self.pos.line_y == self.pos.ly_compare; let are_equal = self.pos.line_y == self.pos.ly_compare;
self.stat.set_coincidence(are_equal); self.stat.set_coincidence(are_equal);
// Request LCD STAT interrupt if conditions met // Request LCD STAT interrupt if conditions met
if self.stat.coincidence_int() && are_equal { if self.stat.coincidence_int() && are_equal {
self.int.set_lcd_stat(true);
}
if self.pos.line_y == 154 {
self.pos.line_y = 0;
if self.stat.oam_int() {
// Enable OAM LCDStat Interrupt
self.int.set_lcd_stat(true); self.int.set_lcd_stat(true);
} }
if self.pos.line_y == 154 { self.scan_state.reset();
self.pos.line_y = 0;
if self.stat.oam_int() { self.stat.set_mode(PpuMode::OamScan);
// Enable OAM LCDStat Interrupt
self.int.set_lcd_stat(true);
}
self.scan_state.reset();
self.stat.set_mode(PpuMode::OamScan);
}
} }
} }
} }

View File

@ -7,7 +7,7 @@ pub(crate) struct Sound {
} }
impl Sound { impl Sound {
pub(crate) fn step(&mut self, _cycles: Cycle) { pub(crate) fn clock(&mut self) {
// //
} }
} }

View File

@ -16,33 +16,31 @@ pub(crate) struct Timer {
} }
impl Timer { impl Timer {
pub(crate) fn step(&mut self, cycles: Cycle) { pub(crate) fn clock(&mut self) {
use TimerSpeed::*; use TimerSpeed::*;
for _ in 0..cycles.into() { self.divider = self.divider.wrapping_add(1);
self.divider = self.divider.wrapping_add(1);
// Get Bit Position // Get Bit Position
let bit = match self.ctrl.speed() { let bit = match self.ctrl.speed() {
Hz4096 => 9, Hz4096 => 9,
Hz262144 => 3, Hz262144 => 3,
Hz65536 => 5, Hz65536 => 5,
Hz16384 => 7, Hz16384 => 7,
}; };
let bit = (self.divider >> bit) as u8 & 0x01; let bit = (self.divider >> bit) as u8 & 0x01;
let timer_enable = self.ctrl.enabled() as u8; let timer_enable = self.ctrl.enabled() as u8;
let and_result = bit & timer_enable; let and_result = bit & timer_enable;
if let Some(previous) = self.prev_and_result { if let Some(previous) = self.prev_and_result {
if previous == 0x01 && and_result == 0x00 { if previous == 0x01 && and_result == 0x00 {
// Falling Edge, increase TIMA Register // Falling Edge, increase TIMA Register
self.increment_tima(); self.increment_tima();
}
} }
self.prev_and_result = Some(and_result);
} }
self.prev_and_result = Some(and_result);
} }
fn increment_tima(&mut self) { fn increment_tima(&mut self) {