You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

46 lines
1.6 KiB

use std::fs;
use std::io::Write;
use flate2::Compression;
use flate2::write::ZlibEncoder;
use crate::formats::common::Pack;
use crate::formats::dcx;
use crate::repackers::errors::PackError;
/// Repack a previously unpacked DCX with this new data.
///
/// Params that are not well understood are reused, others are replaced
/// with accurate values.
pub fn pack_dcx(dcx: &mut dcx::Dcx, data: &[u8], output_path: &str) -> Result<(), PackError> {
dcx.sizes.uncompressed_size = data.len() as u32;
let compressed = compress(dcx, data)?;
dcx.sizes.compressed_size = compressed.len() as u32;
let mut output_file = fs::File::create(output_path)?;
dcx.header.write(&mut output_file)?;
dcx.sizes.write(&mut output_file)?;
dcx.params.write(&mut output_file)?;
dcx.archive.write(&mut output_file)?;
output_file.write_all(&compressed)?;
Ok(())
}
/// Compress data using DCX params.
pub fn compress(dcx: &dcx::Dcx, data: &[u8]) -> Result<Vec<u8>, PackError> {
let method: &[u8] = dcx.params.method.as_slice();
if method == b"DFLT" {
compress_dflt(dcx, data)
} else {
let method_string = String::from_utf8_lossy(method).to_string();
Err(PackError::Compression(format!("Method unknown: {}", method_string)))
}
}
fn compress_dflt(dcx: &dcx::Dcx, data: &[u8]) -> Result<Vec<u8>, PackError> {
let level = dcx.params.unk0C as u32; // Unsure if it really is compression level.
let half_size = data.len() / 2; // Quicker allocation.
let encoder = ZlibEncoder::new(Vec::with_capacity(half_size), Compression::new(level));
Ok(encoder.finish()?)
}