mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2025-02-16 20:29:12 +01:00
added download save command
This commit is contained in:
parent
86435640dd
commit
90a79eccb8
@ -38,6 +38,9 @@ enum Commands {
|
|||||||
/// Upload ROM (and save) to the SC64
|
/// Upload ROM (and save) to the SC64
|
||||||
Upload(UploadArgs),
|
Upload(UploadArgs),
|
||||||
|
|
||||||
|
/// Download save and write it to file
|
||||||
|
DownloadSave(DownloadSaveArgs),
|
||||||
|
|
||||||
/// Upload ROM, 64DD IPL and run disk server
|
/// Upload ROM, 64DD IPL and run disk server
|
||||||
_64DD(_64DDArgs),
|
_64DD(_64DDArgs),
|
||||||
|
|
||||||
@ -89,6 +92,12 @@ struct UploadArgs {
|
|||||||
tv: Option<TvType>,
|
tv: Option<TvType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Args)]
|
||||||
|
struct DownloadSaveArgs {
|
||||||
|
/// Path to the save file
|
||||||
|
path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
struct _64DDArgs {
|
struct _64DDArgs {
|
||||||
/// Path to the ROM file
|
/// Path to the ROM file
|
||||||
@ -234,14 +243,15 @@ fn main() {
|
|||||||
|
|
||||||
fn handle_command(command: &Commands, sn: Option<String>) {
|
fn handle_command(command: &Commands, sn: Option<String>) {
|
||||||
let result = match command {
|
let result = match command {
|
||||||
|
Commands::List => handle_list_command(),
|
||||||
Commands::Upload(args) => handle_upload_command(sn, args),
|
Commands::Upload(args) => handle_upload_command(sn, args),
|
||||||
|
Commands::DownloadSave(args) => handle_download_save_command(sn, args),
|
||||||
Commands::_64DD(args) => handle_64dd_command(sn, args),
|
Commands::_64DD(args) => handle_64dd_command(sn, args),
|
||||||
Commands::Dump(args) => handle_dump_command(sn, args),
|
|
||||||
Commands::Debug(args) => handle_debug_command(sn, args),
|
Commands::Debug(args) => handle_debug_command(sn, args),
|
||||||
|
Commands::Dump(args) => handle_dump_command(sn, args),
|
||||||
Commands::Info => handle_info_command(sn),
|
Commands::Info => handle_info_command(sn),
|
||||||
Commands::Set { command } => handle_set_command(sn, command),
|
Commands::Set { command } => handle_set_command(sn, command),
|
||||||
Commands::Firmware { command } => handle_firmware_command(sn, command),
|
Commands::Firmware { command } => handle_firmware_command(sn, command),
|
||||||
Commands::List => handle_list_command(),
|
|
||||||
};
|
};
|
||||||
match result {
|
match result {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
@ -249,14 +259,25 @@ fn handle_command(command: &Commands, sn: Option<String>) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_list_command() -> Result<(), sc64::Error> {
|
||||||
|
let devices = sc64::list_serial_devices()?;
|
||||||
|
|
||||||
|
println!("{}", "Found devices:".bold());
|
||||||
|
for (i, d) in devices.iter().enumerate() {
|
||||||
|
println!(" {i}: {}", d.sn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_upload_command(sn: Option<String>, args: &UploadArgs) -> Result<(), sc64::Error> {
|
fn handle_upload_command(sn: Option<String>, args: &UploadArgs) -> Result<(), sc64::Error> {
|
||||||
let mut sc64 = init_sc64(sn, true)?;
|
let mut sc64 = init_sc64(sn, true)?;
|
||||||
|
|
||||||
sc64.reset_state()?;
|
|
||||||
|
|
||||||
let (rom_file_unbuffered, 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);
|
let mut rom_file = BufReader::new(rom_file_unbuffered);
|
||||||
|
|
||||||
|
sc64.reset_state()?;
|
||||||
|
|
||||||
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)
|
||||||
})?;
|
})?;
|
||||||
@ -306,6 +327,21 @@ fn handle_upload_command(sn: Option<String>, args: &UploadArgs) -> Result<(), sc
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_download_save_command(
|
||||||
|
sn: Option<String>,
|
||||||
|
args: &DownloadSaveArgs,
|
||||||
|
) -> Result<(), sc64::Error> {
|
||||||
|
let mut sc64 = init_sc64(sn, true)?;
|
||||||
|
|
||||||
|
let (mut file, name) = create_file(&args.path)?;
|
||||||
|
|
||||||
|
log_wait(format!("Downloading save [{name}]"), || {
|
||||||
|
sc64.download_save(&mut file)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_64dd_command(sn: Option<String>, args: &_64DDArgs) -> Result<(), sc64::Error> {
|
fn handle_64dd_command(sn: Option<String>, args: &_64DDArgs) -> Result<(), sc64::Error> {
|
||||||
let _ = (sn, args);
|
let _ = (sn, args);
|
||||||
|
|
||||||
@ -314,24 +350,7 @@ fn handle_64dd_command(sn: Option<String>, args: &_64DDArgs) -> Result<(), sc64:
|
|||||||
// TODO: print BIG warning to not use this mode together with real 64DD
|
// TODO: print BIG warning to not use this mode together with real 64DD
|
||||||
|
|
||||||
println!("{}", "Sorry nothing".yellow());
|
println!("{}", "Sorry nothing".yellow());
|
||||||
|
println!("{}", "64DD emulation not implemented yet".red());
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_dump_command(sn: Option<String>, args: &DumpArgs) -> Result<(), sc64::Error> {
|
|
||||||
let mut sc64 = init_sc64(sn, true)?;
|
|
||||||
|
|
||||||
let (mut dump_file, dump_name) = create_file(&args.path)?;
|
|
||||||
|
|
||||||
let data = log_wait(
|
|
||||||
format!(
|
|
||||||
"Dumping from [0x{:08X}] length [0x{:X}] to [{dump_name}]",
|
|
||||||
args.address, args.length
|
|
||||||
),
|
|
||||||
|| sc64.dump_memory(args.address, args.length),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
dump_file.write(&data)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -384,6 +403,24 @@ fn handle_debug_command(sn: Option<String>, args: &DebugArgs) -> Result<(), sc64
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_dump_command(sn: Option<String>, args: &DumpArgs) -> Result<(), sc64::Error> {
|
||||||
|
let mut sc64 = init_sc64(sn, true)?;
|
||||||
|
|
||||||
|
let (mut dump_file, dump_name) = create_file(&args.path)?;
|
||||||
|
|
||||||
|
let data = log_wait(
|
||||||
|
format!(
|
||||||
|
"Dumping from [0x{:08X}] length [0x{:X}] to [{dump_name}]",
|
||||||
|
args.address, args.length
|
||||||
|
),
|
||||||
|
|| sc64.dump_memory(args.address, args.length),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
dump_file.write(&data)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_info_command(sn: Option<String>) -> Result<(), sc64::Error> {
|
fn handle_info_command(sn: Option<String>) -> Result<(), sc64::Error> {
|
||||||
let mut sc64 = init_sc64(sn, false)?;
|
let mut sc64 = init_sc64(sn, false)?;
|
||||||
|
|
||||||
@ -509,17 +546,6 @@ fn handle_firmware_command(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_list_command() -> Result<(), sc64::Error> {
|
|
||||||
let devices = sc64::list_serial_devices()?;
|
|
||||||
|
|
||||||
println!("{}", "Found devices:".bold());
|
|
||||||
for (i, d) in devices.iter().enumerate() {
|
|
||||||
println!(" {i}: {}", d.sn);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init_sc64(sn: Option<String>, check_firmware: bool) -> Result<sc64::SC64, sc64::Error> {
|
fn init_sc64(sn: Option<String>, check_firmware: bool) -> Result<sc64::SC64, sc64::Error> {
|
||||||
let mut sc64 = sc64::new(sn)?;
|
let mut sc64 = sc64::new(sn)?;
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ use self::{
|
|||||||
};
|
};
|
||||||
use chrono::{DateTime, Local};
|
use chrono::{DateTime, Local};
|
||||||
use std::{
|
use std::{
|
||||||
io::{Read, Seek},
|
io::{Read, Seek, Write},
|
||||||
time::Instant,
|
time::Instant,
|
||||||
{cmp::min, time::Duration},
|
{cmp::min, time::Duration},
|
||||||
};
|
};
|
||||||
@ -413,6 +413,27 @@ impl SC64 {
|
|||||||
self.memory_write_chunked(reader, address, save_length, None)
|
self.memory_write_chunked(reader, address, save_length, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn download_save<T: Write>(&mut self, writer: &mut T) -> Result<(), Error> {
|
||||||
|
let save_type = get_config!(self, SaveType)?;
|
||||||
|
|
||||||
|
let (address, save_length) = match save_type {
|
||||||
|
SaveType::None => {
|
||||||
|
return Err(Error::new("No save type is enabled"));
|
||||||
|
}
|
||||||
|
SaveType::Eeprom4k => (EEPROM_ADDRESS, EEPROM_4K_LENGTH),
|
||||||
|
SaveType::Eeprom16k => (EEPROM_ADDRESS, EEPROM_16K_LENGTH),
|
||||||
|
SaveType::Sram => (SAVE_ADDRESS, SRAM_LENGTH),
|
||||||
|
SaveType::SramBanked => (SAVE_ADDRESS, SRAM_BANKED_LENGTH),
|
||||||
|
SaveType::Flashram => (SAVE_ADDRESS, FLASHRAM_LENGTH),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut data = self.command_memory_read(address, save_length)?;
|
||||||
|
|
||||||
|
writer.write_all(&mut data)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn dump_memory(&mut self, address: u32, length: usize) -> Result<Vec<u8>, Error> {
|
pub fn dump_memory(&mut self, address: u32, length: usize) -> Result<Vec<u8>, Error> {
|
||||||
if address + length as u32 > MEMORY_LENGTH as u32 {
|
if address + length as u32 > MEMORY_LENGTH as u32 {
|
||||||
return Err(Error::new("Invalid dump address or length"));
|
return Err(Error::new("Invalid dump address or length"));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user