move speed limiter out of save state (#1030)

This commit is contained in:
Logan McNaughton
2026-06-07 11:55:18 +02:00
committed by GitHub
parent ba35935d2e
commit 577741907f
6 changed files with 52 additions and 43 deletions
+22 -7
View File
@@ -221,14 +221,27 @@ pub fn get_rom_contents(file_path: &std::path::PathBuf) -> Option<Vec<u8>> {
}
}
#[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<std::time::Instant>,
}
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Device {
#[serde(skip)]
pub netplay: Option<netplay::Netplay>,
#[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,
+1 -1
View File
@@ -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());
+25 -31
View File
@@ -22,17 +22,9 @@ pub struct Vi {
pub clock: u64,
pub delay: u64,
pub field: u32,
#[serde(skip)]
pub next_pace_deadline: Option<std::time::Instant>,
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();
}
}
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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);
}
}
+2 -2
View File
@@ -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;
}
}