Savestate tweaks (#999)

* move savestate processing

* fix stack overflow

* more

* more
This commit is contained in:
Logan McNaughton
2026-05-31 21:29:28 +02:00
committed by GitHub
parent 5175d50aa8
commit d968983ceb
6 changed files with 32 additions and 27 deletions
+5 -2
View File
@@ -703,8 +703,11 @@ void rdp_check_framebuffers(uint32_t address, uint32_t length) {
size_t rdp_state_size() { return sizeof(RDP_DEVICE); }
void rdp_save_state(uint8_t *state, bool rewind) {
if (!rewind) // speed hack for rewind
processor->wait_for_timeline(processor->signal_timeline());
if (!rewind) { // speed hack for rewind
processor->idle();
rdram_dirty.assign(gfx_info.RDRAM_SIZE >> 3, false);
sync_signal = 0;
}
memcpy(state, &rdp_device, sizeof(RDP_DEVICE));
}
+2 -1
View File
@@ -229,6 +229,7 @@ pub struct Device {
#[serde(skip)]
pub ui: ui::Ui,
pub byte_swap: usize,
pub frame_counter: u64,
pub savestate: savestates::Savestate,
pub cpu: cpu::Cpu,
pub pif: pif::Pif,
@@ -290,6 +291,7 @@ impl Device {
ui::Ui::default()
},
byte_swap,
frame_counter: 0,
savestate: savestates::Savestate {
save_state: false,
load_state: false,
@@ -529,7 +531,6 @@ impl Device {
count_per_scanline: 0,
enable_speed_limiter: true,
next_pace_deadline: None,
vi_counter: 0,
min_wait_time: std::time::Duration::from_secs(1),
frame_time: 0.0,
elapsed_time: 0.0,
+2 -2
View File
@@ -58,12 +58,12 @@ pub fn process(device: &mut device::Device, channel: usize) {
let offset = device.pif.channels[channel].rx_buf.unwrap();
let input = if let Some(netplay) = &mut device.netplay {
if netplay.player_number as usize == channel {
let local_input = ui::input::get(&mut device.ui, 0, device.vi.vi_counter);
let local_input = ui::input::get(&mut device.ui, 0, device.frame_counter);
netplay::send_input(netplay, local_input);
}
netplay::get_input(device, channel)
} else {
ui::input::get(&mut device.ui, channel, device.vi.vi_counter)
ui::input::get(&mut device.ui, channel, device.frame_counter)
};
device.pif.ram[offset..offset + 4].copy_from_slice(&input.data.to_ne_bytes());
+1 -15
View File
@@ -120,21 +120,7 @@ fn run_rdp(device: &mut device::Device) {
device.rdp.regs_dpc[DPC_PIPEBUSY_REG] = 0xFFFFFF;
if timer != 0 {
if device.savestate.save_state || device.savestate.save_rewind {
// Right after full sync, good time for save state
let rewind = device.savestate.save_rewind && !device.savestate.save_state;
if rewind {
device.savestate.save_rewind = false;
}
device.savestate.save_state = false;
savestates::create_savestate(device, rewind);
} else if device.savestate.load_state || device.savestate.load_rewind {
// Right after full sync, good time for save state
device.savestate.load_state = false;
let rewind = device.savestate.load_rewind;
device.savestate.load_rewind = false;
savestates::load_savestate(device, rewind);
}
savestates::process_savestates(device);
device::events::create_event(device, device::events::EVENT_TYPE_DP, timer)
}
}
+2 -3
View File
@@ -26,7 +26,6 @@ pub struct Vi {
pub next_pace_deadline: Option<std::time::Instant>,
pub count_per_scanline: u64,
pub enable_speed_limiter: bool,
pub vi_counter: u64,
pub min_wait_time: std::time::Duration,
pub frame_time: f64,
pub elapsed_time: f64,
@@ -152,14 +151,14 @@ pub fn vertical_interrupt_event(device: &mut device::Device) {
reset_pace_deadline(device);
}
if device.vi.vi_counter.is_multiple_of(device.vi.limit_freq) && device.vi.enable_speed_limiter {
if device.frame_counter.is_multiple_of(device.vi.limit_freq) && device.vi.enable_speed_limiter {
speed_limiter(device);
}
unsafe { sdl3_sys::events::SDL_PumpEvents() };
ui::video::update_screen();
device.vi.vi_counter += 1;
device.frame_counter += 1;
if device.netplay.is_none() && paused {
if retroachievements::get_hardcore() {
+20 -4
View File
@@ -94,7 +94,23 @@ static DEVICE_CLONE: std::sync::LazyLock<std::sync::Mutex<device::Device>> =
static SAVES_CLONE: std::sync::LazyLock<std::sync::Mutex<ui::storage::Saves>> =
std::sync::LazyLock::new(|| std::sync::Mutex::new(ui::storage::Saves::default()));
pub fn create_savestate(device: &mut device::Device, rewind: bool) {
pub fn process_savestates(device: &mut device::Device) {
if device.savestate.save_state || device.savestate.save_rewind {
let rewind = device.savestate.save_rewind && !device.savestate.save_state;
if rewind {
device.savestate.save_rewind = false;
}
device.savestate.save_state = false;
create_savestate(device, rewind);
} else if device.savestate.load_state || device.savestate.load_rewind {
device.savestate.load_state = false;
let rewind = device.savestate.load_rewind;
device.savestate.load_rewind = false;
load_savestate(device, rewind);
}
}
fn create_savestate(device: &mut device::Device, rewind: bool) {
let mut rdp_state: Vec<u8> = vec![0; ui::video::state_size()];
ui::video::save_state(rdp_state.as_mut_ptr(), rewind);
@@ -175,7 +191,7 @@ pub fn create_savestate(device: &mut device::Device, rewind: bool) {
});
}
pub fn load_savestate(device: &mut device::Device, rewind: bool) {
fn load_savestate(device: &mut device::Device, rewind: bool) {
if retroachievements::get_hardcore() {
ui::video::onscreen_message(
"Cannot load savestate in RA hardcore mode",
@@ -196,11 +212,11 @@ pub fn load_savestate(device: &mut device::Device, rewind: bool) {
&& let Ok(saves_data) = ui::storage::decompress_file(savestate, "saves")
&& let Ok(rdp_state) = ui::storage::decompress_file(savestate, "rdp_state")
&& let Ok(ra_state) = ui::storage::decompress_file(savestate, "ra_state")
&& let Ok(state) = postcard::from_bytes::<device::Device>(&device_data)
&& let Ok(state) = postcard::from_bytes::<Box<device::Device>>(&device_data)
&& let Ok(saves) = postcard::from_bytes(&saves_data)
{
Some(SavestateData {
device: state,
device: *state,
saves,
rdp_state,
ra_state,