more accurate timing

This commit is contained in:
Alex Janka 2023-02-14 08:23:24 +11:00
parent 645b5e365a
commit f42f58a663
2 changed files with 15 additions and 2 deletions

View file

@ -1,3 +1,5 @@
use std::time::Instant;
use self::{gpu::Gpu, memory::Memory, timer::Timers}; use self::{gpu::Gpu, memory::Memory, timer::Timers};
use crate::{ use crate::{
util::{clear_bit, get_bit}, util::{clear_bit, get_bit},
@ -35,6 +37,7 @@ pub struct Cpu {
halted: bool, halted: bool,
timers: Timers, timers: Timers,
gamepad_handler: Gilrs, gamepad_handler: Gilrs,
cycle_start: Instant,
} }
// Hz // Hz
@ -62,15 +65,18 @@ impl Cpu {
halted: false, halted: false,
timers: Timers::init(), timers: Timers::init(),
gamepad_handler, gamepad_handler,
cycle_start: Instant::now(),
} }
} }
pub fn exec_next(&mut self) { pub fn exec_next(&mut self) {
self.cycle_start = Instant::now();
let interrupt_cycles = self.handle_interrupts(); let interrupt_cycles = self.handle_interrupts();
self.increment_timers(interrupt_cycles); self.increment_timers(interrupt_cycles);
if self.halted { if self.halted {
self.increment_timers(1); self.increment_timers(1);
self.sleep(interrupt_cycles + 1);
return; return;
} }
@ -94,6 +100,7 @@ impl Cpu {
let cycles = self.run_opcode(opcode); let cycles = self.run_opcode(opcode);
self.memory.user_mode = false; self.memory.user_mode = false;
self.increment_timers(cycles); self.increment_timers(cycles);
self.sleep(interrupt_cycles + cycles);
} }
fn next_opcode(&mut self) -> u8 { fn next_opcode(&mut self) -> u8 {

View file

@ -44,9 +44,15 @@ impl Cpu {
self.memory.set(0xFF05, val); self.memory.set(0xFF05, val);
} }
} }
}
let secs = clock_cycles as f64 / CLOCK_SPEED as f64; pub(super) fn sleep(&mut self, machine_cycles: u8) {
spin_sleep::sleep(Duration::from_secs_f64(secs / SPEEDUP)); let secs = ((machine_cycles as f64) * 4.) / CLOCK_SPEED as f64;
if let Some(remaining) =
Duration::from_secs_f64(secs / SPEEDUP).checked_sub(self.cycle_start.elapsed())
{
spin_sleep::sleep(remaining);
}
} }
fn timer_scale(&self) -> (bool, usize) { fn timer_scale(&self) -> (bool, usize) {