This commit is contained in:
Mateusz Faderewski 2023-03-03 17:01:14 +01:00
parent 6d3d807d39
commit ad4f4db137
4 changed files with 286 additions and 68 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,11 @@
use crate::sc64; use crate::sc64;
use chrono::Local; use chrono::Local;
use colored::Colorize;
use panic_message::panic_message;
use std::{ use std::{
io::{ErrorKind, Read, Write}, io::{ErrorKind, Read, Write},
net::{TcpListener, TcpStream}, net::{TcpListener, TcpStream},
panic,
sync::mpsc::{channel, Receiver, Sender}, sync::mpsc::{channel, Receiver, Sender},
thread::{sleep, spawn}, thread::{sleep, spawn},
time::Duration, time::Duration,
@ -77,7 +80,7 @@ impl Handler {
let filename = &self.generate_filename("binaryout", "bin"); let filename = &self.generate_filename("binaryout", "bin");
let mut file = std::fs::File::create(filename)?; let mut file = std::fs::File::create(filename)?;
file.write_all(data)?; file.write_all(data)?;
println!("Wrote {} bytes to {}", data.len(), filename); println!("Wrote {} bytes to [{}]", data.len(), filename);
Ok(()) Ok(())
} }
@ -89,7 +92,7 @@ impl Handler {
fn handle_datatype_screenshot(&mut self, _data: &[u8]) -> Result<(), sc64::Error> { fn handle_datatype_screenshot(&mut self, _data: &[u8]) -> Result<(), sc64::Error> {
if let Some(header) = self.header.take() { if let Some(header) = self.header.take() {
// TODO: support screenshot datatype // TODO: support screenshot datatype
println!("Screenshot datatype not supported yet {:?}", header); println!("Screenshot datatype not supported yet {:02X?}", header);
} else { } else {
println!("Got screenshot packet without header data"); println!("Got screenshot packet without header data");
} }
@ -130,7 +133,7 @@ pub fn new(gdb_port: Option<u16>) -> Result<Handler, sc64::Error> {
listener.set_nonblocking(true).map_err(|_| { listener.set_nonblocking(true).map_err(|_| {
sc64::Error::new("Couldn't set GDB TCP socket listener as non-blocking") sc64::Error::new("Couldn't set GDB TCP socket listener as non-blocking")
})?; })?;
spawn(move || gdb_loop(listener, gdb_loop_tx, gdb_loop_rx)); spawn(move || gdb_thread(listener, gdb_loop_tx, gdb_loop_rx));
} }
Ok(Handler { Ok(Handler {
@ -140,6 +143,15 @@ pub fn new(gdb_port: Option<u16>) -> Result<Handler, sc64::Error> {
}) })
} }
fn gdb_thread(listener: TcpListener, gdb_tx: Sender<Vec<u8>>, gdb_rx: Receiver<Vec<u8>>) {
match panic::catch_unwind(|| gdb_loop(listener, gdb_tx, gdb_rx)) {
Ok(_) => {}
Err(payload) => {
eprintln!("{}", panic_message(&payload).red());
}
};
}
fn gdb_loop(listener: TcpListener, gdb_tx: Sender<Vec<u8>>, gdb_rx: Receiver<Vec<u8>>) { fn gdb_loop(listener: TcpListener, gdb_tx: Sender<Vec<u8>>, gdb_rx: Receiver<Vec<u8>>) {
for tcp_stream in listener.incoming() { for tcp_stream in listener.incoming() {
match tcp_stream { match tcp_stream {

View File

@ -217,7 +217,10 @@ impl From<TvType> for sc64::TvType {
fn main() { fn main() {
let cli = Cli::parse(); let cli = Cli::parse();
panic::set_hook(Box::new(|_| {})); #[cfg(not(debug_assertions))]
{
panic::set_hook(Box::new(|_| {}));
}
match panic::catch_unwind(|| handle_command(&cli.command, cli.sn)) { match panic::catch_unwind(|| handle_command(&cli.command, cli.sn)) {
Ok(_) => {} Ok(_) => {}
@ -260,10 +263,11 @@ 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 {
log_wait(format!("Calculating ROM hash"), || { let (save_type, name) = n64::guess_save_type(&mut rom_file)?;
n64::guess_save_type(&mut rom_file) if let Some(name) = name {
})? println!("Detected ROM name: {name}");
.into() };
save_type.into()
}; };
let save_type: sc64::SaveType = save.into(); let save_type: sc64::SaveType = save.into();
@ -362,6 +366,7 @@ fn handle_debug_command(sn: Option<String>, args: &DebugArgs) -> Result<(), sc64
} else if let Some(gdb_packet) = debug_handler.receive_gdb_packet() { } else if let Some(gdb_packet) = debug_handler.receive_gdb_packet() {
sc64.send_debug_packet(gdb_packet)?; sc64.send_debug_packet(gdb_packet)?;
} else { } else {
// TODO: handle user input
thread::sleep(Duration::from_millis(1)); thread::sleep(Duration::from_millis(1));
} }
} }

View File

@ -9,23 +9,29 @@ pub enum SaveType {
Flashram, Flashram,
} }
const HASH_CHUNK_LENGTH: usize = 64 * 1024; const HASH_CHUNK_LENGTH: usize = 256 * 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, Option<String>), Error> {
let mut ed64_header = vec![0u8; 4]; let mut ed64_header = vec![0u8; 4];
reader.seek(std::io::SeekFrom::Start(0x3C))?; reader.seek(std::io::SeekFrom::Start(0x3C))?;
reader.read(&mut ed64_header)?; reader.read(&mut ed64_header)?;
if &ed64_header[0..2] == b"ED" { if &ed64_header[0..2] == b"ED" {
return Ok(match ed64_header[3] >> 4 { return Ok((
1 => SaveType::Eeprom4k, match ed64_header[3] >> 4 {
2 => SaveType::Eeprom16k, 1 => SaveType::Eeprom4k,
3 => SaveType::Sram, 2 => SaveType::Eeprom16k,
4 => SaveType::SramBanked, 3 => SaveType::Sram,
5 => SaveType::Flashram, 4 => SaveType::SramBanked,
6 => SaveType::Sram, 5 => SaveType::Flashram,
_ => SaveType::None, 6 => SaveType::Sram,
}); _ => SaveType::None,
},
None,
));
} }
let mut pi_config = vec![0u8; 4]; let mut pi_config = vec![0u8; 4];
@ -48,7 +54,6 @@ pub fn guess_save_type<T: Read + Seek>(reader: &mut T) -> Result<SaveType, Error
let mut buffer = vec![0u8; HASH_CHUNK_LENGTH]; let mut buffer = vec![0u8; HASH_CHUNK_LENGTH];
reader.rewind()?; reader.rewind()?;
loop { loop {
let chunk = reader.read(&mut buffer)?; let chunk = reader.read(&mut buffer)?;
if chunk > 0 { if chunk > 0 {
@ -66,15 +71,18 @@ pub fn guess_save_type<T: Read + Seek>(reader: &mut T) -> Result<SaveType, Error
.expect("Error during mupen64plus.ini parse operation"); .expect("Error during mupen64plus.ini parse operation");
if let Some(section) = database.section(Some(hash)) { if let Some(section) = database.section(Some(hash)) {
if let Some(save_type) = section.get("SaveType") { if let Some(save_type) = section.get("SaveType") {
return Ok(match save_type { return Ok((
"Eeprom 4KB" => SaveType::Eeprom4k, match save_type {
"Eeprom 16KB" => SaveType::Eeprom16k, "Eeprom 4KB" => SaveType::Eeprom4k,
"SRAM" => SaveType::Sram, "Eeprom 16KB" => SaveType::Eeprom16k,
"Flash RAM" => SaveType::Flashram, "SRAM" => SaveType::Sram,
_ => SaveType::None, "Flash RAM" => SaveType::Flashram,
}); _ => SaveType::None,
},
section.get("GoodName").map(|s| s.to_string()),
));
} }
} }
Ok(SaveType::None) Ok((SaveType::None, None))
} }