sddl_sec: automatically decompress comp. parts when splitting PEAKS

This commit is contained in:
theubusu
2026-02-21 00:30:12 +01:00
parent c93c18833c
commit f315f60175
3 changed files with 67 additions and 6 deletions
+2 -1
View File
@@ -150,7 +150,8 @@ Options:
**Notes:** Pre-2011 files are not supported. **Notes:** Pre-2011 files are not supported.
**Options:** **Options:**
`sddl_sec:save_extra` - Save SDIT.FDI and .TXT files that are not extracted by default. `sddl_sec:save_extra` - Save SDIT.FDI and .TXT files that are not extracted by default.
`sddl_sec:split_peaks` - Split PEAKS module into partitions (only on older files). `sddl_sec:split_peaks` - Split PEAKS module into partitions (only on older files). This will also automatically decompress compressed partitions.
`sddl_sec:no_decomp_peaks` - Do not automatically decompress partitions when splitting PEAKS with above option.
## SLP ## SLP
**Used in:** Samsung Tizen-based NX series cameras **Used in:** Samsung Tizen-based NX series cameras
+2 -1
View File
@@ -70,6 +70,7 @@ pub fn extract_sddl_sec(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(),
let mut file = app_ctx.file().ok_or("Extractor expected file")?; let mut file = app_ctx.file().ok_or("Extractor expected file")?;
let save_extra = app_ctx.options.iter().any(|e| e == "sddl_sec:save_extra"); let save_extra = app_ctx.options.iter().any(|e| e == "sddl_sec:save_extra");
let split_peaks = app_ctx.options.iter().any(|e| e == "sddl_sec:split_peaks"); let split_peaks = app_ctx.options.iter().any(|e| e == "sddl_sec:split_peaks");
let decomp_peaks = !app_ctx.options.iter().any(|e| e == "sddl_sec:no_decomp_peaks");
let mut secfile_hdr_reader = Cursor::new(decipher(&common::read_exact(&mut file, 32)?)); let mut secfile_hdr_reader = Cursor::new(decipher(&common::read_exact(&mut file, 32)?));
let secfile_header: SecHeader = secfile_hdr_reader.read_be()?; let secfile_header: SecHeader = secfile_hdr_reader.read_be()?;
@@ -164,7 +165,7 @@ pub fn extract_sddl_sec(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(),
if split_peaks && module.module_name() == "PEAKS" { if split_peaks && module.module_name() == "PEAKS" {
println!("\n- Splitting PEAKS"); println!("\n- Splitting PEAKS");
if let Some(ref path) = final_out_path { if let Some(ref path) = final_out_path {
split_peaks_file(path, &app_ctx.output_dir)?; split_peaks_file(path, &app_ctx.output_dir, decomp_peaks)?;
} }
} }
} }
+63 -4
View File
@@ -1,7 +1,10 @@
use binrw::{BinReaderExt, Endian};
use crate::utils::common; use crate::utils::common;
use std::{fs::{self, File, OpenOptions}, io::Write, path::{Path, PathBuf}}; use std::{fs::{self, File, OpenOptions}, io::{Cursor, Seek, SeekFrom, Write}, path::{Path, PathBuf}};
pub fn split_peaks_file(path: &PathBuf, out_path: &PathBuf) -> Result<(), Box<dyn std::error::Error>> { use crate::utils::compression::decompress_zlib;
pub fn split_peaks_file(path: &PathBuf, out_path: &PathBuf, do_decomp: bool) -> Result<(), Box<dyn std::error::Error>> {
let mut file = File::open(path)?; let mut file = File::open(path)?;
let file_size = file.metadata()?.len(); let file_size = file.metadata()?.len();
let output_folder = Path::new(&out_path).join("PEAKS"); let output_folder = Path::new(&out_path).join("PEAKS");
@@ -70,14 +73,70 @@ pub fn split_peaks_file(path: &PathBuf, out_path: &PathBuf) -> Result<(), Box<dy
tsize += part_size; tsize += part_size;
let data = common::read_exact(&mut file, *part_size as usize)?;
let output_path = Path::new(&output_folder).join(format!("{}.bin", part_name)); let output_path = Path::new(&output_folder).join(format!("{}.bin", part_name));
fs::create_dir_all(&output_folder)?; fs::create_dir_all(&output_folder)?;
let data = common::read_exact(&mut file, *part_size as usize)?;
if do_decomp && let Some(part_flag) = part_flag && *part_flag == "c" {
println!("-- Decompressing ...");
decompress_part_to_file(&data, &output_path)?;
continue
}
let mut out_file = OpenOptions::new().write(true).create(true).open(output_path)?; let mut out_file = OpenOptions::new().write(true).create(true).open(output_path)?;
out_file.write_all(&data)?; out_file.write_all(&data)?;
} }
Ok(()) Ok(())
} }
fn decompress_part_to_file(data: &[u8], out_path: &PathBuf) -> Result<(), Box<dyn std::error::Error>> {
let mut reader = Cursor::new(data);
let mut out_file = OpenOptions::new().append(true).create(true).open(out_path)?;
//detect endianness, we can safely assume uncomp size wontbe larger than 4294901760
let uncomp_chen = common::read_exact(&mut reader, 4)?;
let endianness = if uncomp_chen[0..2] == *b"\x00\x00" {
Endian::Little
} else {
Endian::Big
};
reader.seek(SeekFrom::Start(0))?;
let uncompressed_size: u32 = reader.read_type(endianness)?;
let first_blk: u32 = reader.read_type(endianness)?;
let count_blks = (first_blk - 4) / 4;
println!("[INFO] Endianness: {}, Uncompressed size: {}, First block loc: {}, Block count: {}",
endianness, uncompressed_size, first_blk, count_blks);
reader.seek(SeekFrom::Start(4))?;
let mut block_locs: Vec<u32> = Vec::new();
for _ in 0..count_blks {
let loc: u32 = reader.read_type(endianness)?;
block_locs.push(loc);
}
for (n, blk) in block_locs.iter().enumerate() {
reader.seek(SeekFrom::Start(*blk as u64))?;
print!("\rDecompressing... {}/{}",
n + 1, count_blks);
std::io::stdout().flush()?;
//special handling for last block since there is no next block to check, just assume 16k
let blk_size = if n == count_blks as usize - 1 {16384} else {block_locs[n + 1] - blk};
let compressed = common::read_exact(&mut reader, blk_size as usize)?;
let decompressed = decompress_zlib(&compressed)?;
out_file.write_all(&decompressed)?;
}
println!();
Ok(())
}