diff --git a/src/formats/pana_dvd/include.rs b/src/formats/pana_dvd/include.rs index 080ccb0..37a1a01 100644 --- a/src/formats/pana_dvd/include.rs +++ b/src/formats/pana_dvd/include.rs @@ -104,25 +104,27 @@ pub const COMPRESSED_FILE_MAGIC: &[u8; 8] = b"EXTRHEAD"; #[derive(BinRead)] pub struct CompressedFileHeader { - _header_string: [u8; 14], //EXTRHEADDRV \x01\x00 - pub compression_type_byte: u16, - pub decompressed_size: u32, - _destination_address: u32, - pub compressed_size: u32, + _magic_bytes: [u8; 8], // EXTRHEAD + _unk_string: [u8; 4], // DRV\x20 ? + _compressed_flag: u16, // checks for 1 here, else -> "Error! Not compress" + pub compression_type: u16, // 0 - not compressed, 1 - GZIP , 2 - LZSS + pub dest_size: u32, // decompressed size + _dest_address: u32, + pub src_size: u32, // compressed size + _src_address: u32, + _footer_offset: u32, // offset to EXTRFOOT _unk: u32, - _footer_offset: u32, - _base_address: u32, - _checksum: u32, //unknown type of checksum - _checksum_flag: u8, - _unused: [u8; 19], + _checksum: u32, // adler32 calculated every checksum_skip bytes of decompressed data + _checksum_skip: u32, + _unused: [u8; 16], } impl CompressedFileHeader { - pub fn compression_type(&self) -> &str { - if self.compression_type_byte == 0 { + pub fn compression_type_str(&self) -> &str { + if self.compression_type == 0 { return "Uncompressed" - } else if self.compression_type_byte == 1 { + } else if self.compression_type == 1 { return "GZIP" - } else if self.compression_type_byte == 2 { + } else if self.compression_type == 2 { return "LZSS" } else { return "Unknown" diff --git a/src/formats/pana_dvd/mod.rs b/src/formats/pana_dvd/mod.rs index 4d3db46..4330810 100644 --- a/src/formats/pana_dvd/mod.rs +++ b/src/formats/pana_dvd/mod.rs @@ -226,12 +226,12 @@ fn decompress_data(data: &[u8]) -> Result, Box> { let mut data_reader = Cursor::new(data); let header: CompressedFileHeader = data_reader.read_le()?; println!("Compressed size: {}, Decompressed size: {}, Compression type: {}({})", - header.compressed_size, header.decompressed_size, header.compression_type_byte, header.compression_type()); + header.src_size, header.dest_size, header.compression_type, header.compression_type_str()); - let compressed_data = common::read_exact(&mut data_reader, header.compressed_size as usize)?; + let compressed_data = common::read_exact(&mut data_reader, header.src_size as usize)?; let decompressed_data; - if header.compression_type_byte == 1 { //gzip + optionally lzss + if header.compression_type == 1 { //gzip + optionally lzss println!("- Decompressing GZIP..."); let decompressed_gzip = decompress_gzip(&compressed_data)?; @@ -241,13 +241,13 @@ fn decompress_data(data: &[u8]) -> Result, Box> { } else { decompressed_data = decompressed_gzip; } - } else if header.compression_type_byte == 2 { //only lzss + } else if header.compression_type == 2 { //only lzss println!("- Decompressing LZSS..."); decompressed_data = decompress_lzss(&compressed_data); - if decompressed_data.len() != header.decompressed_size as usize { + if decompressed_data.len() != header.dest_size as usize { return Err("Decompressed size does not match size in header, decompression failed!".into()); } - } else if header.compression_type_byte == 0 { //no compression. havent encountered one yet + } else if header.compression_type == 0 { //no compression. havent encountered one yet decompressed_data = compressed_data; } else { diff --git a/src/keys.rs b/src/keys.rs index 0dda242..ce950ab 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -60,18 +60,24 @@ pub static PFLUPG: &[(&str, &str)] = &[ //pana dvd keys (no AES) pub static PANA_DVD_KEYONLY: &[&str] = &[ - ("08E03D859AF9F3EE"), //B3A25A0B9D864F08 # 87 firmwares, ..-~2011 - ("AF4D5B16C298C16D"), //720FCB305F2F6EDA # 3 firmwares, ~2011 - ("9407311B7561F97E"), //FBCC4CEA55466CA6 # 12 firmwares, ~2012 - ("38BB0C17D362701F"), //8AC6E0CFF65651F5 # 8 firmwares, ~2013 - ("EC238CD791456646"), //5FF6D2A1B8675D6F # 3 firmwares, ~2013 - ("8F8CA88482E43D9B"), //918C319720ACFEC1 # 5 firmwares, ~2014 - ("21FCA17361E66B4E"), //542FD3A55F200FD5 # 5 firmwares, ~2014 + ("08E03D859AF9F3EE"), //<=2011 + + // Thanks to + // https://git.gammaspectra.live/WeebDataHoarder/pana-fw#cmd-recover-lzss-cramfs & + // https://git.gammaspectra.live/WeebDataHoarder/pana-fw#cmd-recover-gzip-cramfs + // for these <3 + ("AF4D5B16C298C16D"), // ~2011 + ("9407311B7561F97E"), // ~2012 + ("5D88719745A4EFFF"), // ~2012 + ("38BB0C17D362701F"), // ~2013 + ("EC238CD791456646"), // ~2013 + ("8F8CA88482E43D9B"), // ~2014 + ("21FCA17361E66B4E"), // ~2014 ]; //pana dvd keys (PANAEUSB pair - AES key, AES IV, cust) pub static PANA_DVD_AESPAIR: &[(&str, &str, &str)] = &[ - ("62A39E1C5594AE09244EB326EF7938FA", "46D03C52B1A398FA03276FDE7CC4EA26", "06C943F3B997F7E0"), //# 9 firmwares, ~2018 + ("62A39E1C5594AE09244EB326EF7938FA", "46D03C52B1A398FA03276FDE7CC4EA26", "06C943F3B997F7E0"), // ~2018 ]; //mtk pkg custom keys