general: improve message consistency + rewrite novatek nfwb

This commit is contained in:
theubusu
2025-12-05 20:23:32 +01:00
parent ecc8487134
commit 45feddda8f
22 changed files with 63 additions and 58 deletions
+2 -1
View File
@@ -116,7 +116,8 @@ pub fn extract_epk1(mut file: &File, output_folder: &str) -> Result<(), Box<dyn
let data = common::read_file(&file, pak.offset as u64 + 128, pak.size as usize - 128)?;
println!("\nPak {}: {}, Offset: {}, Size: {}, Platform: {}", i + 1, pak_header.pak_name(), pak.offset, pak.size, pak_header.platform_id());
println!("\n({}/{}) - {}, Offset: {}, Size: {}, Platform: {}",
i + 1, paks.len(), pak_header.pak_name(), pak.offset, pak.size, pak_header.platform_id());
let output_path = Path::new(&output_folder).join(pak_header.pak_name() + ".bin");
+2 -2
View File
@@ -126,7 +126,7 @@ pub fn extract_epk2(mut file: &File, output_folder: &str) -> Result<(), Box<dyn
let segment_count = u32::from_le_bytes(header[84..88].try_into().unwrap());
let mut segment_size = u32::from_le_bytes(header[88..92].try_into().unwrap());
println!("\nPak {}/{} - {}, Size: {}, Segments: {}", pak_n + 1, paks.len(), pak.name, pak.size, segment_count);
println!("\n({}/{}) - {}, Size: {}, Segments: {}", pak_n + 1, paks.len(), pak.name, pak.size, segment_count);
for i in 0..segment_count {
// for first segment we already read the header so skip doing that for it
@@ -161,7 +161,7 @@ pub fn extract_epk2(mut file: &File, output_folder: &str) -> Result<(), Box<dyn
let segment_data = common::read_exact(&mut file, actual_segment_size as usize)?;
let out_data = decrypt_aes_ecb_auto(&matching_key_bytes, &segment_data)?;
println!("- Segment {}/{}, size: {}", i + 1, segment_count, actual_segment_size);
println!("- Segment {}/{} - Size: {}", i + 1, segment_count, actual_segment_size);
let output_path = Path::new(&output_folder).join(pak.name.clone() + ".bin");
+4 -2
View File
@@ -106,11 +106,12 @@ pub fn extract_epk3(mut file: &File, output_folder: &str) -> Result<(), Box<dyn
if new_type {let _unknown = common::read_exact(&mut pkg_info_reader, 4)?;}; //new type has additional value
let mut pak_i = 1;
while (pkg_info_reader.position() as usize) < pkg_info_reader.get_ref().len() {
let mut entry: PkgInfoEntry = pkg_info_reader.read_le()?;
println!("\nPak - {}, Size: {}, Segments: {}",
entry.package_name(), entry.package_size, entry.segment_count);
println!("\n({}) - {}, Size: {}, Segments: {}",
pak_i, entry.package_name(), entry.package_size, entry.segment_count);
for i in 0..entry.segment_count {
if i > 0 {
@@ -136,6 +137,7 @@ pub fn extract_epk3(mut file: &File, output_folder: &str) -> Result<(), Box<dyn
println!("-- Saved to file!");
}
pak_i += 1;
}
println!("\nExtraction finished!");
+1 -1
View File
@@ -35,7 +35,7 @@ pub fn extract_funai_upg(mut file: &File, output_folder: &str) -> Result<(), Box
for i in 0..header.entry_count {
let entry: Entry = file.read_le()?;
println!("\nEntry {}/{} - Type: {}, Size: {}", i + 1, header.entry_count, entry.entry_type, entry.entry_size);
println!("\n({}/{}) - Type: {}, Size: {}", i + 1, header.entry_count, entry.entry_type, entry.entry_size);
let data = common::read_exact(&mut file, entry.entry_size as usize - 2 - 4)?; //size has the unk field + crc32 at the end
let _crc32 = common::read_exact(&mut file, 4)?; //btw the CRC32 includes the entry header
+2 -2
View File
@@ -68,7 +68,7 @@ pub fn is_invincible_image_file(file: &File) -> bool {
pub fn extract_invincible_image(mut file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
let header: Header = file.read_le()?;
println!("\nFile info:\nFile Version: {}.{}\nVersion(1): {}\nVersion(2): {}\nVersion(3): {}\nVersion(4): {}\nData size: {}\nData start offset: {}\nKeep data size: {}\nSkip data size: {}\n\nPayload Count: {}",
println!("File info:\nFile Version: {}.{}\nVersion(1): {}\nVersion(2): {}\nVersion(3): {}\nVersion(4): {}\nData size: {}\nData start offset: {}\nKeep data size: {}\nSkip data size: {}\n\nPayload Count: {}",
header.file_version[0], header.file_version[1], header.ver1(), header.ver2(), header.ver3(), header.ver4(), header.data_size, header.data_start_offset, header.keep_size, header.skip_size, header.payload_count);
let mut entries: Vec<Entry> = Vec::new();
@@ -110,7 +110,7 @@ pub fn extract_invincible_image(mut file: &File, output_folder: &str) -> Result<
let mut i = 1;
for entry in entries {
println!("\nExtracting {}/{} - {}", i, header.payload_count, entry.name());
println!("\n({}/{}) - {}, Size: {}", i, header.payload_count, entry.name(), entry.size);
let data = common::read_exact(&mut data_reader, entry.size as usize)?;
let output_path = Path::new(&output_folder).join(entry.name() + ".bin");
+5 -6
View File
@@ -143,11 +143,11 @@ pub fn extract_msd10(mut file: &File, output_folder: &str) -> Result<(), Box<dyn
for i in 0..header.section_count {
let entry: TizenTocEntry = toc_reader.read_le()?;
println!("\nSection {}: {}", sections[i as usize].index, entry.name());
let offset = sections[i as usize].offset;
let size = sections[i as usize].size;
println!("\n({}/{}) - {}, Size: {}", sections[i as usize].index, sections.len(), entry.name(), size);
let encrypted_data = common::read_file(&file, offset as u64, size as usize)?;
println!("- Decrypting...");
@@ -179,12 +179,11 @@ pub fn extract_msd10(mut file: &File, output_folder: &str) -> Result<(), Box<dyn
assert!(entry.segment_size == sections[i as usize].size, "size in TOC does not match size from header!");
sections[i as usize].name = entry.name().clone();
println!("\nSection {}: {}", sections[i as usize].index, entry.name());
let offset = sections[i as usize].offset;
let size = sections[i as usize].size;
println!("\n({}/{}) - {}, Size: {}", sections[i as usize].index, sections.len(), entry.name(), size);
if i != 0 && entry.name() == sections[i as usize - 1].name { //second section with the same name is some sort of signature
println!("- Skipping signature file...");
continue;
+3 -3
View File
@@ -122,11 +122,11 @@ pub fn extract_msd11(mut file: &File, output_folder: &str) -> Result<(), Box<dyn
for i in 0..header.section_count {
let entry: TocEntry = toc_reader.read_le()?;
println!("\nSection {}: {}", sections[i as usize].index, entry.name());
let offset = sections[i as usize].offset;
let size = sections[i as usize].size;
println!("\n({}/{}) - {}, Size: {}", sections[i as usize].index, sections.len(), entry.name(), size);
let encrypted_data = common::read_file(&file, offset as u64, size as usize)?;
println!("- Decrypting...");
+1 -1
View File
@@ -143,7 +143,7 @@ pub fn extract_mtk_bdp(mut file: &File, output_folder: &str) -> Result<(), Box<d
for i in 0..part_header.part_count {
let part_entry: PartEntry = file.read_le()?;
println!("\n{}/{}. {}, ID: {:02x}, Size: {}", i + 1, part_header.part_count, part_entry.name(), part_entry.id, part_entry.size);
println!("\n({}/{}) - {}, ID: {:02x}, Size: {}", i + 1, part_header.part_count, part_entry.name(), part_entry.id, part_entry.size);
for entry in &entries{
if entry.id == part_entry.id && entry.size == part_entry.size {
+3 -3
View File
@@ -71,7 +71,7 @@ pub fn extract_mtk_pkg(mut file: &File, output_folder: &str) -> Result<(), Box<d
let mut hdr_reader = Cursor::new(header);
let hdr: Header = hdr_reader.read_le()?;
println!("\nFile info:\nFile size: {}\nVendor magic: {}\nVersion info: {}\nProduct name: {}" ,
println!("File info:\nFile size: {}\nVendor magic: {}\nVersion info: {}\nProduct name: {}" ,
hdr.file_size, hdr.vendor_magic(), hdr.version(), hdr.product_name());
let mut part_n = 0;
@@ -80,7 +80,7 @@ pub fn extract_mtk_pkg(mut file: &File, output_folder: &str) -> Result<(), Box<d
let part_entry: PartEntry = file.read_le()?;
let is_encrypted = if (part_entry.flags & 1 << 0) == 1 << 0 {true} else {false};
println!("\nPart {} - {}{}, Size: {}", part_n, part_entry.name(), if is_encrypted {" (Encrypted)"} else {""} ,part_entry.size);
println!("\n{} - {}, Size: {} {}", part_n, part_entry.name(), part_entry.size, if is_encrypted {"[ENCRYPTED]"} else {""} );
let data = common::read_exact(&mut file, part_entry.size as usize + 48)?;
@@ -114,7 +114,7 @@ pub fn extract_mtk_pkg(mut file: &File, output_folder: &str) -> Result<(), Box<d
0
};
println!("Extra header size: {}", extra_header_len);
//println!("Extra header size: {}", extra_header_len);
let output_path = Path::new(&output_folder).join(part_entry.name() + ".bin");
+2 -2
View File
@@ -37,7 +37,7 @@ pub fn extract_mtk_upgrade_loader(mut file: &File, output_folder: &str) -> Resul
let part_entry: PartEntry = file.read_le()?;
let is_encrypted = if (part_entry.flags & 1 << 0) == 1 << 0 {true} else {false};
println!("\nPart {} - {}{}, Size: {}", part_n, part_entry.name(), if is_encrypted {" (Encrypted)"} else {""} ,part_entry.size);
println!("\n{} - {}, Size: {} {}", part_n, part_entry.name(), part_entry.size, if is_encrypted {"[ENCRYPTED]"} else {""} );
let data = common::read_exact(&mut file, part_entry.size as usize)?;
@@ -49,7 +49,7 @@ pub fn extract_mtk_upgrade_loader(mut file: &File, output_folder: &str) -> Resul
0
};
println!("Extra header size: {}", extra_header_len);
//println!("Extra header size: {}", extra_header_len);
let output_path = Path::new(&output_folder).join(part_entry.name() + ".bin");
+12 -11
View File
@@ -1,7 +1,7 @@
use std::fs::File;
use std::path::Path;
use std::fs::{self, OpenOptions};
use std::io::{Write, Seek};
use std::io::{Write};
use binrw::{BinRead, BinReaderExt};
@@ -38,18 +38,22 @@ pub fn is_novatek_file(file: &File) -> bool {
pub fn extract_novatek(mut file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
let header: Header = file.read_le()?;
println!("\nPart count: {}", header.part_count);
println!("Part count: {}", header.part_count);
let mut entries: Vec<PartEntry> = Vec::new();
for i in 0..header.part_count {
for _i in 0..header.part_count {
let part: PartEntry = file.read_le()?;
entries.push(part);
}
let current_pos = file.stream_position()?;
let mut e_i = 0;
for entry in &entries {
e_i += 1;
println!("\n({}/{}) - Index: {}, Offset: {}, Size: {}", e_i, entries.len(), entry.index, entry.offset, entry.size);
let data = common::read_file(&file, part.offset as u64, part.size as usize)?;
let data = common::read_file(&file, entry.offset as u64, entry.size as usize)?;
println!("\nPart {}: index: {}, size: {}, offset: {}", i + 1, part.index, part.size, part.offset);
let output_path = Path::new(&output_folder).join(format!("part_{}.bin", i + 1));
let output_path = Path::new(&output_folder).join(format!("{}.bin", e_i));
fs::create_dir_all(&output_folder)?;
let mut out_file = OpenOptions::new()
@@ -60,9 +64,6 @@ pub fn extract_novatek(mut file: &File, output_folder: &str) -> Result<(), Box<d
out_file.write_all(&data)?;
println!("- Saved file!");
file.seek(std::io::SeekFrom::Start(current_pos))?;
}
Ok(())
+3 -1
View File
@@ -43,6 +43,7 @@ pub fn is_nvt_timg_file(file: &File) -> bool {
pub fn extract_nvt_timg(mut file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
let _timg = common::read_exact(&mut file, 288)?; //TIMG magic + header
let mut pimg_i = 1;
loop {
let pimg = match file.read_le::<PIMG>() {
Ok(val) => val,
@@ -50,7 +51,7 @@ pub fn extract_nvt_timg(mut file: &File, output_folder: &str) -> Result<(), Box<
};
let data = common::read_exact(&mut file, pimg.size as usize)?;
println!("\nPIMG: Name: {}, Size: {}, Dest: {}, Compression: {}", pimg.name(), pimg.size, pimg.dest_dev(), pimg.comp_type());
println!("\n({}) - {}, Size: {}, Dest: {}, Compression: {}", pimg_i, pimg.name(), pimg.size, pimg.dest_dev(), pimg.comp_type());
let out_data;
@@ -75,6 +76,7 @@ pub fn extract_nvt_timg(mut file: &File, output_folder: &str) -> Result<(), Box<
out_file.write_all(&out_data)?;
println!("-- Saved file!");
pimg_i += 1;
}
println!("\nExtraction finished!");
+10 -7
View File
@@ -190,10 +190,12 @@ pub fn extract_pana_dvd(mut file: &File, output_folder: &str) -> Result<(), Box<
modules.push(entry);
}
let mut mod_i = 0;
let mut main_offset: Option<u32> = None;
for module in modules {
println!("\nSave module {}, Offset: {}, Size: {}, Expected checksum: {:#010x}",
module.name(), module.offset, module.size, module.data_checksum);
for module in &modules {
mod_i += 1;
println!("\n({}/{}) - {}, Offset: {}, Size: {}, Expected checksum: {:#010x}",
mod_i, modules.len(), module.name(), module.offset, module.size, module.data_checksum);
file_reader.seek(SeekFrom::Start(module.offset as u64))?;
let data = common::read_exact(&mut file_reader, module.size as usize)?;
@@ -219,7 +221,6 @@ pub fn extract_pana_dvd(mut file: &File, output_folder: &str) -> Result<(), Box<
out_file.write_all(&dec_data)?;
println!("-- Saved file!");
}
if !main_offset.is_some() {
@@ -242,7 +243,9 @@ pub fn extract_pana_dvd(mut file: &File, output_folder: &str) -> Result<(), Box<
main_entries.push(main_entry);
}
for entry in main_entries {
let mut maine_i = 0;
for entry in &main_entries {
maine_i += 1;
let mut data = common::read_exact(&mut file_reader, entry.size as usize)?;
if entry.size > 5120 {
//decrypt first and last 5kb
@@ -260,8 +263,8 @@ pub fn extract_pana_dvd(mut file: &File, output_folder: &str) -> Result<(), Box<
let mut data_reader = Cursor::new(data);
let header: MainEntryHeader = data_reader.read_le()?;
println!("\nSaving entry - Compressed size: {}, Decompressed size: {}, Compression type: {}({})",
header.compressed_size, header.decompressed_size, header.compression_type_byte, header.compression_type());
println!("\nMAIN ({}/{}) - Compressed size: {}, Decompressed size: {}, Compression type: {}({})",
maine_i, main_entries.len(), header.compressed_size, header.decompressed_size, header.compression_type_byte, header.compression_type());
let compressed_data = common::read_exact(&mut data_reader, header.compressed_size as usize)?;
let decompressed_data;
+1 -1
View File
@@ -162,7 +162,7 @@ pub fn extract_pfl_upg(mut file: &File, output_folder: &str) -> Result<(), Box<d
continue
}
println!("\nFile: {}, Size: {}", file_header.file_name(), file_header.real_size);
println!("\nFile - {}, Size: {}", file_header.file_name(), file_header.real_size);
let data = common::read_exact(&mut data_reader, file_header.stored_size as usize)?;
let output_path = Path::new(&output_folder).join(file_header.file_name().trim_start_matches('/'));
+2 -2
View File
@@ -62,7 +62,7 @@ pub fn is_pup_file(file: &File) -> bool {
pub fn extract_pup(mut file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
let header: Header = file.read_le()?;
println!("\nFile info:\nFile size: {}\nEntry count: {}",
println!("File info:\nFile size: {}\nEntry count: {}",
header.file_size, header.entry_count);
let mut entries: Vec<Entry> = Vec::new();
@@ -78,7 +78,7 @@ pub fn extract_pup(mut file: &File, output_folder: &str) -> Result<(), Box<dyn s
let mut e_i = 0;
for entry in &entries {
println!("\n{}/{}: ID: {} Offset: {}, Compressed Size: {}, Uncompressed Size: {}\nCompressed: {}, Blocked: {}, Block table: {}",
println!("\n({}/{}) - ID: {} Offset: {}, Compressed Size: {}, Uncompressed Size: {}\nCompressed: {}, Blocked: {}, Block table: {}",
e_i + 1, entries.len(), entry.id(), entry.offset, entry.compressed_size, entry.uncompressed_size, entry.is_compressed(), entry.is_blocked(), entry.is_block_table());
if !entry.is_block_table () {
+1 -1
View File
@@ -152,7 +152,7 @@ fn actually_extract_ruf(mut file: &File, output_folder: &str, start_offset: u64)
let mut ei = 1;
for entry in entries {
println!("\nEntry {}/{}: {} - {}, Size: {}",
println!("\n({}/{}) - {}({}), Size: {}",
ei, header.payload_count, entry.payload_type_bytes, entry.payload_type(), entry.size);
let data = common::read_exact(&mut data_reader, entry.size as usize)?;
+1 -1
View File
@@ -46,7 +46,7 @@ pub fn extract_rvp(mut file: &File, output_folder: &str) -> Result<(), Box<dyn s
i += 1;
let header_size_bytes = common::read_exact(&mut data_reader, 4)?;
let header_size = u32::from_be_bytes(header_size_bytes.try_into().unwrap());
println!("\nEntry {} - Offset: {}, Header size: {}", i, data_reader.position() - 4, header_size);
println!("\n({}) - Offset: {}, Header size: {}", i, data_reader.position() - 4, header_size);
let hdr = common::read_exact(&mut data_reader, header_size as usize)?;
let size;
+1 -1
View File
@@ -60,7 +60,7 @@ pub fn extract_samsung_old(path: &PathBuf, output_folder: &str) -> Result<(), Bo
let file = File::open(&path)?;
let filename = path.file_name().unwrap().to_str().unwrap();
let file_size = file.metadata()?.len();
println!("\nFile: {}", filename);
println!("\nFile - {}", filename);
let data = common::read_file(&file, 0, file_size.try_into().unwrap())?;
let salt = &data[8..16];
+1 -1
View File
@@ -163,7 +163,7 @@ pub fn extract_sddl_sec(mut file: &File, output_folder: &str) -> Result<(), Box<
let mut entry_header_reader = Cursor::new(decrypt_aes128_cbc_pcks7(&common::read_exact(&mut file, 32)?, &DEC_KEY, &DEC_IV)?);
let entry_header: EntryHeader = entry_header_reader.read_be()?;
println!("\n({}/{}) File: {}, Size: {}", i + 1, total_entry_count, entry_header.name(), entry_header.size());
println!("\n({}/{}) - {}, Size: {}", i + 1, total_entry_count, entry_header.name(), entry_header.size());
let data = common::read_exact(&mut file, entry_header.size() as usize)?;
let dec_data = decrypt_aes128_cbc_pcks7(&data, &DEC_KEY, &DEC_IV)?;
+2 -2
View File
@@ -58,7 +58,7 @@ pub fn is_slp_file(file: &File) -> bool {
pub fn extract_slp(mut file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
let header: Header = file.read_le()?;
println!("\nFile info:\nModel: {}\nVersion: {}\nFirmware: {}\nNew type: {}\n",
println!("File info:\nModel: {}\nVersion: {}\nFirmware: {}\nNew type: {}\n",
header.model(), header.version(), header.firmware(), header.is_new_type());
let mut first_entry_offset = 0;
@@ -88,7 +88,7 @@ pub fn extract_slp(mut file: &File, output_folder: &str) -> Result<(), Box<dyn s
let mut i = 1;
for entry in &entries {
println!("\nExtracting {}/{}", i, &entries.len());
println!("\n({}/{}) - Offset: {}, Size: {}", i, &entries.len(), entry.offset, entry.size);
file.seek(SeekFrom::Start(entry.offset.into()))?;
let data = common::read_exact(&mut file, entry.size as usize)?;
+2 -2
View File
@@ -72,7 +72,7 @@ pub fn extract_sony_bdp(mut file: &File, output_folder: &str) -> Result<(), Box<
let mut hdr_reader = Cursor::new(header);
let hdr: Header = hdr_reader.read_le()?;
println!("\nFile info:\nFirmware: {}\nVersion: {}\nDate: {}\nFile size: {}",
println!("File info:\nFirmware: {}\nVersion: {}\nDate: {}\nFile size: {}",
hdr.firmware_name(), hdr.firmware_version(), hdr.date(), hdr.file_size);
let mut last_file_path: Option<PathBuf> = None;
@@ -88,7 +88,7 @@ pub fn extract_sony_bdp(mut file: &File, output_folder: &str) -> Result<(), Box<
continue
}
println!("\nEntry {} - Offset: {}, Size: {}", i, entry.offset, entry.size);
println!("\n({}) - Offset: {}, Size: {}", i, entry.offset, entry.size);
if i == 1 {
first_entry_offset = entry.offset as u64;
}