move state to new thread (#990)

* move state to new thread

* more

* more
This commit is contained in:
Logan McNaughton
2026-05-30 14:26:38 +02:00
committed by GitHub
parent 3fdbe9a4f7
commit 7fc2412c9c
27 changed files with 91 additions and 52 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ pub struct DecodedCheat {
data: u16,
}
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Cheats {
pub cheats: Vec<Vec<DecodedCheat>>,
pub boot: bool,
+26
View File
@@ -256,6 +256,32 @@ pub fn zero_m128i() -> __m128i {
}
impl Device {
pub fn clone_without_ui(&self) -> Device {
Device {
netplay: None,
ui: ui::Ui::default(),
byte_swap: self.byte_swap,
save_state: self.save_state,
load_state: self.load_state,
cpu: self.cpu.clone(),
pif: self.pif.clone(),
cart: self.cart.clone(),
memory: self.memory.clone(),
rsp: self.rsp.clone(),
rdp: self.rdp.clone(),
rdram: self.rdram.clone(),
mi: self.mi.clone(),
pi: self.pi.clone(),
vi: self.vi.clone(),
ai: self.ai.clone(),
si: self.si.clone(),
ri: self.ri.clone(),
rng: self.rng.clone(),
vru: self.vru.clone(),
transferpaks: self.transferpaks.clone(),
cheats: self.cheats.clone(),
}
}
pub fn new() -> Device {
let mut byte_swap: usize = 0;
let test: [u8; 4] = [1, 2, 3, 4];
+1 -1
View File
@@ -11,7 +11,7 @@ pub const AI_REGS_COUNT: usize = 6;
pub const AI_STATUS_BUSY: u32 = 0x40000000;
const AI_STATUS_FULL: u32 = 0x80000000;
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Ai {
pub regs: [u32; AI_REGS_COUNT],
pub fifo: [AiDma; 2],
+2 -2
View File
@@ -21,7 +21,7 @@ const JDT_EEPROM_16K: u16 = 0xc000; /* 16k EEPROM */
const EEPROM_BLOCK_SIZE: usize = 8;
pub const EEPROM_MAX_SIZE: usize = 0x800;
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct AfRtc {
pub control: u16,
}
@@ -31,7 +31,7 @@ fn byte2bcd(mut n: u32) -> u8 {
(((n / 10) << 4) | (n % 10)) as u8
}
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Cart {
#[serde(skip)]
pub rom: Vec<u8>,
+1 -1
View File
@@ -20,7 +20,7 @@ pub const SC64_CFG_COUNT: usize = 15;
const SC64_BUFFER_MASK: usize = 0x1FFF;
const SC64_EEPROM_MASK: usize = 0xFFF;
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Sc64 {
pub buffer: Vec<u8>,
pub regs: [u32; SC64_REGS_COUNT],
+2 -2
View File
@@ -8,7 +8,7 @@ pub const MX29L1100_ID: u32 = 0x00c2001e;
const MX29L0000_ID: u32 = 0x00c20000;
const MX29L0001_ID: u32 = 0x00c20001;
#[derive(PartialEq, serde::Serialize, serde::Deserialize)]
#[derive(Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum FlashramMode {
ReadArray,
ReadSiliconId,
@@ -18,7 +18,7 @@ pub enum FlashramMode {
PageProgram,
}
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Flashram {
pub status: u32,
pub mode: FlashramMode,
+1 -1
View File
@@ -8,7 +8,7 @@ const MBC3_RTC_DAYS_L: usize = 3;
const MBC3_RTC_DAYS_H: usize = 4;
const MBC3_RTC_REGS_COUNT: usize = 5;
#[derive(Default, serde::Serialize, serde::Deserialize)]
#[derive(Default, Clone, serde::Serialize, serde::Deserialize)]
pub struct GbCart {
pub enabled: bool,
#[serde(skip)]
+1 -1
View File
@@ -1,6 +1,6 @@
use crate::device;
#[derive(Default, serde::Serialize, serde::Deserialize)]
#[derive(Default, Clone, serde::Serialize, serde::Deserialize)]
pub struct TransferPak {
pub enabled: bool,
pub reset_state: u8,
+1 -1
View File
@@ -18,7 +18,7 @@ const VOICE_STATUS_BUSY: u8 = 0x05;
const JDT_VRU: u16 = 0x0100; /* VRU */
const CONT_FLAVOR: u16 = JDT_VRU;
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Vru {
pub status: u8,
pub voice_state: u8,
+1 -1
View File
@@ -91,7 +91,7 @@ const COP0_XCONTEXT_REG_MASK: u64 =
const COP0_PARITYERR_REG_MASK: u64 = 0b00000000000000000000000011111111;
const COP0_TAGLO_REG_MASK: u64 = 0b00001111111111111111111111000000;
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Cop0 {
pub reg_latch: u64,
pub regs: [u64; COP0_REGS_COUNT],
+1 -1
View File
@@ -24,7 +24,7 @@ const FCR31_CAUSE_MASK: u32 = 0b00000000000000111111000000000000;
const FCR31_ENABLE_MASK: u32 = 0b00000000000000000000111110000000;
const FCR31_WRITE_MASK: u32 = 0b00000001100000111111111111111111;
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Cop1 {
pub fcr0: u32,
pub fcr31: u32,
+1 -1
View File
@@ -1,6 +1,6 @@
use crate::{device, savestates};
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Cop2 {
#[serde(skip, default = "savestates::default_instructions")]
pub instrs: [fn(&mut device::Device, u32); 32],
+3 -3
View File
@@ -1,6 +1,6 @@
use crate::{device, savestates, ui};
#[derive(PartialEq, serde::Serialize, serde::Deserialize)]
#[derive(Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum State {
Step,
Take,
@@ -11,13 +11,13 @@ pub enum State {
Exception,
}
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct BranchState {
pub state: State,
pub pc: u64,
}
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Cpu {
pub cop0: device::cop0::Cop0,
pub cop1: device::cop1::Cop1,
+1 -1
View File
@@ -38,7 +38,7 @@ pub enum AccessSize {
Icache = 32,
}
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Memory {
#[serde(skip, default = "savestates::default_memory_read_fast")]
pub fast_read: [fn(&device::Device, u64, AccessSize) -> u32; 0x2000], // fast_read is used for lookups that try to detect idle loops
+1 -1
View File
@@ -44,7 +44,7 @@ const MI_SET_RDRAM: u32 = 1 << 13;
pub const MI_INIT_LENGTH_MASK: u32 = 0b1111111;
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Mi {
pub regs: [u32; MI_REGS_COUNT],
}
+1 -1
View File
@@ -28,7 +28,7 @@ const PI_STATUS_INTERRUPT: u32 = 1 << 3;
const PI_STATUS_RESET: u32 = 1 << 0;
const PI_STATUS_CLR_INTR: u32 = 1 << 1;
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Pi {
pub regs: [u32; PI_REGS_COUNT],
}
+1 -1
View File
@@ -1,7 +1,7 @@
mod rom;
use crate::device;
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Pif {
#[serde(with = "serde_big_array::BigArray")]
pub rom: [u8; 1984],
+1 -1
View File
@@ -40,7 +40,7 @@ const DPC_CLR_PIPE_CTR: u32 = 1 << 7;
const DPC_CLR_CMD_CTR: u32 = 1 << 8;
const DPC_CLR_CLOCK_CTR: u32 = 1 << 9;
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Rdp {
pub regs_dpc: [u32; DPC_REGS_COUNT],
pub regs_dps: [u32; DPS_REGS_COUNT],
+1 -1
View File
@@ -17,7 +17,7 @@ pub const RDRAM_REGS_COUNT: usize = 10;
pub const RDRAM_MASK: usize = 0xFFFFFF;
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Rdram {
pub mem: Vec<u8>,
pub size: u32,
+1 -1
View File
@@ -10,7 +10,7 @@ pub const RI_REFRESH_REG: usize = 4;
//const RI_WERROR_REG: usize = 7;
pub const RI_REGS_COUNT: usize = 8;
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Ri {
pub regs: [u32; RI_REGS_COUNT],
pub ram_init: bool,
+2 -2
View File
@@ -6,7 +6,7 @@ use crate::{device, savestates};
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct BranchState {
pub state: device::cpu::State,
pub pc: u32,
@@ -25,7 +25,7 @@ pub enum InstructionType {
Vu,
}
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Cpu {
#[serde(with = "serde_big_array::BigArray")]
pub instructions: [Instructions; 0x1000 / 4],
+1 -1
View File
@@ -76,7 +76,7 @@ pub struct RspDma {
pub dramaddr: u32,
}
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Rsp {
pub cpu: device::rsp_cpu::Cpu,
pub regs: [u32; SP_REGS_COUNT],
+2 -2
View File
@@ -16,14 +16,14 @@ pub const SI_STATUS_IO_BUSY: u32 = 1 << 1;
//const SI_STATUS_DMA_ERROR: u32 = 1 << 3;
const SI_STATUS_INTERRUPT: u32 = 1 << 12;
#[derive(PartialEq, serde::Serialize, serde::Deserialize)]
#[derive(Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum DmaDir {
None,
Write,
Read,
}
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Si {
pub regs: [u32; SI_REGS_COUNT],
pub dma_dir: DmaDir,
+1 -1
View File
@@ -16,7 +16,7 @@ const VI_H_SYNC_REG: usize = 7;
//const VI_Y_SCALE_REG: usize = 13;
pub const VI_REGS_COUNT: usize = 14;
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Vi {
pub regs: [u32; VI_REGS_COUNT],
pub clock: u64,
+24 -21
View File
@@ -78,10 +78,13 @@ pub fn create_savestate(device: &device::Device) {
let save_path = device.ui.storage.paths.savestate_file_path.clone();
if let Ok(device_data) = postcard::to_stdvec(device)
&& let Ok(saves_data) = postcard::to_stdvec(&device.ui.storage.saves)
{
tokio::spawn(async move {
let device_clone = device.clone_without_ui();
let save_state_slot = device.ui.storage.save_state_slot;
tokio::spawn(async move {
let mut error = false;
if let Ok(device_data) = postcard::to_stdvec(&device_clone)
&& let Ok(saves_data) = postcard::to_stdvec(&device_clone.ui.storage.saves)
{
if let Ok(compressed_file) = ui::storage::compress_file(&[
(&device_data, "device"),
(&saves_data, "saves"),
@@ -90,27 +93,27 @@ pub fn create_savestate(device: &device::Device) {
]) {
if let Err(e) = tokio::fs::write(save_path, compressed_file).await {
eprintln!("Error writing savestate: {}", e);
error = true;
}
} else {
eprintln!("Error compressing savestate");
error = true;
}
});
ui::video::onscreen_message(
&format!(
"Savestate created in slot {}",
device.ui.storage.save_state_slot
),
ui::video::MESSAGE_LENGTH_MESSAGE_VERY_SHORT,
);
} else {
ui::video::onscreen_message(
&format!(
"Failed to create savestate in slot {}",
device.ui.storage.save_state_slot
),
ui::video::MESSAGE_LENGTH_MESSAGE_SHORT,
);
}
} else {
error = true;
}
if error {
ui::video::onscreen_message(
&format!("Failed to create savestate in slot {}", save_state_slot),
ui::video::MESSAGE_LENGTH_MESSAGE_SHORT,
);
} else {
ui::video::onscreen_message(
&format!("Savestate created in slot {}", save_state_slot),
ui::video::MESSAGE_LENGTH_MESSAGE_VERY_SHORT,
);
}
});
}
pub fn load_savestate(device: &mut device::Device) {
+9
View File
@@ -41,6 +41,9 @@ pub struct Audio {
pub gain: f32,
}
unsafe impl Send for Audio {}
unsafe impl Sync for Audio {}
#[derive(Default)]
pub struct Input {
pub keyboard_state: *const bool,
@@ -48,6 +51,9 @@ pub struct Input {
pub controllers: [input::Controllers; 4],
}
unsafe impl Send for Input {}
unsafe impl Sync for Input {}
#[derive(Default)]
pub struct Storage {
pub save_type: Vec<storage::SaveTypes>,
@@ -66,6 +72,9 @@ pub struct Video {
pub vis_rx: Option<tokio::sync::mpsc::Receiver<bool>>,
}
unsafe impl Send for Video {}
unsafe impl Sync for Video {}
#[derive(Default)]
pub struct Usb {
pub usb_tx: Option<tokio::sync::broadcast::Sender<usb::UsbData>>,
+3 -2
View File
@@ -137,8 +137,9 @@ impl Config {
let file_path = dirs.config_dir.join("config.json");
let config_file = std::fs::read(file_path);
if let Ok(config_file) = config_file {
let result = serde_json::from_slice(config_file.as_ref());
if let Ok(result) = result {
let result = serde_json::from_slice::<Config>(config_file.as_ref());
if let Ok(mut result) = result {
result.write_to_disk = true;
return result;
}
}