Allow custom min len header

This commit is contained in:
2025-08-06 22:48:40 +08:00
parent 226ac24844
commit dcba086021
11 changed files with 52 additions and 19 deletions

View File

@@ -61,6 +61,7 @@ impl ScriptBuilder for ArtemisAsbBuilder {
writer: Box<dyn WriteSeek + 'a>,
encoding: Encoding,
file_encoding: Encoding,
_config: &ExtraConfig,
) -> Result<()> {
create_file(filename, writer, encoding, file_encoding)
}

View File

@@ -94,6 +94,7 @@ pub trait ScriptBuilder: std::fmt::Debug {
_writer: Box<dyn WriteSeek + 'a>,
_encoding: Encoding,
_file_encoding: Encoding,
_config: &ExtraConfig,
) -> Result<()> {
Err(anyhow::anyhow!(
"This script type does not support creating directly."
@@ -106,10 +107,11 @@ pub trait ScriptBuilder: std::fmt::Debug {
output_filename: &str,
encoding: Encoding,
file_encoding: Encoding,
config: &ExtraConfig,
) -> Result<()> {
let f = std::fs::File::create(output_filename)?;
let f = std::io::BufWriter::new(f);
self.create_file(filename, Box::new(f), encoding, file_encoding)
self.create_file(filename, Box::new(f), encoding, file_encoding, config)
}
#[cfg(feature = "image")]

View File

@@ -401,16 +401,18 @@ pub struct DscEncoder<'a, T: Write + Seek> {
magic: u32,
key: u32,
dec_count: u32,
min_len: usize,
}
impl<'a, T: Write + Seek> DscEncoder<'a, T> {
pub fn new(writer: &'a mut T) -> Self {
pub fn new(writer: &'a mut T, min_len: usize) -> Self {
let stream = MsbBitWriter::new(writer);
DscEncoder {
stream,
magic: 0x5344 << 16, // "DS"
key: rand::rng().random(),
dec_count: 0,
min_len,
}
}
@@ -419,7 +421,6 @@ impl<'a, T: Write + Seek> DscEncoder<'a, T> {
let mut ops = vec![];
let mut pos = 0;
const MIN_LEN: usize = 2;
const MAX_LEN: usize = 257;
const WINDOW_SIZE: usize = 4097;
@@ -431,7 +432,7 @@ impl<'a, T: Write + Seek> DscEncoder<'a, T> {
let mut best_len = 0;
let mut best_offset = 0;
if max_len >= MIN_LEN {
if max_len >= self.min_len {
let limit = pos.saturating_sub(WINDOW_SIZE);
let key = (data[pos] as u16) << 8 | data[pos + 1] as u16;
let mut match_pos_i32 = head[key as usize];
@@ -463,7 +464,7 @@ impl<'a, T: Write + Seek> DscEncoder<'a, T> {
}
}
if best_len >= MIN_LEN && best_offset >= 2 {
if best_len >= self.min_len && best_offset >= 2 {
ops.push(LzssOp::Match {
len: best_len as u16,
offset: best_offset as u16,
@@ -574,10 +575,10 @@ impl ScriptBuilder for DscBuilder {
_filename: &str,
_encoding: Encoding,
_archive_encoding: Encoding,
_config: &ExtraConfig,
config: &ExtraConfig,
_archive: Option<&Box<dyn Script>>,
) -> Result<Box<dyn Script>> {
Ok(Box::new(Dsc::new(buf)?))
Ok(Box::new(Dsc::new(buf, config)?))
}
fn extensions(&self) -> &'static [&'static str] {
@@ -605,8 +606,9 @@ impl ScriptBuilder for DscBuilder {
mut writer: Box<dyn WriteSeek + 'a>,
_encoding: Encoding,
_file_encoding: Encoding,
config: &ExtraConfig,
) -> Result<()> {
let encoder = DscEncoder::new(&mut writer);
let encoder = DscEncoder::new(&mut writer, config.bgi_compress_min_len);
let data = crate::utils::files::read_file(filename)?;
encoder.pack(&data)?;
Ok(())
@@ -616,16 +618,20 @@ impl ScriptBuilder for DscBuilder {
#[derive(Debug)]
pub struct Dsc {
data: Vec<u8>,
min_len: usize,
}
impl Dsc {
pub fn new(buf: Vec<u8>) -> Result<Self> {
pub fn new(buf: Vec<u8>, config: &ExtraConfig) -> Result<Self> {
if buf.len() < 16 || !buf.starts_with(b"DSC FORMAT 1.00\0") {
return Err(anyhow::anyhow!("Invalid DSC format"));
}
let decoder = DscDecoder::new(&buf)?;
let data = decoder.unpack()?;
Ok(Dsc { data })
Ok(Dsc {
data,
min_len: config.bgi_compress_min_len,
})
}
}
@@ -659,9 +665,13 @@ impl Script for Dsc {
_encoding: Encoding,
_output_encoding: Encoding,
) -> Result<()> {
let encoder = DscEncoder::new(&mut file);
let encoder = DscEncoder::new(&mut file, self.min_len);
let data = crate::utils::files::read_file(custom_filename)?;
encoder.pack(&data)?;
Ok(())
}
}
pub fn parse_min_length(len: &str) -> Result<usize, String> {
clap_num::number_range(len, 2, 256)
}

View File

@@ -512,6 +512,7 @@ pub struct BgiArchiveWriter<T: Write + Seek> {
headers: HashMap<String, BgiFileHeader>,
compress_file: bool,
encoding: Encoding,
min_len: usize,
}
impl<T: Write + Seek> BgiArchiveWriter<T> {
@@ -540,6 +541,7 @@ impl<T: Write + Seek> BgiArchiveWriter<T> {
headers,
compress_file: config.bgi_compress_file,
encoding,
min_len: config.bgi_compress_min_len,
})
}
}
@@ -561,7 +563,7 @@ impl<T: Write + Seek> Archive for BgiArchiveWriter<T> {
pos: 0,
};
Ok(if self.compress_file {
Box::new(BgiArchiveFileWithDsc::new(file))
Box::new(BgiArchiveFileWithDsc::new(file, self.min_len))
} else {
Box::new(file)
})
@@ -640,13 +642,15 @@ impl<'a, T: Write + Seek> Seek for BgiArchiveFile<'a, T> {
pub struct BgiArchiveFileWithDsc<'a, T: Write + Seek> {
writer: BgiArchiveFile<'a, T>,
buf: MemWriter,
min_len: usize,
}
impl<'a, T: Write + Seek> BgiArchiveFileWithDsc<'a, T> {
pub fn new(writer: BgiArchiveFile<'a, T>) -> Self {
pub fn new(writer: BgiArchiveFile<'a, T>, min_len: usize) -> Self {
BgiArchiveFileWithDsc {
writer,
buf: MemWriter::new(),
min_len,
}
}
}
@@ -678,7 +682,7 @@ impl<'a, T: Write + Seek> Seek for BgiArchiveFileWithDsc<'a, T> {
impl<'a, T: Write + Seek> Drop for BgiArchiveFileWithDsc<'a, T> {
fn drop(&mut self) {
let buf = self.buf.as_slice();
let encoder = DscEncoder::new(&mut self.writer);
let encoder = DscEncoder::new(&mut self.writer, self.min_len);
if let Err(e) = encoder.pack(&buf) {
eprintln!("Failed to write DSC data: {}", e);
crate::COUNTER.inc_error();

View File

@@ -514,6 +514,7 @@ pub struct BgiArchiveWriter<T: Write + Seek> {
headers: HashMap<String, BgiFileHeader>,
compress_file: bool,
encoding: Encoding,
min_len: usize,
}
impl<T: Write + Seek> BgiArchiveWriter<T> {
@@ -543,6 +544,7 @@ impl<T: Write + Seek> BgiArchiveWriter<T> {
headers,
compress_file: config.bgi_compress_file,
encoding,
min_len: config.bgi_compress_min_len,
})
}
}
@@ -564,7 +566,7 @@ impl<T: Write + Seek> Archive for BgiArchiveWriter<T> {
pos: 0,
};
Ok(if self.compress_file {
Box::new(BgiArchiveFileWithDsc::new(file))
Box::new(BgiArchiveFileWithDsc::new(file, self.min_len))
} else {
Box::new(file)
})
@@ -643,13 +645,15 @@ impl<'a, T: Write + Seek> Seek for BgiArchiveFile<'a, T> {
pub struct BgiArchiveFileWithDsc<'a, T: Write + Seek> {
writer: BgiArchiveFile<'a, T>,
buf: MemWriter,
min_len: usize,
}
impl<'a, T: Write + Seek> BgiArchiveFileWithDsc<'a, T> {
pub fn new(writer: BgiArchiveFile<'a, T>) -> Self {
pub fn new(writer: BgiArchiveFile<'a, T>, min_len: usize) -> Self {
BgiArchiveFileWithDsc {
writer,
buf: MemWriter::new(),
min_len,
}
}
}
@@ -681,7 +685,7 @@ impl<'a, T: Write + Seek> Seek for BgiArchiveFileWithDsc<'a, T> {
impl<'a, T: Write + Seek> Drop for BgiArchiveFileWithDsc<'a, T> {
fn drop(&mut self) {
let buf = self.buf.as_slice();
let encoder = DscEncoder::new(&mut self.writer);
let encoder = DscEncoder::new(&mut self.writer, self.min_len);
if let Err(e) = encoder.pack(&buf) {
eprintln!("Failed to write DSC data: {}", e);
crate::COUNTER.inc_error();

View File

@@ -50,6 +50,7 @@ impl ScriptBuilder for BGIBsiScriptBuilder {
writer: Box<dyn WriteSeek + 'a>,
encoding: Encoding,
file_encoding: Encoding,
_config: &ExtraConfig,
) -> Result<()> {
create_file(filename, writer, encoding, file_encoding)
}

View File

@@ -57,6 +57,7 @@ impl ScriptBuilder for CstlScriptBuilder {
writer: Box<dyn WriteSeek + 'a>,
encoding: Encoding,
file_encoding: Encoding,
_config: &ExtraConfig,
) -> Result<()> {
create_file(filename, writer, encoding, file_encoding)
}

View File

@@ -61,6 +61,7 @@ impl ScriptBuilder for EscudeBinListBuilder {
writer: Box<dyn WriteSeek + 'a>,
encoding: Encoding,
file_encoding: Encoding,
_config: &ExtraConfig,
) -> Result<()> {
create_file(filename, writer, encoding, file_encoding)
}