Fix Oodle decompression of entries with more than one block

This commit is contained in:
Truman Kilen 2023-05-28 22:51:49 -05:00
parent 8dcf7f504c
commit 45780637c2

View file

@ -404,7 +404,8 @@ impl Entry {
set_printf(printf); set_printf(printf);
*/ */
let func: libloading::Symbol< #[allow(non_snake_case)]
let OodleLZ_Decompress: libloading::Symbol<
extern "C" fn( extern "C" fn(
compBuf: *mut u8, compBuf: *mut u8,
compBufSize: usize, compBufSize: usize,
@ -417,7 +418,7 @@ impl Entry {
decBufSize: usize, decBufSize: usize,
fpCallback: u64, fpCallback: u64,
callbackUserData: u64, callbackUserData: u64,
decoderMemory: u64, decoderMemory: *mut u8,
decoderMemorySize: usize, decoderMemorySize: usize,
threadPhase: u32, threadPhase: u32,
) -> i32, ) -> i32,
@ -425,36 +426,47 @@ impl Entry {
let mut decompressed = vec![0; self.uncompressed as usize]; let mut decompressed = vec![0; self.uncompressed as usize];
// merge all blocks into one (assuming no odd bytes) in between let mut compress_offset = 0;
// oodle does not like decompressing blocks individually let mut decompress_offset = 0;
let buffer = &mut data[ranges[0].start..ranges[ranges.len() - 1].end]; let block_count = ranges.len();
let out = func( for range in ranges {
let decomp = if block_count == 1 {
self.uncompressed as usize
} else {
(self.compression_block_size as usize)
.min(self.uncompressed as usize - compress_offset)
};
let buffer = &mut data[range];
let out = OodleLZ_Decompress(
buffer.as_mut_ptr(), buffer.as_mut_ptr(),
buffer.len(), buffer.len(),
decompressed.as_mut_ptr(), decompressed.as_mut_ptr().offset(decompress_offset),
decompressed.len(), decomp,
0, 1,
0, 1,
0, //verbose 3 0, //verbose 3
0, 0,
0, 0,
0, 0,
0, 0,
0, std::ptr::null_mut(),
0, 0,
3, 3,
); );
if out == 0 { if out == 0 {
return Err(super::Error::DecompressionFailed(Compression::Oodle)); return Err(super::Error::DecompressionFailed(Compression::Oodle));
} else { }
compress_offset += self.compression_block_size as usize;
decompress_offset += out as isize;
}
assert_eq!( assert_eq!(
out as u64, self.uncompressed, decompress_offset, self.uncompressed as isize,
"Unexpected decompressed bytes" "Oodle decompression length mismatch"
); );
buf.write_all(&decompressed)?; buf.write_all(&decompressed)?;
} }
} }
}
_ => todo!(), _ => todo!(),
} }
buf.flush()?; buf.flush()?;