mirror of
https://github.com/Ap0dexMe0/unixtract.git
synced 2026-07-15 21:00:03 +02:00
Add novatek extractor
This commit is contained in:
+2
-1
@@ -2,4 +2,5 @@ pub mod mstar;
|
|||||||
pub mod samsung_old;
|
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
@@ -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());
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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!();
|
||||||
|
|||||||
Reference in New Issue
Block a user