diff --git a/src/args.rs b/src/args.rs index 0bbc356..bd2390f 100644 --- a/src/args.rs +++ b/src/args.rs @@ -3,7 +3,7 @@ use clap::{ArgAction, ArgGroup, Parser, Subcommand}; /// Tools for export and import scripts #[derive(Parser, Debug)] -#[clap(group = ArgGroup::new("encodingg").multiple(false), group = ArgGroup::new("output_encodingg").multiple(false))] +#[clap(group = ArgGroup::new("encodingg").multiple(false), group = ArgGroup::new("output_encodingg").multiple(false), group = ArgGroup::new("archive_encodingg").multiple(false))] #[command(version, about, long_about = None)] pub struct Arg { #[arg(short = 't', long, value_enum, global = true)] @@ -38,6 +38,25 @@ pub struct Arg { )] /// Output code page pub output_code_page: Option, + #[arg( + short = 'a', + long, + value_enum, + global = true, + group = "archive_encodingg" + )] + /// Archive filename encoding + pub archive_encoding: Option, + #[cfg(windows)] + #[arg( + short = 'A', + long, + value_enum, + global = true, + group = "archive_encodingg" + )] + /// Archive code page + pub archive_code_page: Option, #[arg(long, value_enum, global = true)] /// Circus Game pub circus_mes_type: Option, diff --git a/src/main.rs b/src/main.rs index 3e8103f..d6b1238 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,6 +34,33 @@ fn get_encoding( builder.default_encoding() } +fn get_archived_encoding( + arg: &args::Arg, + builder: &Box, + encoding: types::Encoding, +) -> types::Encoding { + match &arg.encoding { + Some(enc) => { + return match enc { + &types::TextEncoding::Default => builder.default_encoding(), + &types::TextEncoding::Auto => types::Encoding::Auto, + &types::TextEncoding::Cp932 => types::Encoding::Cp932, + &types::TextEncoding::Utf8 => types::Encoding::Utf8, + &types::TextEncoding::Gb2312 => types::Encoding::Gb2312, + }; + } + None => {} + } + #[cfg(windows)] + match &arg.code_page { + Some(code_page) => { + return types::Encoding::CodePage(*code_page); + } + None => {} + } + builder.default_archive_encoding().unwrap_or(encoding) +} + fn get_output_encoding(arg: &args::Arg) -> types::Encoding { match &arg.output_encoding { Some(enc) => { @@ -96,8 +123,14 @@ pub fn parse_script( for builder in scripts::BUILDER.iter() { if typ == builder.script_type() { let encoding = get_encoding(arg, builder); + let archive_encoding = get_archived_encoding(arg, builder, encoding); return Ok(( - builder.build_script_from_file(filename, encoding, config)?, + builder.build_script_from_file( + filename, + encoding, + archive_encoding, + config, + )?, builder, )); } @@ -123,8 +156,9 @@ pub fn parse_script( if exts_builder.len() == 1 { let builder = exts_builder.first().unwrap(); let encoding = get_encoding(arg, builder); + let archive_encoding = get_archived_encoding(arg, builder, encoding); return Ok(( - builder.build_script_from_file(filename, encoding, config)?, + builder.build_script_from_file(filename, encoding, archive_encoding, config)?, builder, )); } @@ -153,8 +187,9 @@ pub fn parse_script( if best_builders.len() == 1 { let builder = best_builders.first().unwrap(); let encoding = get_encoding(arg, builder); + let archive_encoding = get_archived_encoding(arg, builder, encoding); return Ok(( - builder.build_script_from_file(filename, encoding, config)?, + builder.build_script_from_file(filename, encoding, archive_encoding, config)?, builder, )); } @@ -194,8 +229,9 @@ pub fn parse_script_from_archive( if exts_builder.len() == 1 { let builder = exts_builder.first().unwrap(); let encoding = get_encoding(arg, builder); + let archive_encoding = get_archived_encoding(arg, builder, encoding); return Ok(( - builder.build_script(file.data().to_vec(), encoding, config)?, + builder.build_script(file.data().to_vec(), encoding, archive_encoding, config)?, builder, )); } @@ -218,8 +254,9 @@ pub fn parse_script_from_archive( if best_builders.len() == 1 { let builder = best_builders.first().unwrap(); let encoding = get_encoding(arg, builder); + let archive_encoding = get_archived_encoding(arg, builder, encoding); return Ok(( - builder.build_script(file.data().to_vec(), encoding, config)?, + builder.build_script(file.data().to_vec(), encoding, archive_encoding, config)?, builder, )); } diff --git a/src/scripts/base.rs b/src/scripts/base.rs index 23face3..fa68249 100644 --- a/src/scripts/base.rs +++ b/src/scripts/base.rs @@ -4,6 +4,10 @@ use anyhow::Result; pub trait ScriptBuilder: std::fmt::Debug { fn default_encoding(&self) -> Encoding; + fn default_archive_encoding(&self) -> Option { + None + } + fn default_patched_encoding(&self) -> Encoding { self.default_encoding() } @@ -12,6 +16,7 @@ pub trait ScriptBuilder: std::fmt::Debug { &self, buf: Vec, encoding: Encoding, + archive_encoding: Encoding, config: &ExtraConfig, ) -> Result>; @@ -19,10 +24,11 @@ pub trait ScriptBuilder: std::fmt::Debug { &self, filename: &str, encoding: Encoding, + archive_encoding: Encoding, config: &ExtraConfig, ) -> Result> { let data = crate::utils::files::read_file(filename)?; - self.build_script(data, encoding, config) + self.build_script(data, encoding, archive_encoding, config) } fn extensions(&self) -> &'static [&'static str]; diff --git a/src/scripts/bgi/script.rs b/src/scripts/bgi/script.rs index 0bfcb17..12dae28 100644 --- a/src/scripts/bgi/script.rs +++ b/src/scripts/bgi/script.rs @@ -22,6 +22,7 @@ impl ScriptBuilder for BGIScriptBuilder { &self, buf: Vec, encoding: Encoding, + _archive_encoding: Encoding, config: &ExtraConfig, ) -> Result> { Ok(Box::new(BGIScript::new(buf, encoding, config)?)) diff --git a/src/scripts/circus/script.rs b/src/scripts/circus/script.rs index 9ecee95..7a6d6cf 100644 --- a/src/scripts/circus/script.rs +++ b/src/scripts/circus/script.rs @@ -22,6 +22,7 @@ impl ScriptBuilder for CircusMesScriptBuilder { &self, buf: Vec, encoding: Encoding, + _archive_encoding: Encoding, config: &ExtraConfig, ) -> Result> { Ok(Box::new(CircusMesScript::new(buf, encoding, config)?)) diff --git a/src/scripts/escude/archive.rs b/src/scripts/escude/archive.rs index e8c380c..2f872a3 100644 --- a/src/scripts/escude/archive.rs +++ b/src/scripts/escude/archive.rs @@ -1,8 +1,8 @@ use super::crypto::*; +use crate::ext::io::*; use crate::scripts::base::*; use crate::types::*; use crate::utils::encoding::decode_to_string; -use crate::ext::io::*; use anyhow::Result; use std::io::{Read, Seek, SeekFrom}; @@ -20,15 +20,20 @@ impl ScriptBuilder for EscudeBinArchiveBuilder { Encoding::Cp932 } + fn default_archive_encoding(&self) -> Option { + Some(Encoding::Cp932) + } + fn build_script( &self, data: Vec, - encoding: Encoding, + _encoding: Encoding, + archive_encoding: Encoding, config: &ExtraConfig, ) -> Result> { Ok(Box::new(EscudeBinArchive::new( MemReader::new(data), - encoding, + archive_encoding, config, )?)) } @@ -36,16 +41,25 @@ impl ScriptBuilder for EscudeBinArchiveBuilder { fn build_script_from_file( &self, filename: &str, - encoding: Encoding, + _encoding: Encoding, + archive_encoding: Encoding, config: &ExtraConfig, ) -> Result> { if filename == "-" { let data = crate::utils::files::read_file(filename)?; - self.build_script(data, encoding, config) + Ok(Box::new(EscudeBinArchive::new( + MemReader::new(data), + archive_encoding, + config, + )?)) } else { let f = std::fs::File::open(filename)?; let reader = std::io::BufReader::new(f); - Ok(Box::new(EscudeBinArchive::new(reader, encoding, config)?)) + Ok(Box::new(EscudeBinArchive::new( + reader, + archive_encoding, + config, + )?)) } } @@ -101,11 +115,11 @@ pub struct EscudeBinArchive { file_count: u32, name_tbl_len: u32, entries: Vec, - encoding: Encoding, + archive_encoding: Encoding, } impl EscudeBinArchive { - pub fn new(mut reader: T, encoding: Encoding, _config: &ExtraConfig) -> Result { + pub fn new(mut reader: T, archive_encoding: Encoding, _config: &ExtraConfig) -> Result { let mut header = [0u8; 8]; reader.read_exact(&mut header)?; if &header != b"ESC-ARC2" { @@ -131,7 +145,7 @@ impl EscudeBinArchive { file_count, name_tbl_len, entries, - encoding, + archive_encoding, }) } } @@ -152,12 +166,11 @@ impl Script for EscudeBinArchive { fn iter_archive<'a>( &'a mut self, ) -> Result>> + 'a>> { - let encoding = self.encoding; Ok(Box::new(EscudeBinArchiveIterator { entries: self.entries.iter(), reader: &mut self.reader, - encoding, file_count: self.file_count, + archive_encoding: self.archive_encoding, })) } } @@ -165,8 +178,8 @@ impl Script for EscudeBinArchive { struct EscudeBinArchiveIterator<'a, T: Iterator, R: Read + Seek> { entries: T, reader: &'a mut R, - encoding: Encoding, file_count: u32, + archive_encoding: Encoding, } impl<'a, T: Iterator, R: Read + Seek> Iterator @@ -186,7 +199,7 @@ impl<'a, T: Iterator, R: Read + Seek> Iterator Ok(name) => name, Err(e) => return Some(Err(e.into())), }; - let name = match decode_to_string(self.encoding, name.as_bytes()) { + let name = match decode_to_string(self.archive_encoding, name.as_bytes()) { Ok(name) => name, Err(e) => return Some(Err(e.into())), }; diff --git a/src/scripts/escude/script.rs b/src/scripts/escude/script.rs index e984fd9..91f02cc 100644 --- a/src/scripts/escude/script.rs +++ b/src/scripts/escude/script.rs @@ -25,6 +25,7 @@ impl ScriptBuilder for EscudeBinScriptBuilder { &self, data: Vec, encoding: Encoding, + _archive_encoding: Encoding, config: &ExtraConfig, ) -> Result> { Ok(Box::new(EscudeBinScript::new(data, encoding, config)?))