Skip to content

Commit 70b38e1

Browse files
committed
lzss_be
1 parent b939ab9 commit 70b38e1

File tree

2 files changed

+18
-22
lines changed

2 files changed

+18
-22
lines changed

kidfile/src/data_formats/lzss_dc.rs renamed to kidfile/src/data_formats/lzss_be.rs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ use crate::{byte_iter::ByteIter, file_data::FileData, Certainty, Decoder};
22

33
// thanks to BoilingTeapot for reverse engineering the compression
44

5-
pub const ENTRY_LZSS_DC: Decoder<Box<[u8]>> = Decoder {
6-
id: "lzss-dc",
7-
desc: "LZSS variant used in N7 DC",
8-
detect: |buf| Certainty::possible_if(decode_header(buf).is_some()),
5+
pub const ENTRY_LZSS_BE: Decoder<Box<[u8]>> = Decoder {
6+
id: "lzss-be",
7+
desc: "LZSS-like used in N7 DC and 12R PS2",
8+
detect: |buf| Certainty::certain_if(decode_header(buf).is_some()),
99
decode
1010
};
1111

@@ -20,21 +20,21 @@ fn decode_header(data: &mut FileData) -> Option<usize> {
2020

2121
fn decode(data: &mut FileData) -> Result<Box<[u8]>, String> {
2222
if let Some(expected_size) = decode_header(data) {
23-
match decompress_lzss_dc(&data.read()[4..], expected_size) {
23+
match decompress_lzss_be(&data.read()[4..], expected_size) {
2424
Ok(decompressed) => Ok(decompressed),
25-
Err(Some(actual_size)) => Err(format!("expected {expected_size} bytes when decompressing, got only {actual_size}")),
25+
Err(Some(actual_size)) => Err(format!("expected {expected_size} bytes when decompressing, got {actual_size}")),
2626
Err(None) => Err(format!("error while decompressing"))
2727
}
2828
} else {
2929
Err(String::new())
3030
}
3131
}
3232

33-
fn decompress_lzss_dc(inp: &[u8], expected_size: usize) -> Result<Box<[u8]>, Option<usize>> {
33+
fn decompress_lzss_be(inp: &[u8], expected_size: usize) -> Result<Box<[u8]>, Option<usize>> {
3434
let mut out = Vec::with_capacity(expected_size);
3535
let mut src = inp.iter().cloned();
3636
while out.len() < expected_size {
37-
let chunk_size = src.next_u16_be().ok_or(out.len())? as usize;
37+
let chunk_size = src.next_u16_be().ok_or(Some(out.len()))? as usize;
3838
let mut chunk = src.by_ref().take(chunk_size);
3939
let chunk_out_start = out.len();
4040
// the flags byte determines whether the next 8 tokens are literals or references
@@ -43,25 +43,21 @@ fn decompress_lzss_dc(inp: &[u8], expected_size: usize) -> Result<Box<[u8]>, Opt
4343
if flags & (1 << i) == 0 { // literal token
4444
if let Some(byte) = chunk.next() {
4545
if out.len() >= expected_size {
46-
return Err(None);
46+
break;
4747
}
4848
out.push(byte);
4949
} else {
5050
break;
5151
}
52-
} else { // reference token
53-
let ref_value = chunk.next_u16_be().ok_or(None)? as usize;
54-
let ref_off = (ref_value >> 5) + 1;
55-
let ref_len = (ref_value & 0b11111) + 3;
56-
if ref_off >= out.len() {
52+
} else if let Some(ref_value) = chunk.next_u16_be() { // reference token
53+
let ref_off = (ref_value as usize >> 5) + 1;
54+
let ref_len = (ref_value as usize & 0b11111) + 3;
55+
let start = out.len() as isize - ref_off as isize;
56+
if ref_len > expected_size - out.len() {
5757
return Err(None);
5858
}
59-
let start = out.len() - ref_off;
60-
if out.len() + ref_len > expected_size {
61-
return Err(None);
62-
}
63-
for i in start..start + ref_len {
64-
out.push(*out.get(i.max(chunk_out_start)).ok_or(None)?);
59+
for i in start..start + ref_len as isize {
60+
out.push(*out.get(i.max(chunk_out_start as isize) as usize).ok_or(None)?);
6561
}
6662
}
6763
}

kidfile/src/data_formats/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ use super::Decoder;
33

44
mod lzss;
55
mod cps;
6-
mod lzss_dc;
6+
mod lzss_be;
77

88
pub const DATA_DECODERS: LazyLock<Vec<Decoder<Box<[u8]>>>> = LazyLock::new(|| [
99
lzss::ENTRY_LZSS,
1010
cps::ENTRY_CPS,
11-
lzss_dc::ENTRY_LZSS_DC
11+
lzss_be::ENTRY_LZSS_BE
1212
].into());

0 commit comments

Comments
 (0)