mirror of
https://github.com/FranLMSP/snes.git
synced 2026-08-03 08:30:01 -04:00
implement one tick per frame option
This commit is contained in:
@@ -393,9 +393,9 @@ mod ppu_registers_test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_get_bg_tile_size() {
|
fn test_get_bg_tile_size() {
|
||||||
let mut registers = PPURegisters::new();
|
let mut registers = PPURegisters::new();
|
||||||
registers.write(BGMODE, 0b00000100);
|
registers.write(BGMODE, 0b00000000);
|
||||||
assert_eq!(registers.get_bg_tile_size(Background::Bg1), TileSize::P8x8);
|
assert_eq!(registers.get_bg_tile_size(Background::Bg1), TileSize::P8x8);
|
||||||
registers.write(BGMODE, 0b00001100);
|
registers.write(BGMODE, 0b00010000);
|
||||||
assert_eq!(registers.get_bg_tile_size(Background::Bg1), TileSize::P16x16);
|
assert_eq!(registers.get_bg_tile_size(Background::Bg1), TileSize::P16x16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ edition = "2021"
|
|||||||
snes-core = { path = "../snes-core" }
|
snes-core = { path = "../snes-core" }
|
||||||
|
|
||||||
# Frontend stuff
|
# Frontend stuff
|
||||||
eframe = "0.24.1"
|
eframe = "0.25.0"
|
||||||
env_logger = "0.10.1"
|
env_logger = "0.10.1"
|
||||||
rfd = "0.12.1"
|
rfd = "0.12.1"
|
||||||
regex = "1.10.2"
|
regex = "1.10.2"
|
||||||
|
wgpu = "0.18.0"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
wgpu = ["eframe/wgpu"]
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
pub struct EmulationState {
|
pub struct EmulationState {
|
||||||
pub is_paused: bool,
|
pub is_paused: bool,
|
||||||
|
pub one_tick_per_frame: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmulationState {
|
impl EmulationState {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
is_paused: true,
|
is_paused: true,
|
||||||
|
one_tick_per_frame: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,6 +16,12 @@ pub fn build_cpu_debug_controls(ctx: &egui::Context, cpu_debug_options: &mut CPU
|
|||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
ui.monospace("Controls:");
|
ui.monospace("Controls:");
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
|
if ui.selectable_label(
|
||||||
|
emulation_state.one_tick_per_frame,
|
||||||
|
"Tick per frame"
|
||||||
|
).clicked() {
|
||||||
|
emulation_state.one_tick_per_frame = !emulation_state.one_tick_per_frame;
|
||||||
|
}
|
||||||
let pause_text = if emulation_state.is_paused {"Resume"} else {"Pause"};
|
let pause_text = if emulation_state.is_paused {"Resume"} else {"Pause"};
|
||||||
if ui.button(pause_text).clicked() {
|
if ui.button(pause_text).clicked() {
|
||||||
emulation_state.is_paused = !emulation_state.is_paused;
|
emulation_state.is_paused = !emulation_state.is_paused;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use snes_core::emulator::Emulator;
|
use snes_core::emulator::Emulator;
|
||||||
|
|
||||||
|
mod utils;
|
||||||
mod emu_ui;
|
mod emu_ui;
|
||||||
mod emu_state;
|
mod emu_state;
|
||||||
|
|
||||||
@@ -9,6 +10,7 @@ mod emu_state;
|
|||||||
struct SnesEmulatorApp {
|
struct SnesEmulatorApp {
|
||||||
emulator: Emulator,
|
emulator: Emulator,
|
||||||
state: emu_state::AppState,
|
state: emu_state::AppState,
|
||||||
|
frame_limit: utils::frame_limiter::FrameLimiter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SnesEmulatorApp {
|
impl SnesEmulatorApp {
|
||||||
@@ -25,14 +27,24 @@ impl eframe::App for SnesEmulatorApp {
|
|||||||
// ui::game::build_game_window(ctx);
|
// ui::game::build_game_window(ctx);
|
||||||
});
|
});
|
||||||
if !self.state.emulation_state.is_paused {
|
if !self.state.emulation_state.is_paused {
|
||||||
self.emulator.loop_frame();
|
if self.state.emulation_state.one_tick_per_frame {
|
||||||
|
self.emulator.tick();
|
||||||
|
} else {
|
||||||
|
self.emulator.loop_frame();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
emu_ui::debug::build_all_debug_options(ctx, &mut self.state.debug_options, &mut self.state.emulation_state, &mut self.emulator);
|
emu_ui::debug::build_all_debug_options(ctx, &mut self.state.debug_options, &mut self.state.emulation_state, &mut self.emulator);
|
||||||
|
ctx.request_repaint();
|
||||||
|
self.frame_limit.limit();
|
||||||
|
self.frame_limit.reset_timer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> eframe::Result<()> {
|
fn main() -> eframe::Result<()> {
|
||||||
let native_options = eframe::NativeOptions::default();
|
let native_options = eframe::NativeOptions {
|
||||||
|
vsync: false,
|
||||||
|
..eframe::NativeOptions::default()
|
||||||
|
};
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"SNES Emulator",
|
"SNES Emulator",
|
||||||
native_options,
|
native_options,
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
use std::{thread, time};
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
pub struct FrameLimiter {
|
||||||
|
timer: Instant,
|
||||||
|
fps: u128,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FrameLimiter {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
timer: Instant::now(),
|
||||||
|
fps: 16600,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset_timer(&mut self) {
|
||||||
|
self.timer = Instant::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn limit(&self) {
|
||||||
|
let elapsed = self.timer.elapsed().as_micros();
|
||||||
|
if elapsed > self.fps {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let wait = (self.fps - elapsed).try_into().unwrap();
|
||||||
|
thread::sleep(time::Duration::from_micros(wait));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FrameLimiter {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
pub mod frame_limiter;
|
||||||
Reference in New Issue
Block a user