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/diskio.c -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"
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]]
name = "aho-corasick"
version = "0.7.20"
@ -312,6 +323,12 @@ dependencies = [
"syn",
]
[[package]]
name = "dlv-list"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257"
[[package]]
name = "either"
version = "1.8.1"
@ -431,6 +448,15 @@ dependencies = [
"crunchy",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
"ahash",
]
[[package]]
name = "heck"
version = "0.4.1"
@ -461,6 +487,12 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "iana-time-zone"
version = "0.1.53"
@ -634,6 +666,12 @@ dependencies = [
"libc",
]
[[package]]
name = "md5"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
[[package]]
name = "memchr"
version = "2.5.0"
@ -725,6 +763,16 @@ version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "os_str_bytes"
version = "6.4.1"
@ -856,6 +904,16 @@ version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "rustix"
version = "0.36.8"
@ -881,8 +939,11 @@ dependencies = [
"crc32fast",
"ctrlc",
"encoding_rs",
"hex",
"image",
"md5",
"panic-message",
"rust-ini",
"serialport",
]

View File

@ -14,6 +14,9 @@ colored = "2.0.0"
crc32fast = "1.3.2"
ctrlc = "3.2.5"
encoding_rs = "0.8.32"
hex = "0.4.3"
image = "0.24.5"
md5 = "0.7.0"
panic-message = "0.3.0"
rust-ini = "0.18.0"
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 std::{
fs::File,
io::{self, Read, Write},
io::{self, BufReader, Read, Write},
path::PathBuf,
sync::{
atomic::{AtomicBool, Ordering},
@ -250,7 +250,8 @@ fn handle_upload_command(sn: Option<String>, args: &UploadArgs) -> Result<(), sc
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}]"), || {
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() {
save_type
} 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();

View File

@ -9,61 +9,71 @@ pub enum SaveType {
Flashram,
}
const HASH_CHUNK_LENGTH: usize = 64 * 1024;
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.read_exact(&mut header)?;
let pi_config = &header[0..4];
match pi_config {
[0x37, 0x80, 0x40, 0x12] => {
header.chunks_exact_mut(2).for_each(|c| c.swap(0, 1));
}
[0x40, 0x12, 0x37, 0x80] => {
header.chunks_exact_mut(4).for_each(|c| {
c.swap(0, 3);
c.swap(1, 2);
});
}
_ => {}
reader.seek(std::io::SeekFrom::Start(0x3C))?;
reader.read(&mut ed64_header)?;
if &ed64_header[0..2] == b"ED" {
return Ok(match ed64_header[3] >> 4 {
1 => SaveType::Eeprom4k,
2 => SaveType::Eeprom16k,
3 => SaveType::Sram,
4 => SaveType::SramBanked,
5 => SaveType::Flashram,
6 => SaveType::Sram,
_ => SaveType::None,
});
}
let rom_id = &header[0x3B..0x3E];
// let region = header[0x3E];
// let revision = header[0x3F];
let mut pi_config = vec![0u8; 4];
// TODO: fix this mess
reader.rewind()?;
reader.read(&mut pi_config)?;
if let Some(save_type) = match rom_id {
b"NTW" | b"NHF" | b"NOS" | b"NTC" | b"NER" | b"NAG" | b"NAB" | b"NS3" | b"NTN" | b"NBN"
| b"NBK" | b"NFH" | b"NMU" | b"NBC" | b"NBH" | b"NHA" | b"NBM" | b"NBV" | b"NBD"
| b"NCT" | b"NCH" | b"NCG" | b"NP2" | b"NXO" | b"NCU" | b"NCX" | b"NDY" | b"NDQ"
| b"NDR" | b"NN6" | b"NDU" | b"NJM" | b"NFW" | b"NF2" | b"NKA" | b"NFG" | b"NGL"
| b"NGV" | b"NGE" | b"NHP" | b"NPG" | b"NIJ" | b"NIC" | b"NFY" | b"NKI" | b"NLL"
| 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"
| 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),
b"NB7" | b"NGT" | b"NFU" | b"NCW" | b"NCZ" | b"ND6" | b"NDO" | b"ND2" | b"N3D" | b"NMX"
| 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),
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"
| b"NZL" | b"NKG" | b"NMF" | b"NRI" | b"NUT" | b"NUM" | b"NOB" | b"CPS" | b"NPM"
| b"NRE" | b"NAL" | b"NT3" | b"NS4" | b"NA2" | b"NVP" | b"NWL" | b"NW2" | b"NWX" => {
Some(SaveType::Sram)
let endian_swapper = match &pi_config[0..4] {
[0x37, 0x80, 0x40, 0x12] => |b: &mut [u8]| b.chunks_exact_mut(2).for_each(|c| c.swap(0, 1)),
[0x40, 0x12, 0x37, 0x80] => |b: &mut [u8]| {
b.chunks_exact_mut(4).for_each(|c| {
c.swap(0, 3);
c.swap(1, 2)
})
},
_ => |_: &mut [u8]| {},
};
let mut hasher = md5::Context::new();
let mut buffer = vec![0u8; HASH_CHUNK_LENGTH];
reader.rewind()?;
loop {
let chunk = reader.read(&mut buffer)?;
if chunk > 0 {
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" => {
Some(SaveType::Flashram)
}
let hash = hex::encode_upper(hasher.compute().0);
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)

View File

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