feat: enable halt and rework timer registers

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-03-27 11:56:47 -05:00
parent 2bf877d1ec
commit bce14348f8
4 changed files with 53 additions and 64 deletions

View File

@ -8,8 +8,7 @@ use super::serial::Serial;
use super::sound::Sound; use super::sound::Sound;
use super::timer::Timer; use super::timer::Timer;
use super::work_ram::{VariableWorkRam, WorkRam}; use super::work_ram::{VariableWorkRam, WorkRam};
use anyhow::anyhow; use std::{fs::File, io::Read};
use std::{convert::TryInto, fs::File, io::Read};
const BOOT_ROM_SIZE: usize = 256; const BOOT_ROM_SIZE: usize = 256;
@ -124,7 +123,7 @@ impl Bus {
0xFF00 => self.joypad.status.into(), 0xFF00 => self.joypad.status.into(),
0xFF01 => self.serial.next, 0xFF01 => self.serial.next,
0xFF02 => self.serial.control.into(), 0xFF02 => self.serial.control.into(),
0xFF04 => self.timer.divider, 0xFF04 => (self.timer.divider >> 8) as u8,
0xFF05 => self.timer.counter, 0xFF05 => self.timer.counter,
0xFF06 => self.timer.modulo, 0xFF06 => self.timer.modulo,
0xFF07 => self.timer.control.into(), 0xFF07 => self.timer.control.into(),

View File

@ -86,21 +86,20 @@ impl Cpu {
} }
pub fn step(&mut self) -> Cycles { 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 { if self.reg.pc > 0x100 {
self.log_state().unwrap(); self.log_state().unwrap();
} }
let cycles = match self.halted() {
Some(state) => {
use HaltState::*;
match state {
ImeSet | NonePending => Cycles::new(4),
SomePending => todo!("Implement HALT bug"),
}
}
None => {
let opcode = self.fetch(); let opcode = self.fetch();
self.inc_pc(); self.inc_pc();
@ -108,6 +107,10 @@ impl Cpu {
let cycles = self.execute(instr); let cycles = self.execute(instr);
self.bus.step(cycles); self.bus.step(cycles);
cycles
}
};
self.handle_interrupts(); self.handle_interrupts();
cycles cycles
@ -167,40 +170,35 @@ impl Cpu {
if self.ime() { if self.ime() {
let mut req: InterruptFlag = req.into(); let mut req: InterruptFlag = req.into();
let mut enabled: InterruptEnable = enabled.into(); let enabled: InterruptEnable = enabled.into();
let vector = if req.vblank() && enabled.vblank() { let vector = if req.vblank() && enabled.vblank() {
// Handle VBlank Interrupt // Handle VBlank Interrupt
req.set_vblank(false); req.set_vblank(false);
enabled.set_vblank(false);
// INT 40h // INT 40h
Some(0x40) Some(0x40)
} else if req.lcd_stat() && enabled.lcd_stat() { } else if req.lcd_stat() && enabled.lcd_stat() {
// Handle LCD STAT Interrupt // Handle LCD STAT Interrupt
req.set_lcd_stat(false); req.set_lcd_stat(false);
enabled.set_lcd_stat(false);
// INT 48h // INT 48h
Some(0x48) Some(0x48)
} else if req.timer() && enabled.timer() { } else if req.timer() && enabled.timer() {
// Handle Timer Interrupt // Handle Timer Interrupt
req.set_timer(false); req.set_timer(false);
enabled.set_timer(false);
// INT 50h // INT 50h
Some(0x50) Some(0x50)
} else if req.serial() && enabled.serial() { } else if req.serial() && enabled.serial() {
// Handle Serial Interrupt // Handle Serial Interrupt
req.set_serial(false); req.set_serial(false);
enabled.set_serial(false);
// INT 58h // INT 58h
Some(0x58) Some(0x58)
} else if req.joypad() && enabled.joypad() { } else if req.joypad() && enabled.joypad() {
// Handle Joypad Interrupt // Handle Joypad Interrupt
req.set_joypad(false); req.set_joypad(false);
enabled.set_joypad(false);
// INT 60h // INT 60h
Some(0x60) Some(0x60)
@ -212,7 +210,6 @@ impl Cpu {
Some(register) => { Some(register) => {
// Write the Changes to 0xFF0F and 0xFFFF registers // Write the Changes to 0xFF0F and 0xFFFF registers
self.write_byte(0xFF0F, req.into()); self.write_byte(0xFF0F, req.into());
self.write_byte(0xFFFF, enabled.into());
// Disable all future interrupts // Disable all future interrupts
self.set_ime(false); self.set_ime(false);

View File

@ -594,7 +594,6 @@ impl Instruction {
} }
}; };
println!("Game Boy HALTed in {:?}", halt_state);
cpu.halt(halt_state); cpu.halt(halt_state);
// Though this can actually last forever // Though this can actually last forever

View File

@ -1,62 +1,57 @@
use crate::Cycles; use crate::Cycles;
use crate::LR35902_CLOCK_SPEED;
use bitfield::bitfield; use bitfield::bitfield;
const DIVIDER_REGISTER_HZ: u32 = 16384; // const DIVIDER_REGISTER_HZ: u32 = 16384;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Timer { pub struct Timer {
pub control: TimerControl, pub control: TimerControl,
pub counter: u8, pub counter: u8,
pub modulo: u8, pub modulo: u8,
pub divider: u8, pub divider: u16,
divider_cycles: Cycles, prev_and_result: Option<u8>,
timer_cycles: Cycles,
interrupt: bool, interrupt: bool,
} }
impl Timer { impl Timer {
pub fn step(&mut self, cycles: Cycles) { pub fn step(&mut self, cycles: Cycles) {
self.timer_cycles += cycles; use TimerSpeed::*;
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;
for _ in 0..cycles.into() {
self.divider = self.divider.wrapping_add(1); self.divider = self.divider.wrapping_add(1);
// Get Bit Position
let pos = match self.control.speed() {
Hz4096 => 9,
Hz262144 => 3,
Hz65536 => 5,
Hz16384 => 7,
};
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);
}
} }
if self.control.enabled() { fn increment_tima(&mut self) {
if self.timer_cycles >= timer_wait {
// The Timer has ticked
self.timer_cycles %= timer_wait;
let (result, did_overflow) = self.counter.overflowing_add(1); let (result, did_overflow) = self.counter.overflowing_add(1);
self.counter = if did_overflow { self.counter = if did_overflow {
self.interrupt = true; self.interrupt = true;
self.modulo self.modulo
} else { } else {
result 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,
};
Cycles::new(difference)
}
pub fn interrupt(&self) -> bool { pub fn interrupt(&self) -> bool {
self.interrupt self.interrupt
@ -71,12 +66,11 @@ impl Default for Timer {
fn default() -> Self { fn default() -> Self {
Self { Self {
control: Default::default(), control: Default::default(),
timer_cycles: Default::default(),
divider_cycles: Default::default(),
counter: 0, counter: 0,
modulo: 0, modulo: 0,
divider: 0, divider: 0,
interrupt: false, interrupt: false,
prev_and_result: None,
} }
} }
} }