diff --git a/Cargo.lock b/Cargo.lock index f28a4dc..61751ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -514,6 +514,7 @@ dependencies = [ name = "emu" version = "0.0.1" dependencies = [ + "instant", "r68k-emu", "r68k-tools", ] @@ -652,7 +653,6 @@ dependencies = [ "eframe", "egui", "emu", - "instant", "tracing-subscriber", "tracing-wasm", ] diff --git a/emu/Cargo.toml b/emu/Cargo.toml index e473719..e48c8f0 100644 --- a/emu/Cargo.toml +++ b/emu/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" [dependencies] r68k-emu = { git = "https://github.com/marhel/r68k.git" } r68k-tools = { git = "https://github.com/marhel/r68k.git" } +instant = "0.1" diff --git a/emu/src/lib.rs b/emu/src/lib.rs index f333adb..6774850 100644 --- a/emu/src/lib.rs +++ b/emu/src/lib.rs @@ -1,6 +1,3 @@ -use r68k_emu::cpu::{STACK_POINTER_REG, ConfiguredCore}; -use r68k_emu::interrupts::AutoInterruptController; - pub mod debug; pub mod gfx; pub mod io; @@ -9,6 +6,9 @@ pub mod rom; pub mod vdp; pub mod z80; +use r68k_emu::cpu::{STACK_POINTER_REG, ConfiguredCore}; +use r68k_emu::interrupts::AutoInterruptController; +use instant::Instant; use gfx::Gfx; // TODO: composit layers in gfx istead of multiple buffers @@ -24,9 +24,44 @@ use gfx::Gfx; pub struct Megadrive { pub core: ConfiguredCore, pub gfx: Gfx, + pub frame_timer: FrameTimer, // version: NTSC/PAL } +pub struct FrameTimer { + pub frames_to_render: u64, + pub frames: u64, + pub epoch: Instant, +} + +impl Default for FrameTimer { + fn default() -> Self { + Self { + frames: 0, + frames_to_render: 0, + epoch: Instant::now(), + } + } +} + +impl FrameTimer { + /// returns frames to render + pub fn frames_to_render(&mut self) -> u64 { + let diff = Instant::now().duration_since(self.epoch); + let frames = (diff.as_millis() as f64 * 0.05992274) as u64; // TODO: PAL + // self.emu.gfx.framerate() + self.frames_to_render = frames - self.frames; + self.frames = frames; + self.frames_to_render + } + /// for unpausing + pub fn reset_epoch(&mut self) { + self.epoch = Instant::now(); + } +} + +// impl default for gfx + impl Megadrive { pub fn new(buf: Vec) -> Self { let mem = mem::Mem::new(buf.into()); @@ -39,9 +74,24 @@ impl Megadrive { Megadrive { core, gfx: Gfx::new(), + frame_timer: Default::default(), } } + /// render frame at current instant + pub fn render(&mut self) { + let frames_to_render = self.frame_timer.frames_to_render(); + if frames_to_render > 3 { // magic number + self.frame(true); + } else if frames_to_render > 0 { + for _ in 0..frames_to_render - 1 { + self.frame(false); + } + self.frame(true); + } + } + + /// renders a single frame pub fn frame(&mut self, draw: bool) { /* cycle counts initially taken from drx/kiwi */ // TODO: use a counter instead diff --git a/frontend/Cargo.toml b/frontend/Cargo.toml index f78511f..ffb5549 100644 --- a/frontend/Cargo.toml +++ b/frontend/Cargo.toml @@ -14,7 +14,6 @@ crate-type = ["cdylib", "rlib"] [dependencies] emu = { path = "../emu" } -instant = "0.1" # puffin = "0.13.3" # puffin_egui = "0.15.0" diff --git a/frontend/src/app.rs b/frontend/src/app.rs index 18840ae..e1376f6 100644 --- a/frontend/src/app.rs +++ b/frontend/src/app.rs @@ -1,12 +1,10 @@ use emu::Megadrive; use crate::widgets; -use instant::Instant; use std::collections::VecDeque; pub struct App { emu: Megadrive, debug: crate::debug::Debug, - game_state: FrameCounter, pub fullscreen: bool, pub vsync: bool, pub running: bool, @@ -19,7 +17,6 @@ impl Default for App { Self { emu: Megadrive::new(buf), debug: Default::default(), - game_state: Default::default(), fullscreen: false, vsync: false, running: true, @@ -28,39 +25,6 @@ impl Default for App { } } -// TODO: move to core -pub struct FrameCounter { - frames: u64, - epoch: Instant, - frames_to_render: u64, -} - -impl Default for FrameCounter { - fn default() -> Self { - Self { - frames: 0, - frames_to_render: 0, - epoch: Instant::now(), - } - } -} - -impl FrameCounter { - /// returns frames to render - pub fn tick(&mut self) -> u64 { - let diff = Instant::now().duration_since(self.epoch); - let frames = (diff.as_millis() as f64 * 0.05992274) as u64; // TODO: PAL - // self.emu.gfx.framerate() - self.frames_to_render = frames - self.frames; - self.frames = frames; - self.frames_to_render - } - /// for unpausing - pub fn reset_epoch(&mut self) { - self.epoch = Instant::now(); - } -} - impl App { pub fn new(cc: &eframe::CreationContext<'_>) -> Self { cc.egui_ctx.set_visuals(egui::Visuals { @@ -99,16 +63,7 @@ impl eframe::App for App { crate::input::dummy_input(ctx, &mut self.emu); - let frames_to_render = self.game_state.tick(); - - if frames_to_render > 3 { - self.emu.frame(true); - } else if frames_to_render > 0 { - for _ in 0..frames_to_render - 1 { - self.emu.frame(false); - } - self.emu.frame(true); - } + self.emu.render(); } // layout starts with fullscreen @@ -150,7 +105,7 @@ impl eframe::App for App { egui::warn_if_debug_build(ui); // ctx.inspection_ui(ui); - ui.label(&format!("MD frames this frame: {}", self.game_state.frames_to_render)); + ui.label(&format!("MD frames this frame: {}", self.emu.frame_timer.frames_to_render)); ui.label(&format!("avg frames {:.1}", self.test_vec.iter().sum::() as f32 / self.test_vec.len() as f32)); if ui.button(if self.running { "pause" } else { "play" }).clicked() { @@ -159,7 +114,7 @@ impl eframe::App for App { ui.radio_value(&mut self.vsync, true, "vsync"); ui.radio_value(&mut self.vsync, false, "not vsync"); - self.test_vec.push_back(self.game_state.frames_to_render.min(4)); + self.test_vec.push_back(self.emu.frame_timer.frames_to_render.min(4)); if self.test_vec.len() > 60 { self.test_vec.pop_front();