From 50efe12aec40a5454dd79d11807e11ceee942ee9 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Wed, 9 Jun 2021 19:41:10 -0500 Subject: [PATCH] chore: change how bus components are clocked --- src/bus.rs | 22 +++--- src/cpu.rs | 6 +- src/ppu.rs | 191 +++++++++++++++++++++++++-------------------------- src/sound.rs | 2 +- src/timer.rs | 38 +++++----- 5 files changed, 125 insertions(+), 134 deletions(-) diff --git a/src/bus.rs b/src/bus.rs index 99c5409..70789b0 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -67,21 +67,17 @@ impl Bus { self.cartridge.as_ref()?.title() } - pub(crate) fn step(&mut self, cycles: Cycle) { - self.step_dma(cycles); - self.ppu.step(cycles); - self.timer.step(cycles); - self.sound.step(cycles); + pub(crate) fn clock(&mut self) { + self.ppu.clock(); + self.timer.clock(); + self.sound.clock(); + self.clock_dma(); } - pub(crate) fn step_dma(&mut self, pending: Cycle) { - let pending_cycles: u32 = pending.into(); - - for _ in 0..pending_cycles { - 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); - } + fn clock_dma(&mut self) { + 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); } } diff --git a/src/cpu.rs b/src/cpu.rs index b3bb54b..87f3489 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -136,8 +136,10 @@ impl Cpu { } }; - self.bus.step(cycles); - self.bus.step_dma(cycles); + let pending: u32 = cycles.into(); + for _ in 0..pending { + self.bus.clock(); + } self.handle_interrupts(); diff --git a/src/ppu.rs b/src/ppu.rs index 534ec25..cc66c71 100644 --- a/src/ppu.rs +++ b/src/ppu.rs @@ -66,124 +66,119 @@ impl BusIo for Ppu { } impl Ppu { - pub(crate) fn step(&mut self, cycles: Cycle) { - let start: u32 = self.cycle.into(); - let end: u32 = cycles.into(); + pub(crate) fn clock(&mut self) { + self.cycle += 1; - for _ in start..(start + end) { - self.cycle += 1; + match self.stat.mode() { + PpuMode::OamScan => { + if self.cycle >= 80.into() { + self.stat.set_mode(PpuMode::Drawing); + } - match self.stat.mode() { - PpuMode::OamScan => { - if self.cycle >= 80.into() { - self.stat.set_mode(PpuMode::Drawing); + self.scan_oam(); + } + 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 { - if self.stat.hblank_int() { - // Enable HBlank 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); + } + + 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); } - // 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()); + PpuMode::VBlank } else { - self.reset(); - } - } - 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 { + if self.stat.oam_int() { + // Enable OAM LCDStat Interrupt self.int.set_lcd_stat(true); } - let next_mode = if self.pos.line_y >= 144 { - // Request VBlank Interrupt - self.int.set_vblank(true); + self.scan_state.reset(); + PpuMode::OamScan + }; - // 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); - } - - 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); - } + self.stat.set_mode(next_mode); } - PpuMode::VBlank => { - if self.cycle > 456.into() { - self.cycle %= 456; - self.pos.line_y += 1; + } + PpuMode::VBlank => { + 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); + // 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 { + // Request LCD STAT interrupt if conditions met + 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); } - if self.pos.line_y == 154 { - self.pos.line_y = 0; + self.scan_state.reset(); - if self.stat.oam_int() { - // Enable OAM LCDStat Interrupt - self.int.set_lcd_stat(true); - } - - self.scan_state.reset(); - - self.stat.set_mode(PpuMode::OamScan); - } + self.stat.set_mode(PpuMode::OamScan); } } } diff --git a/src/sound.rs b/src/sound.rs index 6924ea2..74771f0 100644 --- a/src/sound.rs +++ b/src/sound.rs @@ -7,7 +7,7 @@ pub(crate) struct Sound { } impl Sound { - pub(crate) fn step(&mut self, _cycles: Cycle) { + pub(crate) fn clock(&mut self) { // } } diff --git a/src/timer.rs b/src/timer.rs index ae8a942..5617972 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -16,33 +16,31 @@ pub(crate) struct Timer { } impl Timer { - pub(crate) fn step(&mut self, cycles: Cycle) { + pub(crate) fn clock(&mut self) { use TimerSpeed::*; - for _ in 0..cycles.into() { - self.divider = self.divider.wrapping_add(1); + self.divider = self.divider.wrapping_add(1); - // Get Bit Position - let bit = match self.ctrl.speed() { - Hz4096 => 9, - Hz262144 => 3, - Hz65536 => 5, - Hz16384 => 7, - }; + // Get Bit Position + let bit = match self.ctrl.speed() { + Hz4096 => 9, + Hz262144 => 3, + Hz65536 => 5, + Hz16384 => 7, + }; - let bit = (self.divider >> bit) as u8 & 0x01; - let timer_enable = self.ctrl.enabled() as u8; - let and_result = bit & timer_enable; + let bit = (self.divider >> bit) as u8 & 0x01; + let timer_enable = self.ctrl.enabled() as u8; + let and_result = bit & timer_enable; - if let Some(previous) = self.prev_and_result { - if previous == 0x01 && and_result == 0x00 { - // Falling Edge, increase TIMA Register - self.increment_tima(); - } + if let Some(previous) = self.prev_and_result { + if previous == 0x01 && and_result == 0x00 { + // Falling Edge, increase TIMA Register + self.increment_tima(); } - - self.prev_and_result = Some(and_result); } + + self.prev_and_result = Some(and_result); } fn increment_tima(&mut self) {