mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-07-08 01:31:53 +08:00
Added a new command option archive-encoding
This commit is contained in:
21
src/args.rs
21
src/args.rs
@@ -3,7 +3,7 @@ use clap::{ArgAction, ArgGroup, Parser, Subcommand};
|
|||||||
|
|
||||||
/// Tools for export and import scripts
|
/// Tools for export and import scripts
|
||||||
#[derive(Parser, Debug)]
|
#[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)]
|
#[command(version, about, long_about = None)]
|
||||||
pub struct Arg {
|
pub struct Arg {
|
||||||
#[arg(short = 't', long, value_enum, global = true)]
|
#[arg(short = 't', long, value_enum, global = true)]
|
||||||
@@ -38,6 +38,25 @@ pub struct Arg {
|
|||||||
)]
|
)]
|
||||||
/// Output code page
|
/// Output code page
|
||||||
pub output_code_page: Option<u32>,
|
pub output_code_page: Option<u32>,
|
||||||
|
#[arg(
|
||||||
|
short = 'a',
|
||||||
|
long,
|
||||||
|
value_enum,
|
||||||
|
global = true,
|
||||||
|
group = "archive_encodingg"
|
||||||
|
)]
|
||||||
|
/// Archive filename encoding
|
||||||
|
pub archive_encoding: Option<TextEncoding>,
|
||||||
|
#[cfg(windows)]
|
||||||
|
#[arg(
|
||||||
|
short = 'A',
|
||||||
|
long,
|
||||||
|
value_enum,
|
||||||
|
global = true,
|
||||||
|
group = "archive_encodingg"
|
||||||
|
)]
|
||||||
|
/// Archive code page
|
||||||
|
pub archive_code_page: Option<u32>,
|
||||||
#[arg(long, value_enum, global = true)]
|
#[arg(long, value_enum, global = true)]
|
||||||
/// Circus Game
|
/// Circus Game
|
||||||
pub circus_mes_type: Option<CircusMesType>,
|
pub circus_mes_type: Option<CircusMesType>,
|
||||||
|
|||||||
47
src/main.rs
47
src/main.rs
@@ -34,6 +34,33 @@ fn get_encoding(
|
|||||||
builder.default_encoding()
|
builder.default_encoding()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_archived_encoding(
|
||||||
|
arg: &args::Arg,
|
||||||
|
builder: &Box<dyn scripts::ScriptBuilder + Send + Sync>,
|
||||||
|
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 {
|
fn get_output_encoding(arg: &args::Arg) -> types::Encoding {
|
||||||
match &arg.output_encoding {
|
match &arg.output_encoding {
|
||||||
Some(enc) => {
|
Some(enc) => {
|
||||||
@@ -96,8 +123,14 @@ pub fn parse_script(
|
|||||||
for builder in scripts::BUILDER.iter() {
|
for builder in scripts::BUILDER.iter() {
|
||||||
if typ == builder.script_type() {
|
if typ == builder.script_type() {
|
||||||
let encoding = get_encoding(arg, builder);
|
let encoding = get_encoding(arg, builder);
|
||||||
|
let archive_encoding = get_archived_encoding(arg, builder, encoding);
|
||||||
return Ok((
|
return Ok((
|
||||||
builder.build_script_from_file(filename, encoding, config)?,
|
builder.build_script_from_file(
|
||||||
|
filename,
|
||||||
|
encoding,
|
||||||
|
archive_encoding,
|
||||||
|
config,
|
||||||
|
)?,
|
||||||
builder,
|
builder,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -123,8 +156,9 @@ pub fn parse_script(
|
|||||||
if exts_builder.len() == 1 {
|
if exts_builder.len() == 1 {
|
||||||
let builder = exts_builder.first().unwrap();
|
let builder = exts_builder.first().unwrap();
|
||||||
let encoding = get_encoding(arg, builder);
|
let encoding = get_encoding(arg, builder);
|
||||||
|
let archive_encoding = get_archived_encoding(arg, builder, encoding);
|
||||||
return Ok((
|
return Ok((
|
||||||
builder.build_script_from_file(filename, encoding, config)?,
|
builder.build_script_from_file(filename, encoding, archive_encoding, config)?,
|
||||||
builder,
|
builder,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -153,8 +187,9 @@ pub fn parse_script(
|
|||||||
if best_builders.len() == 1 {
|
if best_builders.len() == 1 {
|
||||||
let builder = best_builders.first().unwrap();
|
let builder = best_builders.first().unwrap();
|
||||||
let encoding = get_encoding(arg, builder);
|
let encoding = get_encoding(arg, builder);
|
||||||
|
let archive_encoding = get_archived_encoding(arg, builder, encoding);
|
||||||
return Ok((
|
return Ok((
|
||||||
builder.build_script_from_file(filename, encoding, config)?,
|
builder.build_script_from_file(filename, encoding, archive_encoding, config)?,
|
||||||
builder,
|
builder,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -194,8 +229,9 @@ pub fn parse_script_from_archive(
|
|||||||
if exts_builder.len() == 1 {
|
if exts_builder.len() == 1 {
|
||||||
let builder = exts_builder.first().unwrap();
|
let builder = exts_builder.first().unwrap();
|
||||||
let encoding = get_encoding(arg, builder);
|
let encoding = get_encoding(arg, builder);
|
||||||
|
let archive_encoding = get_archived_encoding(arg, builder, encoding);
|
||||||
return Ok((
|
return Ok((
|
||||||
builder.build_script(file.data().to_vec(), encoding, config)?,
|
builder.build_script(file.data().to_vec(), encoding, archive_encoding, config)?,
|
||||||
builder,
|
builder,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -218,8 +254,9 @@ pub fn parse_script_from_archive(
|
|||||||
if best_builders.len() == 1 {
|
if best_builders.len() == 1 {
|
||||||
let builder = best_builders.first().unwrap();
|
let builder = best_builders.first().unwrap();
|
||||||
let encoding = get_encoding(arg, builder);
|
let encoding = get_encoding(arg, builder);
|
||||||
|
let archive_encoding = get_archived_encoding(arg, builder, encoding);
|
||||||
return Ok((
|
return Ok((
|
||||||
builder.build_script(file.data().to_vec(), encoding, config)?,
|
builder.build_script(file.data().to_vec(), encoding, archive_encoding, config)?,
|
||||||
builder,
|
builder,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ use anyhow::Result;
|
|||||||
pub trait ScriptBuilder: std::fmt::Debug {
|
pub trait ScriptBuilder: std::fmt::Debug {
|
||||||
fn default_encoding(&self) -> Encoding;
|
fn default_encoding(&self) -> Encoding;
|
||||||
|
|
||||||
|
fn default_archive_encoding(&self) -> Option<Encoding> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn default_patched_encoding(&self) -> Encoding {
|
fn default_patched_encoding(&self) -> Encoding {
|
||||||
self.default_encoding()
|
self.default_encoding()
|
||||||
}
|
}
|
||||||
@@ -12,6 +16,7 @@ pub trait ScriptBuilder: std::fmt::Debug {
|
|||||||
&self,
|
&self,
|
||||||
buf: Vec<u8>,
|
buf: Vec<u8>,
|
||||||
encoding: Encoding,
|
encoding: Encoding,
|
||||||
|
archive_encoding: Encoding,
|
||||||
config: &ExtraConfig,
|
config: &ExtraConfig,
|
||||||
) -> Result<Box<dyn Script>>;
|
) -> Result<Box<dyn Script>>;
|
||||||
|
|
||||||
@@ -19,10 +24,11 @@ pub trait ScriptBuilder: std::fmt::Debug {
|
|||||||
&self,
|
&self,
|
||||||
filename: &str,
|
filename: &str,
|
||||||
encoding: Encoding,
|
encoding: Encoding,
|
||||||
|
archive_encoding: Encoding,
|
||||||
config: &ExtraConfig,
|
config: &ExtraConfig,
|
||||||
) -> Result<Box<dyn Script>> {
|
) -> Result<Box<dyn Script>> {
|
||||||
let data = crate::utils::files::read_file(filename)?;
|
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];
|
fn extensions(&self) -> &'static [&'static str];
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ impl ScriptBuilder for BGIScriptBuilder {
|
|||||||
&self,
|
&self,
|
||||||
buf: Vec<u8>,
|
buf: Vec<u8>,
|
||||||
encoding: Encoding,
|
encoding: Encoding,
|
||||||
|
_archive_encoding: Encoding,
|
||||||
config: &ExtraConfig,
|
config: &ExtraConfig,
|
||||||
) -> Result<Box<dyn Script>> {
|
) -> Result<Box<dyn Script>> {
|
||||||
Ok(Box::new(BGIScript::new(buf, encoding, config)?))
|
Ok(Box::new(BGIScript::new(buf, encoding, config)?))
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ impl ScriptBuilder for CircusMesScriptBuilder {
|
|||||||
&self,
|
&self,
|
||||||
buf: Vec<u8>,
|
buf: Vec<u8>,
|
||||||
encoding: Encoding,
|
encoding: Encoding,
|
||||||
|
_archive_encoding: Encoding,
|
||||||
config: &ExtraConfig,
|
config: &ExtraConfig,
|
||||||
) -> Result<Box<dyn Script>> {
|
) -> Result<Box<dyn Script>> {
|
||||||
Ok(Box::new(CircusMesScript::new(buf, encoding, config)?))
|
Ok(Box::new(CircusMesScript::new(buf, encoding, config)?))
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use super::crypto::*;
|
use super::crypto::*;
|
||||||
|
use crate::ext::io::*;
|
||||||
use crate::scripts::base::*;
|
use crate::scripts::base::*;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
use crate::utils::encoding::decode_to_string;
|
use crate::utils::encoding::decode_to_string;
|
||||||
use crate::ext::io::*;
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
|
||||||
@@ -20,15 +20,20 @@ impl ScriptBuilder for EscudeBinArchiveBuilder {
|
|||||||
Encoding::Cp932
|
Encoding::Cp932
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_archive_encoding(&self) -> Option<Encoding> {
|
||||||
|
Some(Encoding::Cp932)
|
||||||
|
}
|
||||||
|
|
||||||
fn build_script(
|
fn build_script(
|
||||||
&self,
|
&self,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
encoding: Encoding,
|
_encoding: Encoding,
|
||||||
|
archive_encoding: Encoding,
|
||||||
config: &ExtraConfig,
|
config: &ExtraConfig,
|
||||||
) -> Result<Box<dyn Script>> {
|
) -> Result<Box<dyn Script>> {
|
||||||
Ok(Box::new(EscudeBinArchive::new(
|
Ok(Box::new(EscudeBinArchive::new(
|
||||||
MemReader::new(data),
|
MemReader::new(data),
|
||||||
encoding,
|
archive_encoding,
|
||||||
config,
|
config,
|
||||||
)?))
|
)?))
|
||||||
}
|
}
|
||||||
@@ -36,16 +41,25 @@ impl ScriptBuilder for EscudeBinArchiveBuilder {
|
|||||||
fn build_script_from_file(
|
fn build_script_from_file(
|
||||||
&self,
|
&self,
|
||||||
filename: &str,
|
filename: &str,
|
||||||
encoding: Encoding,
|
_encoding: Encoding,
|
||||||
|
archive_encoding: Encoding,
|
||||||
config: &ExtraConfig,
|
config: &ExtraConfig,
|
||||||
) -> Result<Box<dyn Script>> {
|
) -> Result<Box<dyn Script>> {
|
||||||
if filename == "-" {
|
if filename == "-" {
|
||||||
let data = crate::utils::files::read_file(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 {
|
} else {
|
||||||
let f = std::fs::File::open(filename)?;
|
let f = std::fs::File::open(filename)?;
|
||||||
let reader = std::io::BufReader::new(f);
|
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<T: Read + Seek + std::fmt::Debug> {
|
|||||||
file_count: u32,
|
file_count: u32,
|
||||||
name_tbl_len: u32,
|
name_tbl_len: u32,
|
||||||
entries: Vec<BinEntry>,
|
entries: Vec<BinEntry>,
|
||||||
encoding: Encoding,
|
archive_encoding: Encoding,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Read + Seek + std::fmt::Debug> EscudeBinArchive<T> {
|
impl<T: Read + Seek + std::fmt::Debug> EscudeBinArchive<T> {
|
||||||
pub fn new(mut reader: T, encoding: Encoding, _config: &ExtraConfig) -> Result<Self> {
|
pub fn new(mut reader: T, archive_encoding: Encoding, _config: &ExtraConfig) -> Result<Self> {
|
||||||
let mut header = [0u8; 8];
|
let mut header = [0u8; 8];
|
||||||
reader.read_exact(&mut header)?;
|
reader.read_exact(&mut header)?;
|
||||||
if &header != b"ESC-ARC2" {
|
if &header != b"ESC-ARC2" {
|
||||||
@@ -131,7 +145,7 @@ impl<T: Read + Seek + std::fmt::Debug> EscudeBinArchive<T> {
|
|||||||
file_count,
|
file_count,
|
||||||
name_tbl_len,
|
name_tbl_len,
|
||||||
entries,
|
entries,
|
||||||
encoding,
|
archive_encoding,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,12 +166,11 @@ impl<T: Read + Seek + std::fmt::Debug> Script for EscudeBinArchive<T> {
|
|||||||
fn iter_archive<'a>(
|
fn iter_archive<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
) -> Result<Box<dyn Iterator<Item = Result<Box<dyn ArchiveContent>>> + 'a>> {
|
) -> Result<Box<dyn Iterator<Item = Result<Box<dyn ArchiveContent>>> + 'a>> {
|
||||||
let encoding = self.encoding;
|
|
||||||
Ok(Box::new(EscudeBinArchiveIterator {
|
Ok(Box::new(EscudeBinArchiveIterator {
|
||||||
entries: self.entries.iter(),
|
entries: self.entries.iter(),
|
||||||
reader: &mut self.reader,
|
reader: &mut self.reader,
|
||||||
encoding,
|
|
||||||
file_count: self.file_count,
|
file_count: self.file_count,
|
||||||
|
archive_encoding: self.archive_encoding,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,8 +178,8 @@ impl<T: Read + Seek + std::fmt::Debug> Script for EscudeBinArchive<T> {
|
|||||||
struct EscudeBinArchiveIterator<'a, T: Iterator<Item = &'a BinEntry>, R: Read + Seek> {
|
struct EscudeBinArchiveIterator<'a, T: Iterator<Item = &'a BinEntry>, R: Read + Seek> {
|
||||||
entries: T,
|
entries: T,
|
||||||
reader: &'a mut R,
|
reader: &'a mut R,
|
||||||
encoding: Encoding,
|
|
||||||
file_count: u32,
|
file_count: u32,
|
||||||
|
archive_encoding: Encoding,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Iterator<Item = &'a BinEntry>, R: Read + Seek> Iterator
|
impl<'a, T: Iterator<Item = &'a BinEntry>, R: Read + Seek> Iterator
|
||||||
@@ -186,7 +199,7 @@ impl<'a, T: Iterator<Item = &'a BinEntry>, R: Read + Seek> Iterator
|
|||||||
Ok(name) => name,
|
Ok(name) => name,
|
||||||
Err(e) => return Some(Err(e.into())),
|
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,
|
Ok(name) => name,
|
||||||
Err(e) => return Some(Err(e.into())),
|
Err(e) => return Some(Err(e.into())),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ impl ScriptBuilder for EscudeBinScriptBuilder {
|
|||||||
&self,
|
&self,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
encoding: Encoding,
|
encoding: Encoding,
|
||||||
|
_archive_encoding: Encoding,
|
||||||
config: &ExtraConfig,
|
config: &ExtraConfig,
|
||||||
) -> Result<Box<dyn Script>> {
|
) -> Result<Box<dyn Script>> {
|
||||||
Ok(Box::new(EscudeBinScript::new(data, encoding, config)?))
|
Ok(Box::new(EscudeBinScript::new(data, encoding, config)?))
|
||||||
|
|||||||
Reference in New Issue
Block a user