Add novatek extractor

This commit is contained in:
theubusu
2025-10-07 00:04:47 +02:00
parent 6e33b3bc49
commit 6f4b3ccb53
5 changed files with 82 additions and 26 deletions
+1
View File
@@ -3,3 +3,4 @@ pub mod samsung_old;
pub mod tpv_timg; pub mod tpv_timg;
pub mod pfl_upg; pub mod pfl_upg;
pub mod epk1; pub mod epk1;
pub mod novatek;
+2 -9
View File
@@ -22,7 +22,6 @@ struct Pak {
} }
pub fn extract_epk1(mut file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> { pub fn extract_epk1(mut file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
//check type of epk1 //check type of epk1
let epk1_type; let epk1_type;
let init_pak_count_bytes = common::read_file(&file, 8, 4)?; let init_pak_count_bytes = common::read_file(&file, 8, 4)?;
@@ -46,14 +45,11 @@ pub fn extract_epk1(mut file: &File, output_folder: &str) -> Result<(), Box<dyn
let mut paks: Vec<Pak> = Vec::new(); let mut paks: Vec<Pak> = Vec::new();
if epk1_type == "be" { if epk1_type == "be" {
//epak magic let _epak = common::read_exact(&mut file, 4)?; //epak magic
let _epak = common::read_exact(&mut file, 4)?;
//file size
let file_size_bytes = common::read_exact(&mut file, 4)?; let file_size_bytes = common::read_exact(&mut file, 4)?;
let file_size = u32::from_be_bytes(file_size_bytes.try_into().unwrap()); let file_size = u32::from_be_bytes(file_size_bytes.try_into().unwrap());
//pak count
let pak_count_bytes = common::read_exact(&mut file, 4)?; let pak_count_bytes = common::read_exact(&mut file, 4)?;
let pak_count = u32::from_be_bytes(pak_count_bytes.try_into().unwrap()); let pak_count = u32::from_be_bytes(pak_count_bytes.try_into().unwrap());
@@ -79,14 +75,11 @@ pub fn extract_epk1(mut file: &File, output_folder: &str) -> Result<(), Box<dyn
file_size, pak_count, version[1], version[2], version[3]); file_size, pak_count, version[1], version[2], version[3]);
} else if epk1_type == "le" { } else if epk1_type == "le" {
//epak magic let _epak = common::read_exact(&mut file, 4)?; //epak magic
let _epak = common::read_exact(&mut file, 4)?;
//file size
let file_size_bytes = common::read_exact(&mut file, 4)?; let file_size_bytes = common::read_exact(&mut file, 4)?;
let file_size = u32::from_le_bytes(file_size_bytes.try_into().unwrap()); let file_size = u32::from_le_bytes(file_size_bytes.try_into().unwrap());
//pak count
let pak_count_bytes = common::read_exact(&mut file, 4)?; let pak_count_bytes = common::read_exact(&mut file, 4)?;
let pak_count = u32::from_le_bytes(pak_count_bytes.try_into().unwrap()); let pak_count = u32::from_le_bytes(pak_count_bytes.try_into().unwrap());
+69
View File
@@ -0,0 +1,69 @@
use std::fs::File;
use std::path::Path;
use std::fs::{self, OpenOptions};
use std::io::{Write, Seek};
use crate::common;
pub fn is_novatek_file(file: &File) -> bool {
let header = common::read_file(&file, 0, 4).expect("Failed to read from file.");
let header_string = String::from_utf8_lossy(&header);
if header_string == "NFWB"{
true
} else {
false
}
}
pub fn extract_novatek(mut file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
let _magic = common::read_exact(&mut file, 4)?; //NFWB magic
let _flags = common::read_exact(&mut file, 4)?;
let _header_size = common::read_exact(&mut file, 4)?;
let _ = common::read_exact(&mut file, 40)?; //unknown
let part_count_bytes = common::read_exact(&mut file, 4)?;
let part_count = u32::from_le_bytes(part_count_bytes.try_into().unwrap());
let _first_part_offset = common::read_exact(&mut file, 4)?;
println!("Part count: {}", part_count);
let _ = common::read_exact(&mut file, 116)?;
for i in 0..part_count {
let _ = common::read_exact(&mut file, 16)?; //unknown
let index_bytes = common::read_exact(&mut file, 4)?;
let index = u32::from_le_bytes(index_bytes.try_into().unwrap());
let size_bytes = common::read_exact(&mut file, 4)?;
let size = u32::from_le_bytes(size_bytes.try_into().unwrap());
let offset_bytes = common::read_exact(&mut file, 4)?;
let offset = u32::from_le_bytes(offset_bytes.try_into().unwrap());
let current_pos = file.stream_position()?;
let data = common::read_file(&file, offset as u64, size as usize)?;
println!("- Part {}: index: {}, size: {}, offset: {}", i + 1, index, size, offset);
let output_path = Path::new(&output_folder).join(format!("part_{}.bin", i + 1));
fs::create_dir_all(&output_folder)?;
let mut out_file = OpenOptions::new()
.write(true)
.create(true)
.open(output_path)?;
out_file.write_all(&data)?;
println!("-- Saved file!");
file.seek(std::io::SeekFrom::Start(current_pos))?;
}
Ok(())
}
+5 -16
View File
@@ -61,41 +61,30 @@ fn decrypt_aes256_ecb(key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, Box<dyn
} }
pub fn extract_pfl_upg(mut file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> { pub fn extract_pfl_upg(mut file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
//2SWU3TXV magic let _ = common::read_exact(&mut file, 8)?; //2SWU3TXV magic
let _ = common::read_exact(&mut file, 8)?;
//header size
let header_size_bytes = common::read_exact(&mut file, 4)?; let header_size_bytes = common::read_exact(&mut file, 4)?;
let header_size = u32::from_le_bytes(header_size_bytes.try_into().unwrap()); let header_size = u32::from_le_bytes(header_size_bytes.try_into().unwrap());
//data size
let data_size_bytes = common::read_exact(&mut file, 4)?; let data_size_bytes = common::read_exact(&mut file, 4)?;
let data_size = u32::from_le_bytes(data_size_bytes.try_into().unwrap()); let data_size = u32::from_le_bytes(data_size_bytes.try_into().unwrap());
//crc32 let _crc32 = common::read_exact(&mut file, 4)?;
let _ = common::read_exact(&mut file, 4)?;
//mask
let mask_bytes = common::read_exact(&mut file, 4)?; let mask_bytes = common::read_exact(&mut file, 4)?;
let mask = u32::from_le_bytes(mask_bytes.try_into().unwrap()); let mask = u32::from_le_bytes(mask_bytes.try_into().unwrap());
//data size decompressed let _data_size_decompressed = common::read_exact(&mut file, 4)?;
let _ = common::read_exact(&mut file, 4)?;
//padding2? let _padding2 = common::read_exact(&mut file, 4)?;
let _ = common::read_exact(&mut file, 4)?;
//description
let description_bytes = common::read_exact(&mut file, 512)?; let description_bytes = common::read_exact(&mut file, 512)?;
let description = common::string_from_bytes(&description_bytes); let description = common::string_from_bytes(&description_bytes);
//signature
let signature = common::read_exact(&mut file, 128)?; let signature = common::read_exact(&mut file, 128)?;
//unknown let _ = common::read_exact(&mut file, 32)?; //unknown
let _ = common::read_exact(&mut file, 32)?;
//version string
let version_bytes = common::read_exact(&mut file, header_size as usize - 704)?; let version_bytes = common::read_exact(&mut file, header_size as usize - 704)?;
let version = common::string_from_bytes(&version_bytes); let version = common::string_from_bytes(&version_bytes);
+4
View File
@@ -39,6 +39,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("TPV TIMG file detected!"); println!("TPV TIMG file detected!");
println!(); println!();
formats::tpv_timg::extract_tpv_timg(&file, &output_path)?; formats::tpv_timg::extract_tpv_timg(&file, &output_path)?;
} else if formats::novatek::is_novatek_file(&file) {
println!("Novatek file detected!");
println!();
formats::novatek::extract_novatek(&file, &output_path)?;
} else if formats::epk1::is_epk1_file(&file) { } else if formats::epk1::is_epk1_file(&file) {
println!("EPK1 file detected!"); println!("EPK1 file detected!");
println!(); println!();