From bce14348f8c5fd058b60ec0ac1687e563c5e24a3 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Sat, 27 Mar 2021 11:56:47 -0500 Subject: [PATCH] feat: enable halt and rework timer registers --- src/bus.rs | 5 ++-- src/cpu.rs | 43 ++++++++++++++--------------- src/instruction.rs | 1 - src/timer.rs | 68 +++++++++++++++++++++------------------------- 4 files changed, 53 insertions(+), 64 deletions(-) diff --git a/src/bus.rs b/src/bus.rs index 06713ff..0a46910 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -8,8 +8,7 @@ use super::serial::Serial; use super::sound::Sound; use super::timer::Timer; use super::work_ram::{VariableWorkRam, WorkRam}; -use anyhow::anyhow; -use std::{convert::TryInto, fs::File, io::Read}; +use std::{fs::File, io::Read}; const BOOT_ROM_SIZE: usize = 256; @@ -124,7 +123,7 @@ impl Bus { 0xFF00 => self.joypad.status.into(), 0xFF01 => self.serial.next, 0xFF02 => self.serial.control.into(), - 0xFF04 => self.timer.divider, + 0xFF04 => (self.timer.divider >> 8) as u8, 0xFF05 => self.timer.counter, 0xFF06 => self.timer.modulo, 0xFF07 => self.timer.control.into(), diff --git a/src/cpu.rs b/src/cpu.rs index 77d307b..1386549 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -86,28 +86,31 @@ impl Cpu { } pub fn step(&mut self) -> Cycles { - // if let Some(state) = self.halted() { - // use HaltState::*; - - // match state { - // ImeSet | NonePending => Cycles::new(4), - // SomePending => { - // todo!("Implement HALT Bug"); - // } - // } - // }; - if self.reg.pc > 0x100 { self.log_state().unwrap(); } - let opcode = self.fetch(); - self.inc_pc(); + let cycles = match self.halted() { + Some(state) => { + use HaltState::*; - let instr = self.decode(opcode); - let cycles = self.execute(instr); + match state { + ImeSet | NonePending => Cycles::new(4), + SomePending => todo!("Implement HALT bug"), + } + } + None => { + let opcode = self.fetch(); + self.inc_pc(); + + let instr = self.decode(opcode); + let cycles = self.execute(instr); + + self.bus.step(cycles); + cycles + } + }; - self.bus.step(cycles); self.handle_interrupts(); cycles @@ -167,40 +170,35 @@ impl Cpu { if self.ime() { let mut req: InterruptFlag = req.into(); - let mut enabled: InterruptEnable = enabled.into(); + let enabled: InterruptEnable = enabled.into(); let vector = if req.vblank() && enabled.vblank() { // Handle VBlank Interrupt req.set_vblank(false); - enabled.set_vblank(false); // INT 40h Some(0x40) } else if req.lcd_stat() && enabled.lcd_stat() { // Handle LCD STAT Interrupt req.set_lcd_stat(false); - enabled.set_lcd_stat(false); // INT 48h Some(0x48) } else if req.timer() && enabled.timer() { // Handle Timer Interrupt req.set_timer(false); - enabled.set_timer(false); // INT 50h Some(0x50) } else if req.serial() && enabled.serial() { // Handle Serial Interrupt req.set_serial(false); - enabled.set_serial(false); // INT 58h Some(0x58) } else if req.joypad() && enabled.joypad() { // Handle Joypad Interrupt req.set_joypad(false); - enabled.set_joypad(false); // INT 60h Some(0x60) @@ -212,7 +210,6 @@ impl Cpu { Some(register) => { // Write the Changes to 0xFF0F and 0xFFFF registers self.write_byte(0xFF0F, req.into()); - self.write_byte(0xFFFF, enabled.into()); // Disable all future interrupts self.set_ime(false); diff --git a/src/instruction.rs b/src/instruction.rs index eee0cff..cf40a49 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -594,7 +594,6 @@ impl Instruction { } }; - println!("Game Boy HALTed in {:?}", halt_state); cpu.halt(halt_state); // Though this can actually last forever diff --git a/src/timer.rs b/src/timer.rs index d68848e..01a2892 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -1,61 +1,56 @@ use crate::Cycles; -use crate::LR35902_CLOCK_SPEED; use bitfield::bitfield; -const DIVIDER_REGISTER_HZ: u32 = 16384; +// const DIVIDER_REGISTER_HZ: u32 = 16384; #[derive(Debug, Clone, Copy)] pub struct Timer { pub control: TimerControl, pub counter: u8, pub modulo: u8, - pub divider: u8, - divider_cycles: Cycles, - timer_cycles: Cycles, + pub divider: u16, + prev_and_result: Option, interrupt: bool, } impl Timer { pub fn step(&mut self, cycles: Cycles) { - self.timer_cycles += cycles; - self.divider_cycles += cycles; - - // Divider Register - let divider_wait = Cycles::new(LR35902_CLOCK_SPEED / DIVIDER_REGISTER_HZ); - let timer_wait = self.timer_cycles(); - - if self.divider_cycles >= divider_wait { - // The Divider Timer has ticked - self.divider_cycles %= divider_wait; + use TimerSpeed::*; + for _ in 0..cycles.into() { self.divider = self.divider.wrapping_add(1); - } - if self.control.enabled() { - if self.timer_cycles >= timer_wait { - // The Timer has ticked - self.timer_cycles %= timer_wait; + // Get Bit Position + let pos = match self.control.speed() { + Hz4096 => 9, + Hz262144 => 3, + Hz65536 => 5, + Hz16384 => 7, + }; - let (result, did_overflow) = self.counter.overflowing_add(1); - self.counter = if did_overflow { - self.interrupt = true; - self.modulo - } else { - result - }; + let bit = (self.divider >> pos) as u8 & 0x01; + let timer_enable = self.control.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 Regiser + self.increment_tima(); + } } + self.prev_and_result = Some(and_result); } } - fn timer_cycles(&self) -> Cycles { - let difference = match self.control.speed() { - TimerSpeed::Hz4096 => LR35902_CLOCK_SPEED / 4096, - TimerSpeed::Hz262144 => LR35902_CLOCK_SPEED / 262144, - TimerSpeed::Hz65536 => LR35902_CLOCK_SPEED / 65536, - TimerSpeed::Hz16384 => LR35902_CLOCK_SPEED / 16384, - }; + fn increment_tima(&mut self) { + let (result, did_overflow) = self.counter.overflowing_add(1); - Cycles::new(difference) + self.counter = if did_overflow { + self.interrupt = true; + self.modulo + } else { + result + } } pub fn interrupt(&self) -> bool { @@ -71,12 +66,11 @@ impl Default for Timer { fn default() -> Self { Self { control: Default::default(), - timer_cycles: Default::default(), - divider_cycles: Default::default(), counter: 0, modulo: 0, divider: 0, interrupt: false, + prev_and_result: None, } } }