From 534fd6b254befc04c1ff4bf5a5cacc7f2c466eef Mon Sep 17 00:00:00 2001 From: Hyphen-ated Date: Sat, 11 Jun 2022 20:15:29 -0700 Subject: [PATCH 1/2] first pass at upload-latest-sfc it works but the rust is disgusting --- src/main.rs | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4423b9d..58149a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,8 +24,10 @@ use std::thread::sleep; use std::io::prelude::*; use std::fs::File; use std::fs; +use std::path::Path; use std::time::Duration; use scan_fmt::scan_fmt; +use crate::usb2snes::usb2snes::SyncClient; mod usb2snes; @@ -70,7 +72,25 @@ struct Opt { path_to_remove: Option, #[structopt(long = "devel", name = "Show all the transaction with the usb2snes server")] - devel: bool + devel: bool, + + #[structopt(subcommand)] + command: Option +} + +#[derive(StructOpt, Debug)] +enum Command { + #[structopt(name = "upload-latest-sfc", about = "Find the most recent .sfc file in local-source dir, and upload it to target-dir on the device")] + UploadLatestSfc { + #[structopt(name = "local-source-dir", help = "Directory on this computer to get the latest .sfc out of, e.g. your downloads folder")] + local_source_dir: String, + + #[structopt(name = "target-dir", help = "Directory on the device to put the .sfc into")] + target_dir: String, + + #[structopt(long = "wipe-target-dir", help = "Delete .sfc files in target-dir before copying a new one there")] + wipe_target_dir: bool + } } fn main() { @@ -162,9 +182,8 @@ fn main() { std::process::exit(1); } let local_path = opt.file_to_upload.unwrap(); - let data = fs::read(local_path).expect("Error opening the file or reading the content"); - let path = opt.path.unwrap(); - usb2snes.send_file(&path, data); + let snes_path = opt.path.unwrap(); + upload_file(local_path, snes_path, &mut usb2snes); } if opt.file_to_download != None { let path:String = opt.file_to_download.unwrap(); @@ -174,7 +193,7 @@ fn main() { let f = File::create(local_path); let mut f = match f { Ok(file) => file, - Err(err) => panic!("Probleme opening the file {:?} : {:?}", path, err), + Err(err) => panic!("Problem opening the file {:?} : {:?}", path, err), }; f.write_all(&data).expect("Can't write the data to the file"); } @@ -183,5 +202,67 @@ fn main() { println!("Removing : {:?}", path); usb2snes.remove_path(&path); } + match opt.command { + Some(Command::UploadLatestSfc {local_source_dir, target_dir, wipe_target_dir }) => { + do_upload_latest_sfc(&mut usb2snes, local_source_dir, target_dir, wipe_target_dir).unwrap(); + }, + None => {} + } + + } +} + +fn upload_file(local_path:String, snes_path:String, usb2snes: &mut SyncClient) { + print!("Sending file {} to snes at {}", local_path, snes_path); + let data = fs::read(local_path).expect("Error opening the file or reading the content"); + usb2snes.send_file(&snes_path, data); +} + +fn do_upload_latest_sfc(usb2snes: &mut SyncClient, local_source_dir:String, target_dir:String, wipe_target_dir:bool) + -> Result<(), Box> { + println!("Uploading latest sfc from {:?} to {:?}. with wipe-target-dir={:?}", + local_source_dir, + target_dir, + wipe_target_dir); + let local_dir_path = Path::new(&local_source_dir); + + let mut newest_seconds_since_mod = u64::MAX; + let mut newest_file_name:Option = None; + for entry in fs::read_dir(local_dir_path) + .expect(&format!("Can't read the given local dir {:?}", local_source_dir)) { + let entry = entry?; + + let file_path = entry.path(); + let f_name = entry.file_name().to_string_lossy().into_owned(); + if !f_name.ends_with(".sfc") { + continue + } + + let metadata = fs::metadata(&file_path)?; + let seconds_since_mod = metadata.modified()?.elapsed()?.as_secs(); + if seconds_since_mod < newest_seconds_since_mod { + newest_seconds_since_mod = seconds_since_mod; + newest_file_name = Some(f_name); + } } + let file_name_to_send = newest_file_name.expect("No sfc found in local dir"); + println!("Newest sfc file found: {:?}", file_name_to_send); + + if wipe_target_dir { + let roms = usb2snes.ls(&target_dir); + for rom in roms { + if rom.name.ends_with(".sfc") { + let snes_path = format!("{}/{}", target_dir, rom.name); + println!("Deleting snes file {}", snes_path); + usb2snes.remove_path(&snes_path); + } + } + + } + + let local_path:String = format!("{}/{}", local_source_dir, file_name_to_send); + let snes_path:String = format!("{}/{}", target_dir, file_name_to_send); + upload_file(local_path, snes_path, usb2snes); + + Ok(()) } From 069bdf3231c020cb09ec77d654a2c06a7221c834 Mon Sep 17 00:00:00 2001 From: Hyphen-ated Date: Sun, 12 Jun 2022 16:14:26 -0700 Subject: [PATCH 2/2] add a readme --- readme.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 readme.md diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..385feaf --- /dev/null +++ b/readme.md @@ -0,0 +1,33 @@ +This is a command line tool to interact with a SNES over USB, for example to transfer files to a flash cart's SD card. It has not been very thoroughly tested, so make sure you have backups of any important files on your SNES before using this. + +It requires you to be running a separate program to manage the SNES communication. You can use either: + +* [QUsb2Snes](https://skarsnik.github.io/QUsb2snes/) +* [SNI](https://github.com/alttpo/sni) (also included as part of Archipelago) + +## Installation +If you're on windows, get it from the sidebar on the right of this github page. + +Otherwise build it from source. + +## Usage + +`usb2snes-cli --help` for a description of all the available operations + +Things you can do include: listing/writing/deleting files on the device, launching a specific rom, resetting the current +game, and returning to the main menu. + +### upload-latest-sfc +This command lets you automatically select the newest .sfc file in some directory and send it to the device. +For example, you might use it like this: + +`usb2snes-cli --upload-latest-sfc c:/users//Downloads incoming --wipe-target-dir` + +This will take the newest sfc file in your Downloads directory and send it to the `incoming/` directory on the SNES. By including --wipe-target-dir, it makes it delete any other sfc files in `incoming/` + +You might find it convenient to have a shortcut that does this if you play a lot of randos and you want a quick one-button way to get your newest rando rom onto your console. + +## How to Build From Source +Install Rust from https://www.rust-lang.org/ + +Then do `cargo build` \ No newline at end of file