mupen database

This commit is contained in:
Mateusz Faderewski 2023-03-03 13:21:16 +01:00
parent 24a665611e
commit 6d3d807d39
7 changed files with 18115 additions and 51 deletions

1
.gitattributes vendored
View File

@ -5,3 +5,4 @@ hw/pcb/*.html linguist-generated
sw/bootloader/src/fatfs/* linguist-vendored sw/bootloader/src/fatfs/* linguist-vendored
sw/bootloader/src/fatfs/diskio.c -linguist-vendored sw/bootloader/src/fatfs/diskio.c -linguist-vendored
sw/controller/inc/* linguist-vendored sw/controller/inc/* linguist-vendored
sw/deployer/data/* linguist-vendored

61
sw/deployer/Cargo.lock generated
View File

@ -29,6 +29,17 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "ahash"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
"getrandom",
"once_cell",
"version_check",
]
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.7.20" version = "0.7.20"
@ -312,6 +323,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "dlv-list"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257"
[[package]] [[package]]
name = "either" name = "either"
version = "1.8.1" version = "1.8.1"
@ -431,6 +448,15 @@ dependencies = [
"crunchy", "crunchy",
] ]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
"ahash",
]
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.4.1" version = "0.4.1"
@ -461,6 +487,12 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
version = "0.1.53" version = "0.1.53"
@ -634,6 +666,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "md5"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.5.0" version = "2.5.0"
@ -725,6 +763,16 @@ version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "ordered-multimap"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a"
dependencies = [
"dlv-list",
"hashbrown",
]
[[package]] [[package]]
name = "os_str_bytes" name = "os_str_bytes"
version = "6.4.1" version = "6.4.1"
@ -856,6 +904,16 @@ version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rust-ini"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df"
dependencies = [
"cfg-if",
"ordered-multimap",
]
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.36.8" version = "0.36.8"
@ -881,8 +939,11 @@ dependencies = [
"crc32fast", "crc32fast",
"ctrlc", "ctrlc",
"encoding_rs", "encoding_rs",
"hex",
"image", "image",
"md5",
"panic-message", "panic-message",
"rust-ini",
"serialport", "serialport",
] ]

View File

@ -14,6 +14,9 @@ colored = "2.0.0"
crc32fast = "1.3.2" crc32fast = "1.3.2"
ctrlc = "3.2.5" ctrlc = "3.2.5"
encoding_rs = "0.8.32" encoding_rs = "0.8.32"
hex = "0.4.3"
image = "0.24.5" image = "0.24.5"
md5 = "0.7.0"
panic-message = "0.3.0" panic-message = "0.3.0"
rust-ini = "0.18.0"
serialport = { git = "https://github.com/serialport/serialport-rs", branch = "main" } serialport = { git = "https://github.com/serialport/serialport-rs", branch = "main" }

17985
sw/deployer/data/mupen64plus.ini vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@ use colored::Colorize;
use panic_message::panic_message; use panic_message::panic_message;
use std::{ use std::{
fs::File, fs::File,
io::{self, Read, Write}, io::{self, BufReader, Read, Write},
path::PathBuf, path::PathBuf,
sync::{ sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
@ -250,7 +250,8 @@ fn handle_upload_command(sn: Option<String>, args: &UploadArgs) -> Result<(), sc
sc64.reset_state()?; sc64.reset_state()?;
let (mut rom_file, rom_name, rom_length) = open_file(&args.rom)?; let (rom_file_unbuffered, rom_name, rom_length) = open_file(&args.rom)?;
let mut rom_file = BufReader::new(rom_file_unbuffered);
log_wait(format!("Uploading ROM [{rom_name}]"), || { log_wait(format!("Uploading ROM [{rom_name}]"), || {
sc64.upload_rom(&mut rom_file, rom_length, args.no_shadow) sc64.upload_rom(&mut rom_file, rom_length, args.no_shadow)
@ -259,7 +260,10 @@ fn handle_upload_command(sn: Option<String>, args: &UploadArgs) -> Result<(), sc
let save: SaveType = if let Some(save_type) = args.save_type.clone() { let save: SaveType = if let Some(save_type) = args.save_type.clone() {
save_type save_type
} else { } else {
n64::guess_save_type(&mut rom_file)?.into() log_wait(format!("Calculating ROM hash"), || {
n64::guess_save_type(&mut rom_file)
})?
.into()
}; };
let save_type: sc64::SaveType = save.into(); let save_type: sc64::SaveType = save.into();

View File

@ -9,61 +9,71 @@ pub enum SaveType {
Flashram, Flashram,
} }
const HASH_CHUNK_LENGTH: usize = 64 * 1024;
pub fn guess_save_type<T: Read + Seek>(reader: &mut T) -> Result<SaveType, Error> { pub fn guess_save_type<T: Read + Seek>(reader: &mut T) -> Result<SaveType, Error> {
let mut header = vec![0u8; 0x40]; let mut ed64_header = vec![0u8; 4];
reader.rewind()?; reader.seek(std::io::SeekFrom::Start(0x3C))?;
reader.read_exact(&mut header)?; reader.read(&mut ed64_header)?;
if &ed64_header[0..2] == b"ED" {
let pi_config = &header[0..4]; return Ok(match ed64_header[3] >> 4 {
match pi_config { 1 => SaveType::Eeprom4k,
[0x37, 0x80, 0x40, 0x12] => { 2 => SaveType::Eeprom16k,
header.chunks_exact_mut(2).for_each(|c| c.swap(0, 1)); 3 => SaveType::Sram,
} 4 => SaveType::SramBanked,
[0x40, 0x12, 0x37, 0x80] => { 5 => SaveType::Flashram,
header.chunks_exact_mut(4).for_each(|c| { 6 => SaveType::Sram,
c.swap(0, 3); _ => SaveType::None,
c.swap(1, 2); });
});
}
_ => {}
} }
let rom_id = &header[0x3B..0x3E]; let mut pi_config = vec![0u8; 4];
// let region = header[0x3E];
// let revision = header[0x3F];
// TODO: fix this mess reader.rewind()?;
reader.read(&mut pi_config)?;
if let Some(save_type) = match rom_id { let endian_swapper = match &pi_config[0..4] {
b"NTW" | b"NHF" | b"NOS" | b"NTC" | b"NER" | b"NAG" | b"NAB" | b"NS3" | b"NTN" | b"NBN" [0x37, 0x80, 0x40, 0x12] => |b: &mut [u8]| b.chunks_exact_mut(2).for_each(|c| c.swap(0, 1)),
| b"NBK" | b"NFH" | b"NMU" | b"NBC" | b"NBH" | b"NHA" | b"NBM" | b"NBV" | b"NBD" [0x40, 0x12, 0x37, 0x80] => |b: &mut [u8]| {
| b"NCT" | b"NCH" | b"NCG" | b"NP2" | b"NXO" | b"NCU" | b"NCX" | b"NDY" | b"NDQ" b.chunks_exact_mut(4).for_each(|c| {
| b"NDR" | b"NN6" | b"NDU" | b"NJM" | b"NFW" | b"NF2" | b"NKA" | b"NFG" | b"NGL" c.swap(0, 3);
| b"NGV" | b"NGE" | b"NHP" | b"NPG" | b"NIJ" | b"NIC" | b"NFY" | b"NKI" | b"NLL" c.swap(1, 2)
| b"NLR" | b"NKT" | b"CLB" | b"NLB" | b"NMW" | b"NML" | b"NTM" | b"NMI" | b"NMG" })
| b"NMO" | b"NMS" | b"NMR" | b"NCR" | b"NEA" | b"NPW" | b"NPY" | b"NPT" | b"NRA" },
| b"NWQ" | b"NSU" | b"NSN" | b"NK2" | b"NSV" | b"NFX" | b"NFP" | b"NS6" | b"NNA" _ => |_: &mut [u8]| {},
| b"NRS" | b"NSW" | b"NSC" | b"NSA" | b"NB6" | b"NSS" | b"NTX" | b"NT6" | b"NTP" };
| b"NTJ" | b"NRC" | b"NTR" | b"NTB" | b"NGU" | b"NIR" | b"NVL" | b"NVY" | b"NWC"
| b"NAD" | b"NWU" | b"NYK" | b"NMZ" | b"NSM" | b"NWR" => Some(SaveType::Eeprom4k), let mut hasher = md5::Context::new();
b"NB7" | b"NGT" | b"NFU" | b"NCW" | b"NCZ" | b"ND6" | b"NDO" | b"ND2" | b"N3D" | b"NMX" let mut buffer = vec![0u8; HASH_CHUNK_LENGTH];
| b"NGC" | b"NIM" | b"NNB" | b"NMV" | b"NM8" | b"NEV" | b"NPP" | b"NUB" | b"NPD"
| b"NRZ" | b"NR7" | b"NEP" | b"NYS" => Some(SaveType::Eeprom16k), reader.rewind()?;
b"NTE" | b"NVB" | b"NB5" | b"CFZ" | b"NFZ" | b"NSI" | b"NG6" | b"NGP" | b"NYW" | b"NHY"
| b"NIB" | b"NPS" | b"NPA" | b"NP4" | b"NJ5" | b"NP6" | b"NPE" | b"NJG" | b"CZL" loop {
| b"NZL" | b"NKG" | b"NMF" | b"NRI" | b"NUT" | b"NUM" | b"NOB" | b"CPS" | b"NPM" let chunk = reader.read(&mut buffer)?;
| b"NRE" | b"NAL" | b"NT3" | b"NS4" | b"NA2" | b"NVP" | b"NWL" | b"NW2" | b"NWX" => { if chunk > 0 {
Some(SaveType::Sram) endian_swapper(&mut buffer[0..chunk]);
hasher.consume(&buffer[0..chunk]);
} else {
break;
} }
b"CDZ" => Some(SaveType::SramBanked), }
b"NCC" | b"NDA" | b"NAF" | b"NJF" | b"NKJ" | b"NZS" | b"NM6" | b"NCK" | b"NMQ" | b"NPN"
| b"NPF" | b"NPO" | b"CP2" | b"NP3" | b"NRH" | b"NSQ" | b"NT9" | b"NW4" | b"NDP" => { let hash = hex::encode_upper(hasher.compute().0);
Some(SaveType::Flashram)
let database_ini = include_str!("../data/mupen64plus.ini");
let database = ini::Ini::load_from_str(database_ini)
.expect("Error during mupen64plus.ini parse operation");
if let Some(section) = database.section(Some(hash)) {
if let Some(save_type) = section.get("SaveType") {
return Ok(match save_type {
"Eeprom 4KB" => SaveType::Eeprom4k,
"Eeprom 16KB" => SaveType::Eeprom16k,
"SRAM" => SaveType::Sram,
"Flash RAM" => SaveType::Flashram,
_ => SaveType::None,
});
} }
_ => None,
} {
return Ok(save_type);
} }
Ok(SaveType::None) Ok(SaveType::None)

View File

@ -211,7 +211,7 @@ pub enum BootMode {
impl Display for BootMode { impl Display for BootMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self { f.write_str(match self {
Self::Menu => "Menu", Self::Menu => "Bootloader -> Menu from SD card",
Self::Rom => "Bootloader -> ROM", Self::Rom => "Bootloader -> ROM",
Self::DdIpl => "Bootloader -> 64DD IPL", Self::DdIpl => "Bootloader -> 64DD IPL",
Self::DirectRom => "ROM (direct)", Self::DirectRom => "ROM (direct)",