From 7e97ccaf4845d158b53d747352c66c75c61de836 Mon Sep 17 00:00:00 2001 From: modeco80 Date: Thu, 29 Jun 2023 00:10:18 -0400 Subject: [PATCH] jmrenamer: Add "unclear" mode This will allow transparent switching between clear names and .DAT names. --- crates/jmrenamer/Cargo.toml | 1 + crates/jmrenamer/src/main.rs | 103 ++++++++++++++++++++++++++++++++--- 2 files changed, 95 insertions(+), 9 deletions(-) diff --git a/crates/jmrenamer/Cargo.toml b/crates/jmrenamer/Cargo.toml index 62a666d..e65773e 100644 --- a/crates/jmrenamer/Cargo.toml +++ b/crates/jmrenamer/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] +clap = { version = "4.3.8", features = ["derive"] } jmmt = { path = "../jmmt" } diff --git a/crates/jmrenamer/src/main.rs b/crates/jmrenamer/src/main.rs index 3329b35..f97ca1f 100644 --- a/crates/jmrenamer/src/main.rs +++ b/crates/jmrenamer/src/main.rs @@ -6,16 +6,27 @@ use jmmt::hash::filename::*; use jmmt::read::package_toc::read_package_toc; use std::{fs, path::Path}; -// TODO: A mode that will re-name everything back? This wouldn't be too hard to implement +use clap::{Subcommand, Parser}; -fn main() { - // A relatively simple idiot-check. Later on utilities might have a shared library - // of code which validates game root stuff and can open it up/etc. - if !Path::new("DATA").is_dir() { - println!("This program should be run in the root of an extracted copy."); - return (); - } +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +#[command(propagate_version = true)] +struct Cli { + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand)] +enum Commands { + /// Rename the files in the DATA directory to the original filenames. + Clear, + + /// Rename the files to the .DAT filenames that the game expects. + Unclear, +} + +fn do_clear() { let package_toc_filename = format!("DATA/{}", dat_filename("package.toc")); match read_package_toc(Path::new(package_toc_filename.as_str()).to_path_buf()) { @@ -42,7 +53,7 @@ fn main() { return (); } }; - println!("moved {} -> {}", src_path.display(), dest_path.display()); + println!("Clearnamed {} -> {}", src_path.display(), dest_path.display()); } } @@ -64,3 +75,77 @@ fn main() { } } } + +fn do_unclear() { + let package_toc_filename = String::from("DATA/package.toc"); + + match read_package_toc(Path::new(package_toc_filename.as_str()).to_path_buf()) { + Ok(toc) => { + for toc_entry in toc { + + let dat_clearname = format!( + "DATA/{}", + toc_entry + .file_name() + .expect("How did invalid ASCII get here?") + ); + let src_path = Path::new(dat_clearname.as_str()); + + + let dat_dest = format!( + "DATA/{}", + dat_filename_from_hash(toc_entry.file_name_hash()) + ); + + let dest_path = Path::new(dat_dest.as_str()); + + if src_path.exists() { + match fs::rename(src_path, dest_path) { + Ok(_) => {} + Err(error) => { + println!("Error renaming {}: {}", src_path.display(), error); + return (); + } + }; + println!("Uncleared {} -> {}", src_path.display(), dest_path.display()); + } + } + + let package_toc_dat_filename = format!("DATA/{}", dat_filename("package.toc")); + match fs::rename( + Path::new("DATA/package.toc"), + Path::new(package_toc_dat_filename.as_str()), + ) { + Ok(_) => {} + Err(error) => { + println!("Error renaming TOC file: {}", error); + return (); + } + }; + } + + Err(error) => { + println!("Error reading package.toc file: {}", error); + return (); + } + } +} + +fn main() { + // A relatively simple idiot-check. Later on utilities might have a shared library + // of code which validates game root stuff and can open it up/etc. + if !Path::new("DATA").is_dir() { + println!("This program should be run in the root of an extracted copy."); + return (); + } + + let cli = Cli::parse(); + + + match &cli.command { + Commands::Clear => + do_clear(), + Commands::Unclear => + do_unclear() + } +}