mirror of
https://github.com/Ap0dexMe0/unixtract.git
synced 2026-07-15 21:00:03 +02:00
change novatek, tpv_timg and pfl_upg extractor to use structs
This commit is contained in:
Generated
+49
@@ -69,6 +69,12 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "array-init"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
@@ -81,6 +87,30 @@ version = "1.8.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
|
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "binrw"
|
||||||
|
version = "0.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81419ff39e6ed10a92a7f125290859776ced35d9a08a665ae40b23e7ca702f30"
|
||||||
|
dependencies = [
|
||||||
|
"array-init",
|
||||||
|
"binrw_derive",
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "binrw_derive"
|
||||||
|
version = "0.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "376404e55ec40d0d6f8b4b7df3f87b87954bd987f0cf9a7207ea3b6ea5c9add4"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"owo-colors",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.10.4"
|
version = "0.10.4"
|
||||||
@@ -99,6 +129,12 @@ dependencies = [
|
|||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.24.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
@@ -266,6 +302,12 @@ dependencies = [
|
|||||||
"cipher",
|
"cipher",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "find-msvc-tools"
|
name = "find-msvc-tools"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@@ -449,6 +491,12 @@ version = "1.70.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "owo-colors"
|
||||||
|
version = "4.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pem-rfc7468"
|
name = "pem-rfc7468"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@@ -644,6 +692,7 @@ name = "unixtract"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
|
"binrw",
|
||||||
"cbc",
|
"cbc",
|
||||||
"clap",
|
"clap",
|
||||||
"ecb",
|
"ecb",
|
||||||
|
|||||||
+3
-1
@@ -14,4 +14,6 @@ sha1 = "0.10"
|
|||||||
flate2 = "1.0"
|
flate2 = "1.0"
|
||||||
rsa = { version = "0.9", features = ["hazmat"] }
|
rsa = { version = "0.9", features = ["hazmat"] }
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
ecb = "0.1"
|
ecb = "0.1"
|
||||||
|
|
||||||
|
binrw = "0.15"
|
||||||
@@ -9,4 +9,6 @@
|
|||||||
- Samsung MSD11(Tizen 2016+) - Complete
|
- Samsung MSD11(Tizen 2016+) - Complete
|
||||||
- Panasonic SDDL.SEC(2011+) - Complete
|
- Panasonic SDDL.SEC(2011+) - Complete
|
||||||
- LG Epk2 (Crypted and plain header)- 100% complete (unless unencrypted versions exist >)
|
- LG Epk2 (Crypted and plain header)- 100% complete (unless unencrypted versions exist >)
|
||||||
- LG epk3 - Probably fine??? but needs more testing (and more stolen keys)
|
- LG epk3 - Probably fine??? but needs more testing (and more stolen keys)
|
||||||
|
|
||||||
|
Todo: use STRUCTS on everything
|
||||||
+29
-25
@@ -3,8 +3,31 @@ use std::path::Path;
|
|||||||
use std::fs::{self, OpenOptions};
|
use std::fs::{self, OpenOptions};
|
||||||
use std::io::{Write, Seek};
|
use std::io::{Write, Seek};
|
||||||
|
|
||||||
|
use binrw::{BinRead, BinReaderExt};
|
||||||
|
|
||||||
use crate::common;
|
use crate::common;
|
||||||
|
|
||||||
|
#[derive(Debug, BinRead)]
|
||||||
|
#[br(little)]
|
||||||
|
struct Header {
|
||||||
|
#[br(count = 4)] _magic_bytes: Vec<u8>,
|
||||||
|
#[br(count = 4)] _flags: Vec<u8>,
|
||||||
|
_header_size: u32,
|
||||||
|
#[br(count = 40)] _unknown1: Vec<u8>,
|
||||||
|
part_count: u32,
|
||||||
|
_first_part_offset: u32,
|
||||||
|
#[br(count = 116)] _unknown2: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, BinRead)]
|
||||||
|
#[br(little)]
|
||||||
|
struct PartEntry {
|
||||||
|
#[br(count = 16)] _unknown: Vec<u8>,
|
||||||
|
index: u32,
|
||||||
|
size: u32,
|
||||||
|
offset: u32,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_novatek_file(file: &File) -> bool {
|
pub fn is_novatek_file(file: &File) -> bool {
|
||||||
let header = common::read_file(&file, 0, 4).expect("Failed to read from file.");
|
let header = common::read_file(&file, 0, 4).expect("Failed to read from file.");
|
||||||
if header == b"NFWB" {
|
if header == b"NFWB" {
|
||||||
@@ -15,37 +38,18 @@ pub fn is_novatek_file(file: &File) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_novatek(mut file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
|
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 header: Header = file.read_le()?;
|
||||||
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)?;
|
println!("\nPart count: {}", header.part_count);
|
||||||
let part_count = u32::from_le_bytes(part_count_bytes.try_into().unwrap());
|
|
||||||
|
|
||||||
let _first_part_offset = common::read_exact(&mut file, 4)?;
|
for i in 0..header.part_count {
|
||||||
|
let part: PartEntry = file.read_le()?;
|
||||||
println!("\nPart 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 current_pos = file.stream_position()?;
|
||||||
|
|
||||||
let data = common::read_file(&file, offset as u64, size as usize)?;
|
let data = common::read_file(&file, part.offset as u64, part.size as usize)?;
|
||||||
|
|
||||||
println!("\nPart {}: index: {}, size: {}, offset: {}", i + 1, index, size, offset);
|
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!("part_{}.bin", i + 1));
|
||||||
|
|
||||||
|
|||||||
+49
-41
@@ -7,10 +7,46 @@ use std::fs::{self, OpenOptions};
|
|||||||
|
|
||||||
use aes::Aes256;
|
use aes::Aes256;
|
||||||
use ecb::{Decryptor, cipher::{BlockDecryptMut, KeyInit, generic_array::GenericArray}};
|
use ecb::{Decryptor, cipher::{BlockDecryptMut, KeyInit, generic_array::GenericArray}};
|
||||||
|
use binrw::{BinRead, BinReaderExt};
|
||||||
|
|
||||||
use crate::common;
|
use crate::common;
|
||||||
use crate::keys;
|
use crate::keys;
|
||||||
|
|
||||||
|
#[derive(Debug, BinRead)]
|
||||||
|
#[br(little)]
|
||||||
|
struct Header {
|
||||||
|
#[br(count = 8)] _magic_bytes: Vec<u8>,
|
||||||
|
header_size: u32,
|
||||||
|
data_size: u32,
|
||||||
|
#[br(count = 4)] _crc32: Vec<u8>,
|
||||||
|
mask: u32,
|
||||||
|
_data_size_decompressed: u32,
|
||||||
|
_padding2: u32,
|
||||||
|
#[br(count = 512)] description_bytes: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Header {
|
||||||
|
fn description(&self) -> String {
|
||||||
|
common::string_from_bytes(&self.description_bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, BinRead)]
|
||||||
|
#[br(little)]
|
||||||
|
struct FileHeader {
|
||||||
|
#[br(count = 60)] file_name_bytes: Vec<u8>,
|
||||||
|
real_size: u32,
|
||||||
|
stored_size: u32,
|
||||||
|
_header_size: u32,
|
||||||
|
_attributes: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileHeader {
|
||||||
|
fn file_name(&self) -> String {
|
||||||
|
common::string_from_bytes(&self.file_name_bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_pfl_upg_file(file: &File) -> bool {
|
pub fn is_pfl_upg_file(file: &File) -> bool {
|
||||||
let header = common::read_file(&file, 0, 8).expect("Failed to read from file.");
|
let header = common::read_file(&file, 0, 8).expect("Failed to read from file.");
|
||||||
if header == b"2SWU3TXV" {
|
if header == b"2SWU3TXV" {
|
||||||
@@ -32,6 +68,7 @@ static AUTO_FWS: &[(&str, &str)] = &[
|
|||||||
("Q582E", "q522e"),
|
("Q582E", "q522e"),
|
||||||
("Q5481", "q5481"),
|
("Q5481", "q5481"),
|
||||||
("Q5431", "q5431"),
|
("Q5431", "q5431"),
|
||||||
|
("S5551", "q5551"), //Sharp
|
||||||
];
|
];
|
||||||
|
|
||||||
type Aes256EcbDec = Decryptor<Aes256>;
|
type Aes256EcbDec = Decryptor<Aes256>;
|
||||||
@@ -51,39 +88,19 @@ 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>> {
|
||||||
let _ = common::read_exact(&mut file, 8)?; //2SWU3TXV magic
|
let header: Header = file.read_le()?;
|
||||||
|
|
||||||
let header_size_bytes = common::read_exact(&mut file, 4)?;
|
|
||||||
let header_size = u32::from_le_bytes(header_size_bytes.try_into().unwrap());
|
|
||||||
|
|
||||||
let data_size_bytes = common::read_exact(&mut file, 4)?;
|
|
||||||
let data_size = u32::from_le_bytes(data_size_bytes.try_into().unwrap());
|
|
||||||
|
|
||||||
let _crc32 = 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 _data_size_decompressed = common::read_exact(&mut file, 4)?;
|
|
||||||
|
|
||||||
let _padding2 = common::read_exact(&mut file, 4)?;
|
|
||||||
|
|
||||||
let description_bytes = common::read_exact(&mut file, 512)?;
|
|
||||||
let description = common::string_from_bytes(&description_bytes);
|
|
||||||
|
|
||||||
let signature = common::read_exact(&mut file, 128)?;
|
let signature = common::read_exact(&mut file, 128)?;
|
||||||
|
|
||||||
let _ = common::read_exact(&mut file, 32)?; //unknown
|
let _ = common::read_exact(&mut file, 32)?; //unknown
|
||||||
|
|
||||||
let version_bytes = common::read_exact(&mut file, header_size as usize - 704)?;
|
let version_bytes = common::read_exact(&mut file, header.header_size as usize - 704)?;
|
||||||
let version = common::string_from_bytes(&version_bytes);
|
let version = common::string_from_bytes(&version_bytes);
|
||||||
|
|
||||||
println!("\nVersion: {}", version);
|
println!("\nVersion: {}", version);
|
||||||
println!("Description: \n{}", description);
|
println!("Description: \n{}", header.description());
|
||||||
println!("Data size: {}", data_size);
|
println!("Data size: {}", header.data_size);
|
||||||
|
|
||||||
let decrypted_data;
|
let decrypted_data;
|
||||||
if (mask & 0x2000_0000) != 0 {
|
if (header.mask & 0x2000_0000) != 0 {
|
||||||
println!("File is encrypted.");
|
println!("File is encrypted.");
|
||||||
let mut key = None;
|
let mut key = None;
|
||||||
let mut n_hex = None;
|
let mut n_hex = None;
|
||||||
@@ -122,33 +139,24 @@ pub fn extract_pfl_upg(mut file: &File, output_folder: &str) -> Result<(), Box<d
|
|||||||
let aes_key = &decrypted[20..52];
|
let aes_key = &decrypted[20..52];
|
||||||
println!("AES key: {}\n", hex::encode(aes_key));
|
println!("AES key: {}\n", hex::encode(aes_key));
|
||||||
|
|
||||||
let encrypted_data = common::read_exact(&mut file, data_size as usize)?;
|
let encrypted_data = common::read_exact(&mut file, header.data_size as usize)?;
|
||||||
println!("Decrypting data...");
|
println!("Decrypting data...");
|
||||||
decrypted_data = decrypt_aes256_ecb(aes_key, &encrypted_data)?;
|
decrypted_data = decrypt_aes256_ecb(aes_key, &encrypted_data)?;
|
||||||
} else {
|
} else {
|
||||||
println!("File is not encrypted.");
|
println!("File is not encrypted.");
|
||||||
decrypted_data = common::read_exact(&mut file, data_size as usize)?;
|
decrypted_data = common::read_exact(&mut file, header.data_size as usize)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut data_reader = Cursor::new(decrypted_data);
|
let mut data_reader = Cursor::new(decrypted_data);
|
||||||
|
|
||||||
while (data_reader.position() as usize) < data_reader.get_ref().len() {
|
while (data_reader.position() as usize) < data_reader.get_ref().len() {
|
||||||
//file header
|
let file_header: FileHeader = data_reader.read_le()?;
|
||||||
let file_header = common::read_exact(&mut data_reader, 76)?;
|
|
||||||
|
|
||||||
let file_name = common::string_from_bytes(&file_header[0..60]);
|
println!("\nFile: {}, Size: {}", file_header.file_name(), file_header.real_size);
|
||||||
|
|
||||||
let real_size = u32::from_le_bytes(file_header[60..64].try_into().unwrap());
|
let data = common::read_exact(&mut data_reader, file_header.stored_size as usize)?;
|
||||||
|
|
||||||
let stored_size = u32::from_le_bytes(file_header[64..68].try_into().unwrap());
|
let output_path = Path::new(&output_folder).join(file_header.file_name().trim_start_matches('/'));
|
||||||
|
|
||||||
let _header_size = u32::from_le_bytes(file_header[68..72].try_into().unwrap());
|
|
||||||
|
|
||||||
println!("\nFile: {}, Size: {}", file_name, real_size);
|
|
||||||
|
|
||||||
let data = common::read_exact(&mut data_reader, stored_size as usize)?;
|
|
||||||
|
|
||||||
let output_path = Path::new(&output_folder).join(file_name.trim_start_matches('/'));
|
|
||||||
|
|
||||||
if let Some(parent) = output_path.parent() {
|
if let Some(parent) = output_path.parent() {
|
||||||
fs::create_dir_all(parent)?;
|
fs::create_dir_all(parent)?;
|
||||||
@@ -160,7 +168,7 @@ pub fn extract_pfl_upg(mut file: &File, output_folder: &str) -> Result<(), Box<d
|
|||||||
.create(true)
|
.create(true)
|
||||||
.open(output_path)?;
|
.open(output_path)?;
|
||||||
|
|
||||||
out_file.write_all(&data[..real_size as usize])?;
|
out_file.write_all(&data[..file_header.real_size as usize])?;
|
||||||
|
|
||||||
println!("- Saved file!");
|
println!("- Saved file!");
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-35
@@ -3,10 +3,37 @@ use std::path::{Path};
|
|||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::fs::{self, File, OpenOptions};
|
use std::fs::{self, File, OpenOptions};
|
||||||
|
|
||||||
|
use binrw::{BinRead, BinReaderExt};
|
||||||
use flate2::read::GzDecoder;
|
use flate2::read::GzDecoder;
|
||||||
|
|
||||||
use crate::common;
|
use crate::common;
|
||||||
|
|
||||||
|
#[derive(Debug, BinRead)]
|
||||||
|
#[br(little)]
|
||||||
|
struct PIMG {
|
||||||
|
#[br(count = 4)] _magic_bytes: Vec<u8>,
|
||||||
|
_unknown1: u32,
|
||||||
|
size: u32,
|
||||||
|
_unknown2: u32,
|
||||||
|
#[br(count = 16)] _checksum: Vec<u8>,
|
||||||
|
#[br(count = 16)] name_bytes: Vec<u8>,
|
||||||
|
#[br(count = 64)] dest_dev_bytes: Vec<u8>,
|
||||||
|
#[br(count = 16)] comp_type_bytes: Vec<u8>,
|
||||||
|
#[br(count = 1032)] _comment: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PIMG {
|
||||||
|
fn name(&self) -> String {
|
||||||
|
common::string_from_bytes(&self.name_bytes)
|
||||||
|
}
|
||||||
|
fn dest_dev(&self) -> String {
|
||||||
|
common::string_from_bytes(&self.dest_dev_bytes)
|
||||||
|
}
|
||||||
|
fn comp_type(&self) -> String {
|
||||||
|
common::string_from_bytes(&self.comp_type_bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_tpv_timg_file(file: &File) -> bool {
|
pub fn is_tpv_timg_file(file: &File) -> bool {
|
||||||
let header = common::read_file(&file, 0, 4).expect("Failed to read from file.");
|
let header = common::read_file(&file, 0, 4).expect("Failed to read from file.");
|
||||||
if header == b"TIMG" {
|
if header == b"TIMG" {
|
||||||
@@ -28,51 +55,27 @@ pub fn extract_tpv_timg(mut file: &File, output_folder: &str) -> Result<(), Box<
|
|||||||
let _timg = common::read_exact(&mut file, 288)?; //TIMG magic + header
|
let _timg = common::read_exact(&mut file, 288)?; //TIMG magic + header
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
//PIMG
|
let pimg = match file.read_le::<PIMG>() {
|
||||||
let mut pimg = [0u8; 4];
|
Ok(val) => val,
|
||||||
if file.read_exact(&mut pimg).is_err() {
|
Err(_) => break, // EOF
|
||||||
break; //EOF
|
};
|
||||||
} else {
|
let data = common::read_exact(&mut file, pimg.size as usize)?;
|
||||||
assert!(&pimg == b"PIMG", "Invalid PIMG section!");
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = common::read_exact(&mut file, 4)?; //4 bytes 00
|
println!("\nPIMG: Name: {}, Size: {}, Dest: {}, Compression: {}", pimg.name(), pimg.size, pimg.dest_dev(), pimg.comp_type());
|
||||||
|
|
||||||
let size_bytes = common::read_exact(&mut file, 4)?;
|
|
||||||
let size = u32::from_le_bytes(size_bytes.try_into().unwrap());
|
|
||||||
|
|
||||||
let _ = common::read_exact(&mut file, 4)?; //4 bytes 00
|
|
||||||
|
|
||||||
let _checksum = common::read_exact(&mut file, 16)?; //16 bytes checksum? or maybe signature
|
|
||||||
|
|
||||||
let name_bytes = common::read_exact(&mut file, 16)?;
|
|
||||||
let name = common::string_from_bytes(&name_bytes);
|
|
||||||
|
|
||||||
let dev_bytes = common::read_exact(&mut file, 64)?;
|
|
||||||
let dev = common::string_from_bytes(&dev_bytes);
|
|
||||||
|
|
||||||
let comp_bytes = common::read_exact(&mut file, 16)?;
|
|
||||||
let comp_type = common::string_from_bytes(&comp_bytes);
|
|
||||||
|
|
||||||
let _ = common::read_exact(&mut file, 1032)?; //1032 bytes maybe comment? skip this
|
|
||||||
|
|
||||||
let data = common::read_exact(&mut file, size as usize)?;
|
|
||||||
|
|
||||||
println!("\nPIMG: Name: {}, Size: {}, Dest: {}, Compression: {}", name, size, dev, comp_type);
|
|
||||||
|
|
||||||
let out_data;
|
let out_data;
|
||||||
|
|
||||||
if comp_type == "gzip" {
|
if pimg.comp_type() == "gzip" {
|
||||||
println!("- Decompressing gzip...");
|
println!("- Decompressing gzip...");
|
||||||
out_data = decompress_gzip(&data)?;
|
out_data = decompress_gzip(&data)?;
|
||||||
} else if comp_type == "none" {
|
} else if pimg.comp_type() == "none" {
|
||||||
out_data = data;
|
out_data = data;
|
||||||
} else {
|
} else {
|
||||||
println!("- Warning: unsupported compression type!");
|
println!("- Warning: unsupported compression type!");
|
||||||
out_data = data;
|
out_data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
let output_path = Path::new(&output_folder).join(name + ".bin");
|
let output_path = Path::new(&output_folder).join(pimg.name() + ".bin");
|
||||||
|
|
||||||
fs::create_dir_all(&output_folder)?;
|
fs::create_dir_all(&output_folder)?;
|
||||||
let mut out_file = OpenOptions::new()
|
let mut out_file = OpenOptions::new()
|
||||||
@@ -88,5 +91,4 @@ pub fn extract_tpv_timg(mut file: &File, output_folder: &str) -> Result<(), Box<
|
|||||||
println!("\nExtraction finished!");
|
println!("\nExtraction finished!");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user