diff --git a/src/device.rs b/src/device.rs index 21598a65..4cc09479 100644 --- a/src/device.rs +++ b/src/device.rs @@ -221,14 +221,27 @@ pub fn get_rom_contents(file_path: &std::path::PathBuf) -> Option> { } } +#[derive(serde::Serialize, serde::Deserialize)] +pub struct SpeedLimiter { + pub limit_freq: u64, + #[serde(skip)] + #[serde(default = "std::time::Instant::now")] + pub limit_freq_check: std::time::Instant, + pub frame_counter: u64, + pub enabled: bool, + pub min_wait_time: std::time::Duration, + #[serde(skip)] + pub next_pace_deadline: Option, +} + #[derive(serde::Serialize, serde::Deserialize)] pub struct Device { #[serde(skip)] pub netplay: Option, #[serde(skip)] pub ui: ui::Ui, + pub speed_limiter: SpeedLimiter, pub byte_swap: usize, - pub frame_counter: u64, pub savestate: savestates::Savestate, pub cpu: cpu::Cpu, pub pif: pif::Pif, @@ -289,8 +302,15 @@ impl Device { } else { ui::Ui::default() }, + speed_limiter: SpeedLimiter { + limit_freq: 2, + limit_freq_check: std::time::Instant::now(), + frame_counter: 0, + enabled: true, + min_wait_time: std::time::Duration::from_secs(1), + next_pace_deadline: None, + }, byte_swap, - frame_counter: 0, savestate: savestates::Savestate { save_state: false, load_state: false, @@ -528,13 +548,8 @@ impl Device { field: 0, delay: 0, count_per_scanline: 0, - enable_speed_limiter: true, - next_pace_deadline: None, - min_wait_time: std::time::Duration::from_secs(1), frame_time: 0.0, elapsed_time: 0.0, - limit_freq: 2, - limit_freq_check: std::time::Instant::now(), }, vru: controller::vru::Vru { status: 0, diff --git a/src/device/controller.rs b/src/device/controller.rs index 1eda9e50..61afd961 100644 --- a/src/device/controller.rs +++ b/src/device/controller.rs @@ -59,7 +59,7 @@ pub fn process(device: &mut device::Device, channel: usize) { let input = if let Some(netplay) = &mut device.netplay { netplay.inputs[channel].0 } else { - ui::input::get(&mut device.ui, channel, device.frame_counter) + ui::input::get(&mut device.ui, channel, device.speed_limiter.frame_counter) }; device.pif.ram[offset..offset + 4].copy_from_slice(&input.data.to_ne_bytes()); diff --git a/src/device/vi.rs b/src/device/vi.rs index 95153923..2b512444 100644 --- a/src/device/vi.rs +++ b/src/device/vi.rs @@ -22,17 +22,9 @@ pub struct Vi { pub clock: u64, pub delay: u64, pub field: u32, - #[serde(skip)] - pub next_pace_deadline: Option, pub count_per_scanline: u64, - pub enable_speed_limiter: bool, - pub min_wait_time: std::time::Duration, pub frame_time: f64, pub elapsed_time: f64, - pub limit_freq: u64, - #[serde(skip)] - #[serde(default = "std::time::Instant::now")] - pub limit_freq_check: std::time::Instant, } const MAX_LIMIT_FREQ: u64 = 3; @@ -45,12 +37,10 @@ pub fn set_expected_refresh_rate(device: &mut device::Device) { device.vi.frame_time = 1.0 / expected_refresh_rate; device.vi.delay = (device.cpu.clock_rate as f64 / expected_refresh_rate) as u64; device.vi.count_per_scanline = device.vi.delay / (device.vi.regs[VI_V_SYNC_REG] + 1) as u64; - - reset_pace_deadline(device); } fn reset_pace_deadline(device: &mut device::Device) { - device.vi.next_pace_deadline = None; + device.speed_limiter.next_pace_deadline = None; } fn set_vertical_interrupt(device: &mut device::Device) { @@ -154,8 +144,11 @@ pub fn vertical_interrupt_event(device: &mut device::Device) { } if !netplay::netplay_in_rollback(device.netplay.as_ref()) - && device.frame_counter.is_multiple_of(device.vi.limit_freq) - && device.vi.enable_speed_limiter + && device + .speed_limiter + .frame_counter + .is_multiple_of(device.speed_limiter.limit_freq) + && device.speed_limiter.enabled { speed_limiter(device); } @@ -163,8 +156,8 @@ pub fn vertical_interrupt_event(device: &mut device::Device) { if !netplay::netplay_in_rollback(device.netplay.as_ref()) { unsafe { sdl3_sys::events::SDL_PumpEvents() }; ui::video::update_screen(); + device.speed_limiter.frame_counter += 1; } - device.frame_counter += 1; if device.netplay.is_some() { device.netplay.as_mut().unwrap().inputs = netplay::process_requests(device); @@ -203,8 +196,9 @@ pub fn init(device: &mut device::Device) { fn speed_limiter(device: &mut device::Device) { let mut speed_limiter_toggled = false; - let mut interval = - std::time::Duration::from_secs_f64(device.vi.frame_time * device.vi.limit_freq as f64); + let mut interval = std::time::Duration::from_secs_f64( + device.vi.frame_time * device.speed_limiter.limit_freq as f64, + ); if let Some(netplay) = &device.netplay { let ahead = netplay.session.frames_ahead(); @@ -216,51 +210,51 @@ fn speed_limiter(device: &mut device::Device) { } let now = std::time::Instant::now(); - match device.vi.next_pace_deadline { + match device.speed_limiter.next_pace_deadline { None => { - device.vi.next_pace_deadline = Some(now + interval); + device.speed_limiter.next_pace_deadline = Some(now + interval); speed_limiter_toggled = true; } Some(deadline) => { if now < deadline { let dur = deadline - now; spin_sleep::sleep(dur); - if dur < device.vi.min_wait_time { - device.vi.min_wait_time = dur; + if dur < device.speed_limiter.min_wait_time { + device.speed_limiter.min_wait_time = dur; } } else { //println!("did not sleep"); - device.vi.min_wait_time = std::time::Duration::from_secs(0); + device.speed_limiter.min_wait_time = std::time::Duration::from_secs(0); } let mut next = deadline + interval; let t = std::time::Instant::now(); while next <= t { next += interval; } - device.vi.next_pace_deadline = Some(next); + device.speed_limiter.next_pace_deadline = Some(next); } } - if std::time::Instant::now().duration_since(device.vi.limit_freq_check) + if std::time::Instant::now().duration_since(device.speed_limiter.limit_freq_check) > std::time::Duration::from_secs(1) { if !speed_limiter_toggled { - if device.vi.min_wait_time == std::time::Duration::from_secs(0) - && device.vi.limit_freq < MAX_LIMIT_FREQ + if device.speed_limiter.min_wait_time == std::time::Duration::from_secs(0) + && device.speed_limiter.limit_freq < MAX_LIMIT_FREQ { - device.vi.limit_freq += 1; + device.speed_limiter.limit_freq += 1; reset_pace_deadline(device); - } else if device.vi.min_wait_time + } else if device.speed_limiter.min_wait_time > std::time::Duration::from_secs_f64(device.vi.frame_time) - && device.vi.limit_freq > 1 + && device.speed_limiter.limit_freq > 1 { - device.vi.limit_freq -= 1; + device.speed_limiter.limit_freq -= 1; reset_pace_deadline(device); } } //println!("limit freq: {}", device.vi.limit_freq); - device.vi.min_wait_time = std::time::Duration::from_secs(1); - device.vi.limit_freq_check = std::time::Instant::now(); + device.speed_limiter.min_wait_time = std::time::Duration::from_secs(1); + device.speed_limiter.limit_freq_check = std::time::Instant::now(); } } diff --git a/src/netplay.rs b/src/netplay.rs index 1e206097..3e2a23e7 100644 --- a/src/netplay.rs +++ b/src/netplay.rs @@ -258,7 +258,7 @@ fn process_netplay(device: &mut device::Device) -> Vec<(ui::input::InputData, gg fn advance_frame(device: &mut device::Device) { let netplay = device.netplay.as_mut().unwrap(); - let local_input = ui::input::get(&mut device.ui, 0, device.frame_counter); + let local_input = ui::input::get(&mut device.ui, 0, device.speed_limiter.frame_counter); let local_handle = *netplay.session.local_player_handles().first().unwrap(); netplay .session diff --git a/src/ui/audio.rs b/src/ui/audio.rs index 47c5f306..46f8cef9 100644 --- a/src/ui/audio.rs +++ b/src/ui/audio.rs @@ -203,7 +203,7 @@ pub fn play_audio(device: &device::Device, dram_addr: usize, length: u64) { primary_buffer.len() as i32 * 2, ) }; - } else if device.vi.enable_speed_limiter { + } else if device.speed_limiter.enabled { adjust_audio_frequency(device.ui.audio.audio_stream, 0.0005); } } diff --git a/src/ui/video.rs b/src/ui/video.rs index e7bed84f..8bbbed02 100644 --- a/src/ui/video.rs +++ b/src/ui/video.rs @@ -219,9 +219,9 @@ pub fn check_callback(device: &mut device::Device) -> (bool, bool) { device.cpu.clock_rate, // 1 second ); } - if device.vi.enable_speed_limiter != callback.enable_speedlimiter { + if device.speed_limiter.enabled != callback.enable_speedlimiter { speed_limiter_toggled = true; - device.vi.enable_speed_limiter = callback.enable_speedlimiter; + device.speed_limiter.enabled = callback.enable_speedlimiter; } }