Don't store luts in savestate (#993)
* use hashmap for tlb * more * more * more * more * more
This commit is contained in:
parent
79d2c023e6
commit
5c7170268e
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -2232,6 +2232,7 @@ dependencies = [
|
||||
"regex",
|
||||
"reqwest",
|
||||
"rfd",
|
||||
"rustc-hash 2.1.2",
|
||||
"sdl3-image-sys",
|
||||
"sdl3-src",
|
||||
"sdl3-sys",
|
||||
|
||||
@ -25,6 +25,7 @@ encoding_rs = "0.8"
|
||||
mimalloc = "0.1"
|
||||
regex = "1.11"
|
||||
tokio-tungstenite = "0.29"
|
||||
rustc-hash = "2.1"
|
||||
futures = "0.3"
|
||||
socket2 = { version = "0.6", features = ["all"] }
|
||||
rand = "0.10"
|
||||
|
||||
@ -26,7 +26,7 @@ pub type Cheat = std::collections::BTreeMap<String, std::collections::BTreeMap<S
|
||||
|
||||
pub fn init(
|
||||
device: &mut device::Device,
|
||||
cheat_settings: std::collections::HashMap<String, Option<String>>,
|
||||
cheat_settings: rustc_hash::FxHashMap<String, Option<String>>,
|
||||
) {
|
||||
let cheats = serde_json::from_slice::<Cheat>(include_bytes!("../data/cheats.json"))
|
||||
.unwrap()
|
||||
|
||||
@ -16,7 +16,7 @@ const N64_EXTENSIONS_UNCOMPRESSED: [&str; 8] =
|
||||
use rand::{Rng, SeedableRng};
|
||||
|
||||
use crate::{cheats, netplay, retroachievements, savestates, ui};
|
||||
use std::{collections::HashMap, io::Read};
|
||||
use std::io::Read;
|
||||
|
||||
pub mod ai;
|
||||
pub mod cache;
|
||||
@ -310,20 +310,8 @@ impl Device {
|
||||
is_event: false,
|
||||
instrs: [cop0::reserved; 32],
|
||||
instrs2: [cop0::reserved; 32],
|
||||
tlb_lut_w: vec![
|
||||
tlb::TlbLut {
|
||||
address: 0,
|
||||
cached: false,
|
||||
};
|
||||
0x100000
|
||||
],
|
||||
tlb_lut_r: vec![
|
||||
tlb::TlbLut {
|
||||
address: 0,
|
||||
cached: false,
|
||||
};
|
||||
0x100000
|
||||
],
|
||||
tlb_lut_w: vec![],
|
||||
tlb_lut_r: vec![],
|
||||
tlb_entries: [tlb::TlbEntry {
|
||||
mask: 0,
|
||||
vpn2: 0,
|
||||
@ -558,7 +546,7 @@ impl Device {
|
||||
word_buffer: [0; 40],
|
||||
words: Vec::new(),
|
||||
talking: false,
|
||||
word_mappings: HashMap::new(),
|
||||
word_mappings: rustc_hash::FxHashMap::default(),
|
||||
},
|
||||
rng: set_rng(),
|
||||
transferpaks: [
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use crate::device;
|
||||
#[cfg(all(feature = "gui", not(target_os = "android")))]
|
||||
use crate::ui;
|
||||
use std::collections::HashMap;
|
||||
|
||||
const JCMD_VRU_READ: u8 = 0x09;
|
||||
const JCMD_VRU_WRITE: u8 = 0x0A;
|
||||
@ -28,7 +27,7 @@ pub struct Vru {
|
||||
pub word_buffer: [u16; 40],
|
||||
pub words: Vec<String>,
|
||||
pub talking: bool,
|
||||
pub word_mappings: HashMap<String, String>,
|
||||
pub word_mappings: rustc_hash::FxHashMap<String, String>,
|
||||
}
|
||||
|
||||
pub fn init(device: &mut device::Device) {
|
||||
@ -186,7 +185,7 @@ pub fn process(device: &mut device::Device, channel: usize) {
|
||||
#[cfg(any(not(feature = "gui"), target_os = "android"))]
|
||||
let index = 0x7FFF;
|
||||
let num_results = if index == 0x7FFF { 0 } else { 1 };
|
||||
let data: HashMap<usize, u16> = HashMap::from([
|
||||
let data: rustc_hash::FxHashMap<usize, u16> = rustc_hash::FxHashMap::from_iter([
|
||||
(0, 0x8000),
|
||||
(2, 0x0F00),
|
||||
(4, 0), // error flags
|
||||
@ -247,7 +246,7 @@ pub fn vru_talking_event(device: &mut device::Device) {
|
||||
}
|
||||
|
||||
fn create_word_mappings(device: &mut device::Device) {
|
||||
device.vru.word_mappings = HashMap::from([
|
||||
device.vru.word_mappings = rustc_hash::FxHashMap::from_iter([
|
||||
(
|
||||
String::from("03A50024000303CF00A80003036000EA"),
|
||||
String::from("pikachu"),
|
||||
|
||||
@ -100,7 +100,9 @@ pub struct Cop0 {
|
||||
pub instrs: [fn(&mut device::Device, u32); 32],
|
||||
#[serde(skip, default = "savestates::default_instructions")]
|
||||
pub instrs2: [fn(&mut device::Device, u32); 32],
|
||||
#[serde(skip)]
|
||||
pub tlb_lut_r: Vec<device::tlb::TlbLut>,
|
||||
#[serde(skip)]
|
||||
pub tlb_lut_w: Vec<device::tlb::TlbLut>,
|
||||
pub tlb_entries: [device::tlb::TlbEntry; 32],
|
||||
pub is_event: bool,
|
||||
@ -369,6 +371,7 @@ pub fn init(device: &mut device::Device) {
|
||||
];
|
||||
|
||||
map_instructions(device);
|
||||
device::tlb::init(device);
|
||||
|
||||
// taken from VR4300 manual
|
||||
device.cpu.cop0.regs[COP0_RANDOM_REG] = 0b00000000000000000000000000011111;
|
||||
|
||||
@ -30,6 +30,23 @@ pub struct TlbEntry {
|
||||
pub phys_odd: u64,
|
||||
}
|
||||
|
||||
pub fn init(device: &mut device::Device) {
|
||||
device.cpu.cop0.tlb_lut_r.resize(
|
||||
0x100000,
|
||||
device::tlb::TlbLut {
|
||||
address: 0,
|
||||
cached: false,
|
||||
},
|
||||
);
|
||||
device.cpu.cop0.tlb_lut_w.resize(
|
||||
0x100000,
|
||||
device::tlb::TlbLut {
|
||||
address: 0,
|
||||
cached: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
pub fn read(device: &mut device::Device, index: u64) {
|
||||
if index > 31 {
|
||||
return;
|
||||
@ -181,7 +198,7 @@ fn tlb_unmap(device: &mut device::Device, index: u64) {
|
||||
}
|
||||
}
|
||||
|
||||
fn tlb_map(device: &mut device::Device, index: u64) {
|
||||
pub fn tlb_map(device: &mut device::Device, index: u64) {
|
||||
let e = &device.cpu.cop0.tlb_entries[index as usize];
|
||||
|
||||
if e.v_even != 0
|
||||
|
||||
@ -38,7 +38,7 @@ pub struct PlayerData {
|
||||
lag: u8,
|
||||
count: u32,
|
||||
pub reg_id: u32,
|
||||
input_events: std::collections::HashMap<u32, InputEvent>,
|
||||
input_events: rustc_hash::FxHashMap<u32, InputEvent>,
|
||||
}
|
||||
|
||||
struct InputEvent {
|
||||
@ -310,25 +310,25 @@ pub fn init(peer_addr: std::net::SocketAddr, player_number: u8) -> Netplay {
|
||||
lag: 0,
|
||||
count: 0,
|
||||
reg_id: reg_id[0],
|
||||
input_events: std::collections::HashMap::new(),
|
||||
input_events: rustc_hash::FxHashMap::default(),
|
||||
},
|
||||
PlayerData {
|
||||
lag: 0,
|
||||
count: 0,
|
||||
reg_id: reg_id[1],
|
||||
input_events: std::collections::HashMap::new(),
|
||||
input_events: rustc_hash::FxHashMap::default(),
|
||||
},
|
||||
PlayerData {
|
||||
lag: 0,
|
||||
count: 0,
|
||||
reg_id: reg_id[2],
|
||||
input_events: std::collections::HashMap::new(),
|
||||
input_events: rustc_hash::FxHashMap::default(),
|
||||
},
|
||||
PlayerData {
|
||||
lag: 0,
|
||||
count: 0,
|
||||
reg_id: reg_id[3],
|
||||
input_events: std::collections::HashMap::new(),
|
||||
input_events: rustc_hash::FxHashMap::default(),
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@ -97,12 +97,13 @@ pub fn create_savestate(device: &mut device::Device, rewind: bool) {
|
||||
let save_path = device.ui.storage.paths.savestate_file_path.clone();
|
||||
|
||||
let device_clone = device.clone_without_ui();
|
||||
let saves_clone = device.ui.storage.saves.clone();
|
||||
let save_state_slot = device.ui.storage.save_state_slot;
|
||||
let rewind_pool = device.savestate.rewind_pool.clone();
|
||||
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)
|
||||
&& let Ok(saves_data) = postcard::to_stdvec(&saves_clone)
|
||||
{
|
||||
if rewind {
|
||||
if let Ok(mut pool) = rewind_pool.lock() {
|
||||
@ -246,6 +247,11 @@ pub fn load_savestate(device: &mut device::Device, rewind: bool) {
|
||||
}
|
||||
}
|
||||
|
||||
device::tlb::init(device);
|
||||
for i in 0..32 {
|
||||
device::tlb::tlb_map(device, i);
|
||||
}
|
||||
|
||||
device::pif::connect_pif_channels(device);
|
||||
for i in 0..4 {
|
||||
if let Some(handler) = device.pif.channels[i].pak_handler {
|
||||
|
||||
@ -85,7 +85,7 @@ pub struct Usb {
|
||||
pub struct GameSettings {
|
||||
pub overclock: bool,
|
||||
pub disable_expansion_pak: bool,
|
||||
pub cheats: std::collections::HashMap<String, Option<String>>,
|
||||
pub cheats: rustc_hash::FxHashMap<String, Option<String>>,
|
||||
pub load_savestate_slot: Option<u32>,
|
||||
}
|
||||
|
||||
@ -259,7 +259,7 @@ impl Ui {
|
||||
write_pending: false,
|
||||
},
|
||||
romsave: storage::RomSave {
|
||||
data: std::collections::HashMap::new(),
|
||||
data: rustc_hash::FxHashMap::default(),
|
||||
write_pending: false,
|
||||
},
|
||||
},
|
||||
|
||||
@ -66,8 +66,7 @@ pub struct Emulation {
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct Cheats {
|
||||
pub cheats:
|
||||
std::collections::HashMap<String, std::collections::HashMap<String, Option<String>>>,
|
||||
pub cheats: rustc_hash::FxHashMap<String, rustc_hash::FxHashMap<String, Option<String>>>,
|
||||
}
|
||||
|
||||
#[derive(Default, serde::Serialize, serde::Deserialize)]
|
||||
@ -109,7 +108,7 @@ impl Cheats {
|
||||
}
|
||||
}
|
||||
Cheats {
|
||||
cheats: std::collections::HashMap::new(),
|
||||
cheats: rustc_hash::FxHashMap::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ fn run_with_path(weak: slint::Weak<AppWindow>, path: std::path::PathBuf) {
|
||||
ui::GameSettings {
|
||||
overclock: handle.get_overclock_n64_cpu(),
|
||||
disable_expansion_pak: handle.get_disable_expansion_pak(),
|
||||
cheats: std::collections::HashMap::new(), // will be filled in later
|
||||
cheats: rustc_hash::FxHashMap::default(), // will be filled in later
|
||||
load_savestate_slot: None,
|
||||
},
|
||||
None,
|
||||
@ -702,7 +702,7 @@ fn open_rom(app: &AppWindow) {
|
||||
ui::GameSettings {
|
||||
overclock,
|
||||
disable_expansion_pak,
|
||||
cheats: std::collections::HashMap::new(), // will be filled in later
|
||||
cheats: rustc_hash::FxHashMap::default(), // will be filled in later
|
||||
load_savestate_slot: None,
|
||||
},
|
||||
None,
|
||||
|
||||
@ -19,7 +19,7 @@ pub struct NetplayRoom {
|
||||
md5: Option<String>,
|
||||
game_name: Option<String>,
|
||||
pub port: Option<i32>,
|
||||
features: Option<std::collections::HashMap<String, String>>,
|
||||
features: Option<rustc_hash::FxHashMap<String, String>>,
|
||||
buffer_target: Option<i32>,
|
||||
}
|
||||
|
||||
@ -60,9 +60,8 @@ async fn get_local_servers() -> Vec<(String, String)> {
|
||||
broadcast_sock.recv(&mut buffer),
|
||||
)
|
||||
.await
|
||||
&& let Ok(data) = serde_json::from_slice::<std::collections::HashMap<String, String>>(
|
||||
&buffer[..result],
|
||||
)
|
||||
&& let Ok(data) =
|
||||
serde_json::from_slice::<rustc_hash::FxHashMap<String, String>>(&buffer[..result])
|
||||
{
|
||||
let mut local_servers = vec![];
|
||||
for server in data.iter() {
|
||||
@ -207,7 +206,7 @@ fn setup_create_window(
|
||||
|
||||
if let Ok(response) = response
|
||||
&& let Ok(server) = response
|
||||
.json::<std::collections::HashMap<String, String>>()
|
||||
.json::<rustc_hash::FxHashMap<String, String>>()
|
||||
.await
|
||||
{
|
||||
let server_url = server.values().next().unwrap();
|
||||
@ -427,19 +426,19 @@ fn update_sessions(weak: slint::Weak<AppWindow>) {
|
||||
.header("netplay-id", env!("NETPLAY_ID"))
|
||||
.send();
|
||||
tokio::spawn(async move {
|
||||
let mut dispatcher_servers = std::collections::HashMap::new();
|
||||
let mut dispatcher_servers = rustc_hash::FxHashMap::default();
|
||||
let response = task.await;
|
||||
if let Ok(response) = response
|
||||
&& let Ok(servers) = response
|
||||
.json::<std::collections::HashMap<String, String>>()
|
||||
.json::<rustc_hash::FxHashMap<String, String>>()
|
||||
.await
|
||||
{
|
||||
dispatcher_servers = servers;
|
||||
}
|
||||
let weak2 = weak.clone();
|
||||
weak.upgrade_in_event_loop(move |handle| {
|
||||
let mut servers: std::collections::HashMap<String, String> =
|
||||
std::collections::HashMap::new();
|
||||
let mut servers: rustc_hash::FxHashMap<String, String> =
|
||||
rustc_hash::FxHashMap::default();
|
||||
let server_names = handle.get_netplay_server_names();
|
||||
let server_urls = handle.get_netplay_server_urls();
|
||||
for (i, server_name) in server_names.iter().enumerate() {
|
||||
@ -529,7 +528,7 @@ fn create_session(
|
||||
.as_millis()
|
||||
.to_string();
|
||||
let hasher = Sha256::new().chain_update(&now_utc).chain_update(EMU_NAME);
|
||||
let mut features = std::collections::HashMap::new();
|
||||
let mut features = rustc_hash::FxHashMap::default();
|
||||
|
||||
if !game_cheats.is_empty() {
|
||||
features.insert("cheats".to_string(), game_cheats);
|
||||
@ -1126,7 +1125,7 @@ pub fn netplay_window(app: &AppWindow) {
|
||||
ui::GameSettings {
|
||||
overclock: handle.get_overclock_n64_cpu(),
|
||||
disable_expansion_pak: handle.get_disable_expansion_pak(),
|
||||
cheats: std::collections::HashMap::new(), // not used here
|
||||
cheats: rustc_hash::FxHashMap::default(), // not used here
|
||||
load_savestate_slot: None,
|
||||
},
|
||||
write_sender,
|
||||
|
||||
@ -26,19 +26,19 @@ pub struct Paths {
|
||||
|
||||
// the bool indicates whether the save has been written to
|
||||
// if that is the case, it will be flushed to the disk when the program closes
|
||||
#[derive(Default, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Default, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct Save {
|
||||
pub data: Vec<u8>,
|
||||
pub write_pending: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Default, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct RomSave {
|
||||
pub data: std::collections::HashMap<u32, u8>,
|
||||
pub data: rustc_hash::FxHashMap<u32, u8>,
|
||||
pub write_pending: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Default, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct Saves {
|
||||
pub eeprom: Save,
|
||||
pub sram: Save,
|
||||
|
||||
Reference in New Issue
Block a user