From 92855bf6b92b5d2c287a6a5c3694f71b63723904 Mon Sep 17 00:00:00 2001 From: Kevin Hamacher Date: Mon, 17 Feb 2020 19:23:16 +0100 Subject: [PATCH] Implement proper shutdown --- src/cpu.rs | 23 ++++++++++++++++++----- src/interconnect.rs | 11 +++++++++-- src/main.rs | 4 +--- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/cpu.rs b/src/cpu.rs index 0f75062..e652e5e 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -21,6 +21,12 @@ const FLAG_N: u8 = 1 << 6; const FLAG_H: u8 = 1 << 5; const FLAG_C: u8 = 1 << 4; +use interconnect::TickResult; +enum CpuTickResult { + Continue { cycles_executed: usize }, + Shutdown { cycles_executed: usize }, +} + pub struct CPU { // Registers: B, C, D, E, H, L, A regs: [u8; 7], @@ -904,9 +910,13 @@ impl CPU { // The gameboy has a freq of 4.194304MHz // This means it takes it 238.418569ns to execute a single // cycle. - let expected_cycles = start.elapsed().as_nanos() / 238; + let expected_cycles = start.elapsed().as_nanos() / (238 / 2); while cycles_executed < expected_cycles { - cycles_executed += self.run_instruction() as u128; + if let CpuTickResult::Continue { cycles_executed: x, .. } = self.run_instruction() { + cycles_executed += x as u128; + } else { + return; + } } sleep(Duration::new(0, 10 * 238)); } @@ -951,7 +961,7 @@ impl CPU { false } - pub fn run_instruction(&mut self) -> u8 { + pub fn run_instruction(&mut self) -> CpuTickResult { // self.debug = !self.interconnect.is_boot_rom(); if !self.trigger_once && !self.interconnect.is_boot_rom() { self.trigger_once = true; @@ -1745,7 +1755,10 @@ impl CPU { _ => panic!("Unknown instruction: {:02x}", instruction), }; } - self.interconnect.tick(cycles); - cycles + + if self.interconnect.tick(cycles) == TickResult::Shutdown { + return CpuTickResult::Shutdown { cycles_executed: cycles as usize } + } + CpuTickResult::Continue { cycles_executed: cycles as usize } } } diff --git a/src/interconnect.rs b/src/interconnect.rs index 6e21e7c..edc6ec3 100644 --- a/src/interconnect.rs +++ b/src/interconnect.rs @@ -32,6 +32,12 @@ extern crate sdl2; use self::sdl2::event::Event; use self::sdl2::keyboard::Keycode; +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum TickResult { + Continue, + Shutdown, +} + #[derive(Debug)] enum Key { UP, @@ -137,7 +143,7 @@ impl Interconnect { } // Somehow we need different timers for this. - pub fn tick(&mut self, cycles: u8) { + pub fn tick(&mut self, cycles: u8) -> TickResult { self.display.tick(cycles as u16); self.timer.tick(cycles as u16); @@ -168,7 +174,7 @@ impl Interconnect { .. } => { self.cartridge.save(); - panic!("TODO: Proper shutdown"); + return TickResult::Shutdown; } Event::KeyDown { keycode: Some(Keycode::Left), @@ -245,6 +251,7 @@ impl Interconnect { } else { self.cycles += cycles as u16; } + TickResult::Continue } #[inline] diff --git a/src/main.rs b/src/main.rs index 503d2e2..74d6fd2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -36,9 +36,7 @@ fn main() { let interconnect = interconnect::Interconnect::new(bios, rom, save_file); let mut cpu = cpu::CPU::new(interconnect); - loop { - cpu.run(); - } + cpu.run(); } }