fix: Decompression doesn't work for some bundles
It seems that with the new bundle format, chunks are stored uncompressed when their compressed size equals the chunk size.
This commit is contained in:
parent
2219f4fab3
commit
c2ed9275b0
4 changed files with 54 additions and 24 deletions
|
@ -5,3 +5,7 @@
|
|||
=== Added
|
||||
|
||||
- implement decompilation for `.strings` files
|
||||
|
||||
=== Fixed
|
||||
|
||||
- fix issue where some bundles couldn't be opened anymore
|
||||
|
|
|
@ -20,7 +20,7 @@ pub(crate) mod file;
|
|||
|
||||
pub use file::BundleFile;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
|
||||
enum BundleFormat {
|
||||
F7,
|
||||
F8,
|
||||
|
@ -198,14 +198,19 @@ impl Bundle {
|
|||
let mut compressed_buffer = vec![0u8; chunk_size];
|
||||
r.read_exact(&mut compressed_buffer).await?;
|
||||
|
||||
if format >= BundleFormat::F8 && chunk_size == CHUNK_SIZE {
|
||||
decompressed.append(&mut compressed_buffer);
|
||||
} else {
|
||||
// TODO: Optimize to not reallocate?
|
||||
let ctx = ctx.read().await;
|
||||
let oodle_lib = ctx.oodle.as_ref().unwrap();
|
||||
let mut raw_buffer = oodle_lib.decompress(
|
||||
let mut raw_buffer = oodle_lib
|
||||
.decompress(
|
||||
&compressed_buffer,
|
||||
OodleLZ_FuzzSafe::No,
|
||||
OodleLZ_CheckCRC::No,
|
||||
)?;
|
||||
)
|
||||
.wrap_err_with(|| format!("failed to decompress chunk {chunk_index}"))?;
|
||||
|
||||
if unpacked_size_tracked < CHUNK_SIZE {
|
||||
raw_buffer.resize(unpacked_size_tracked, 0);
|
||||
|
@ -216,6 +221,7 @@ impl Bundle {
|
|||
tracing::trace!(raw_size = raw_buffer.len());
|
||||
|
||||
decompressed.append(&mut raw_buffer);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
.instrument(span)
|
||||
|
|
|
@ -11,6 +11,8 @@ use types::*;
|
|||
|
||||
// Hardcoded chunk size of Bitsquid's bundle compression
|
||||
pub const CHUNK_SIZE: usize = 512 * 1024;
|
||||
pub const COMPRESSOR: OodleLZ_Compressor = OodleLZ_Compressor::Kraken;
|
||||
pub const LEVEL: OodleLZ_CompressionLevel = OodleLZ_CompressionLevel::Optimal2;
|
||||
|
||||
pub struct Oodle {
|
||||
lib: Library,
|
||||
|
@ -80,7 +82,7 @@ impl Oodle {
|
|||
};
|
||||
|
||||
if ret == 0 {
|
||||
eyre::bail!("Failed to decompress chunk.");
|
||||
eyre::bail!("Decompression failed.");
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
|
@ -97,18 +99,15 @@ impl Oodle {
|
|||
// TODO: Query oodle for buffer size
|
||||
let mut out = vec![0u8; CHUNK_SIZE];
|
||||
|
||||
let compressor = OodleLZ_Compressor::Kraken;
|
||||
let level = OodleLZ_CompressionLevel::Optimal2;
|
||||
|
||||
let ret = unsafe {
|
||||
let compress: Symbol<OodleLZ_Compress> = self.lib.get(b"OodleLZ_Compress\0")?;
|
||||
|
||||
compress(
|
||||
compressor,
|
||||
COMPRESSOR,
|
||||
raw.as_ptr() as *const _,
|
||||
raw.len(),
|
||||
out.as_mut_ptr() as *mut _,
|
||||
level,
|
||||
LEVEL,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
|
@ -120,11 +119,25 @@ impl Oodle {
|
|||
tracing::debug!(compressed_size = ret, "Compressed chunk");
|
||||
|
||||
if ret == 0 {
|
||||
eyre::bail!("Failed to compress chunk.");
|
||||
eyre::bail!("Compression failed.");
|
||||
}
|
||||
|
||||
out.resize(ret as usize, 0);
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
pub fn get_decode_buffer_size(
|
||||
&self,
|
||||
raw_size: usize,
|
||||
corruption_possible: bool,
|
||||
) -> Result<usize> {
|
||||
unsafe {
|
||||
let f: Symbol<OodleLZ_GetDecodeBufferSize> =
|
||||
self.lib.get(b"OodleLZ_GetDecodeBufferSize\0")?;
|
||||
|
||||
let size = f(COMPRESSOR, raw_size, corruption_possible);
|
||||
Ok(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -179,6 +179,13 @@ pub type OodleLZ_Compress = extern "C" fn(
|
|||
scratch_size: c_size_t,
|
||||
) -> c_ulonglong;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type OodleLZ_GetDecodeBufferSize = extern "C" fn(
|
||||
compressor: OodleLZ_Compressor,
|
||||
raw_size: c_size_t,
|
||||
corruption_possible: bool,
|
||||
) -> c_size_t;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type OodleCore_Plugins_SetPrintf =
|
||||
extern "C" fn(f: t_fp_OodleCore_Plugin_Printf) -> t_fp_OodleCore_Plugin_Printf;
|
||||
|
|
Loading…
Add table
Reference in a new issue