Refactor timer

This commit is contained in:
Franco Colmenarez 2021-11-15 09:27:03 -05:00
parent c1dc14680e
commit 5acb3ba6d5
3 changed files with 20 additions and 22 deletions

View File

@ -13,7 +13,7 @@ use crate::ppu::{
DMA_ADDRESS, DMA_ADDRESS,
}; };
use crate::cpu::{Interrupt}; use crate::cpu::{Interrupt};
use crate::timer::{TIMER_DIVIDER_REGISTER_ADDRESS}; use crate::timer::{Timer, TIMER_DIVIDER_REGISTER_ADDRESS};
use crate::joypad::{Joypad, JOYPAD_ADDRESS}; use crate::joypad::{Joypad, JOYPAD_ADDRESS};
pub struct AddressRange { pub struct AddressRange {
@ -53,12 +53,12 @@ pub const INTERRUPT_FLAG_ADDRESS: u16 = 0xFF0F;
pub struct Bus { pub struct Bus {
game_rom: ROM, game_rom: ROM,
data: [u8; 0x10000], data: [u8; 0x10000],
pub reset_timer: bool,
joypad: Rc<RefCell<Joypad>>, joypad: Rc<RefCell<Joypad>>,
timer: Rc<RefCell<Timer>>,
} }
impl Bus { impl Bus {
pub fn new(joypad: Rc<RefCell<Joypad>>) -> Self { pub fn new(joypad: Rc<RefCell<Joypad>>, timer: Rc<RefCell<Timer>>) -> Self {
let args: Vec<String> = std::env::args().collect(); let args: Vec<String> = std::env::args().collect();
if args.len() < 2 { if args.len() < 2 {
println!("Please, specify a ROM file"); println!("Please, specify a ROM file");
@ -98,8 +98,8 @@ impl Bus {
Self { Self {
data, data,
game_rom, game_rom,
reset_timer: false,
joypad, joypad,
timer,
} }
} }
@ -110,6 +110,8 @@ impl Bus {
return 0b11100000 | self.data[address as usize]; return 0b11100000 | self.data[address as usize];
} else if address == JOYPAD_ADDRESS { } else if address == JOYPAD_ADDRESS {
return self.joypad.borrow().read(self.data[address as usize]); return self.joypad.borrow().read(self.data[address as usize]);
} else if address == TIMER_DIVIDER_REGISTER_ADDRESS {
return self.timer.borrow().read_divider();
} }
self.data[address as usize] self.data[address as usize]
} }
@ -137,7 +139,7 @@ impl Bus {
self.data[address as usize] = data; self.data[address as usize] = data;
self.data[(WORK_RAM_1.begin() + (address - ECHO_RAM.begin())) as usize] = data; // Copy to the working RAM self.data[(WORK_RAM_1.begin() + (address - ECHO_RAM.begin())) as usize] = data; // Copy to the working RAM
} else if address == TIMER_DIVIDER_REGISTER_ADDRESS { } else if address == TIMER_DIVIDER_REGISTER_ADDRESS {
self.reset_timer = true; self.timer.borrow_mut().reset();
} else if address == LCD_CONTROL_ADDRESS { } else if address == LCD_CONTROL_ADDRESS {
self.data[address as usize] = data; self.data[address as usize] = data;
// Check if LCD is being turned on or off // Check if LCD is being turned on or off

View File

@ -14,19 +14,20 @@ pub struct Emulator {
cpu: CPU, cpu: CPU,
ppu: PPU, ppu: PPU,
bus: Bus, bus: Bus,
timer: Timer, timer: Rc<RefCell<Timer>>,
joypad: Rc<RefCell<Joypad>>, joypad: Rc<RefCell<Joypad>>,
} }
impl Emulator { impl Emulator {
pub fn new() -> Self { pub fn new() -> Self {
let joypad = Rc::new(RefCell::new(Joypad::new())); let joypad = Rc::new(RefCell::new(Joypad::new()));
let timer = Rc::new(RefCell::new(Timer::new()));
Self { Self {
cpu: CPU::new(), cpu: CPU::new(),
ppu: PPU::new(), ppu: PPU::new(),
bus: Bus::new(Rc::clone(&joypad)), bus: Bus::new(Rc::clone(&joypad), Rc::clone(&timer)),
timer: Timer::new(), timer,
joypad: joypad, joypad,
} }
} }
@ -107,12 +108,8 @@ impl Emulator {
self.cpu.reset_cycles(); self.cpu.reset_cycles();
while self.cpu.get_cycles().to_t().0 <= cpu_cycles.0 { while self.cpu.get_cycles().to_t().0 <= cpu_cycles.0 {
self.cpu.run(&mut self.bus); self.cpu.run(&mut self.bus);
if self.bus.reset_timer {
self.bus.reset_timer = false;
self.timer.reset(&mut self.bus);
}
self.ppu.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles().to_t(), frame_buffer); self.ppu.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles().to_t(), frame_buffer);
self.timer.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles().to_t()); self.timer.borrow_mut().do_cycles(&mut self.bus, self.cpu.get_last_op_cycles().to_t());
// 1 CPU cycle = 238.42ns // 1 CPU cycle = 238.42ns
// thread::sleep(time::Duration::from_nanos((self.cpu.get_last_op_cycles().0 * 238).try_into().unwrap())); // thread::sleep(time::Duration::from_nanos((self.cpu.get_last_op_cycles().0 * 238).try_into().unwrap()));
@ -125,12 +122,8 @@ impl Emulator {
let mut frame: [u8; 144 * 160 * 4] = [0; 144 * 160 * 4]; let mut frame: [u8; 144 * 160 * 4] = [0; 144 * 160 * 4];
while !exit { while !exit {
self.cpu.run(&mut self.bus); self.cpu.run(&mut self.bus);
if self.bus.reset_timer {
self.bus.reset_timer = false;
self.timer.reset(&mut self.bus);
}
self.ppu.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles().to_t(), &mut frame); self.ppu.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles().to_t(), &mut frame);
self.timer.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles().to_t()); self.timer.borrow_mut().do_cycles(&mut self.bus, self.cpu.get_last_op_cycles().to_t());
// exit = self.cpu.get_exec_calls_count() >= 1258895; // log 1 // exit = self.cpu.get_exec_calls_count() >= 1258895; // log 1
exit = self.cpu.get_exec_calls_count() >= 161502; // log 2 exit = self.cpu.get_exec_calls_count() >= 161502; // log 2

View File

@ -28,9 +28,13 @@ impl Timer {
} }
} }
pub fn reset(&mut self, bus: &mut Bus) { pub fn read_divider(&self) -> u8 {
self.divider.to_be_bytes()[0]
}
pub fn reset(&mut self) {
println!("Reset divider");
self.divider = 0; self.divider = 0;
bus.force_write(TIMER_DIVIDER_REGISTER_ADDRESS, 0);
} }
pub fn do_cycles(&mut self, bus: &mut Bus, cycles: Cycles) { pub fn do_cycles(&mut self, bus: &mut Bus, cycles: Cycles) {
@ -41,7 +45,6 @@ impl Timer {
self.cycle(bus); self.cycle(bus);
count += 1; count += 1;
} }
bus.force_write(TIMER_DIVIDER_REGISTER_ADDRESS, self.divider.to_be_bytes()[0]);
} }
fn cycle(&mut self, bus: &mut Bus) { fn cycle(&mut self, bus: &mut Bus) {