From 6940f13b258adf3fdea583dbc1bee7305edcf18b Mon Sep 17 00:00:00 2001 From: theubusu <80545678+theubusu@users.noreply.github.com> Date: Fri, 10 Oct 2025 22:04:51 +0200 Subject: [PATCH] change epk1 to structs and more --- TODO.md | 2 +- src/formats/epk1.rs | 102 +++++++++++++++++++--------------------- src/formats/epk2.rs | 71 +++++++++++++++------------- src/formats/novatek.rs | 6 +-- src/formats/pfl_upg.rs | 8 +--- src/formats/tpv_timg.rs | 3 -- 6 files changed, 91 insertions(+), 101 deletions(-) diff --git a/TODO.md b/TODO.md index 81240f3..34291a1 100644 --- a/TODO.md +++ b/TODO.md @@ -11,4 +11,4 @@ - LG Epk2 (Crypted and plain header)- 100% complete (unless unencrypted versions exist >) - LG epk3 - Probably fine??? but needs more testing (and more stolen keys) -Todo: use STRUCTS on everything \ No newline at end of file +Todo: use STRUCTS on everything and move them to seperate files probably \ No newline at end of file diff --git a/src/formats/epk1.rs b/src/formats/epk1.rs index f5d02a4..d8c64b2 100644 --- a/src/formats/epk1.rs +++ b/src/formats/epk1.rs @@ -3,8 +3,38 @@ use std::path::{Path}; use std::fs::{self, OpenOptions}; use std::io::{Write, Seek, SeekFrom}; +use binrw::{BinRead, BinReaderExt}; + use crate::common; +#[derive(BinRead)] +struct CommonHeader { + #[br(count = 4)] _magic_bytes: Vec, + file_size: u32, + pak_count: u32, +} + +#[derive(BinRead)] +struct Pak { + offset : u32, + size : u32, +} + +#[derive(BinRead)] +struct PakHeader { + #[br(count = 4)] pak_name_bytes: Vec, + stored_size: u32, + #[br(count = 15)] platform_id_bytes: Vec, +} +impl PakHeader { + fn pak_name(&self) -> String { + common::string_from_bytes(&self.pak_name_bytes) + } + fn platform_id(&self) -> String { + common::string_from_bytes(&self.platform_id_bytes) + } +} + pub fn is_epk1_file(file: &File) -> bool { let header = common::read_file(&file, 0, 4).expect("Failed to read from file."); if header == b"epak" { @@ -14,11 +44,6 @@ pub fn is_epk1_file(file: &File) -> bool { } } -struct Pak { - offset : u32, - size : u32, -} - pub fn extract_epk1(mut file: &File, output_folder: &str) -> Result<(), Box> { //check type of epk1 let epk1_type; @@ -43,59 +68,39 @@ pub fn extract_epk1(mut file: &File, output_folder: &str) -> Result<(), Box = Vec::new(); if epk1_type == "be" { - let _epak = common::read_exact(&mut file, 4)?; //epak magic - - let file_size_bytes = common::read_exact(&mut file, 4)?; - let file_size = u32::from_be_bytes(file_size_bytes.try_into().unwrap()); - - let pak_count_bytes = common::read_exact(&mut file, 4)?; - let pak_count = u32::from_be_bytes(pak_count_bytes.try_into().unwrap()); + let header: CommonHeader = file.read_be()?; for _i in 0..10 { //header can fit max 10 pak entries - let pak_offset_bytes = common::read_exact(&mut file, 4)?; - let pak_offset = u32::from_be_bytes(pak_offset_bytes.try_into().unwrap()); + let pak: Pak = file.read_be()?; - let pak_size_bytes = common::read_exact(&mut file, 4)?; - let pak_size = u32::from_be_bytes(pak_size_bytes.try_into().unwrap()); - - if pak_offset == 0 && pak_size == 0 { + if pak.offset == 0 && pak.size == 0 { continue; } - paks.push(Pak { offset: pak_offset, size: pak_size }); + paks.push(Pak { offset: pak.offset, size: pak.size }); } - assert!(pak_count as usize == paks.len(), "Paks count in header does not match the amount of non empty pak entries!"); + assert!(header.pak_count as usize == paks.len(), "Paks count in header does not match the amount of non empty pak entries!"); let version = common::read_exact(&mut file, 4)?; println!("EPK info:\nFile size: {}\nPak count: {}\nVersion: {:02x?}.{:02x?}.{:02x?}", - file_size, pak_count, version[1], version[2], version[3]); + header.file_size, header.pak_count, version[1], version[2], version[3]); } else if epk1_type == "le" { - let _epak = common::read_exact(&mut file, 4)?; //epak magic - - let file_size_bytes = common::read_exact(&mut file, 4)?; - let file_size = u32::from_le_bytes(file_size_bytes.try_into().unwrap()); - - let pak_count_bytes = common::read_exact(&mut file, 4)?; - let pak_count = u32::from_le_bytes(pak_count_bytes.try_into().unwrap()); + let header: CommonHeader = file.read_le()?; for _i in 0..20 { //header can fit max 20 pak entries - let pak_offset_bytes = common::read_exact(&mut file, 4)?; - let pak_offset = u32::from_le_bytes(pak_offset_bytes.try_into().unwrap()); + let pak: Pak = file.read_le()?; - let pak_size_bytes = common::read_exact(&mut file, 4)?; - let pak_size = u32::from_le_bytes(pak_size_bytes.try_into().unwrap()); - - if pak_offset == 0 && pak_size == 0 { + if pak.offset == 0 && pak.size == 0 { continue; } - paks.push(Pak { offset: pak_offset, size: pak_size }); + paks.push(Pak { offset: pak.offset, size: pak.size }); } - assert!(pak_count as usize == paks.len(), "Paks count in header does not match the amount of non empty pak entries!"); + assert!(header.pak_count as usize == paks.len(), "Paks count in header does not match the amount of non empty pak entries!"); let version = common::read_exact(&mut file, 4)?; @@ -103,29 +108,18 @@ pub fn extract_epk1(mut file: &File, output_folder: &str) -> Result<(), Box Result<(), Box, + file_size: u32, + pak_count: u32, + #[br(count = 4)] _epk2_magic: Vec, + #[br(count = 4)] version: Vec, + #[br(count = 32)] ota_id_bytes: Vec, +} +impl Header { + fn ota_id(&self) -> String { + common::string_from_bytes(&self.ota_id_bytes) + } +} + +#[derive(BinRead)] +struct PakEntry { + offset: u32, + size: u32, + #[br(count = 4)] name_bytes: Vec, + #[br(count = 4)] _version: Vec, + segment_size: u32, +} +impl PakEntry { + fn name(&self) -> String { + common::string_from_bytes(&self.name_bytes) + } +} + pub fn is_epk2_file(file: &File) -> bool { let header = common::read_file(&file, 128, 4).expect("Failed to read from file."); if header == b"epak" { @@ -48,46 +79,20 @@ pub fn extract_epk2(mut file: &File, output_folder: &str) -> Result<(), Box = Vec::new(); //parse paks in header - for i in 0..pak_count { - let offset_bytes = common::read_exact(&mut hdr_reader, 4)?; - let offset = u32::from_le_bytes(offset_bytes.try_into().unwrap()) + 128; //add 128 bytes of initial signature + for i in 0..hdr.pak_count { + let pak: PakEntry = hdr_reader.read_le()?; - let size_bytes = common::read_exact(&mut hdr_reader, 4)?; - let size = u32::from_le_bytes(size_bytes.try_into().unwrap()); + println!("Pak {}: {}, offset: {}, size: {}, segment size: {}", i + 1, pak.name(), pak.offset + 128, pak.size, pak.segment_size); - let name_bytes = common::read_exact(&mut hdr_reader, 4)?; - let name = common::string_from_bytes(&name_bytes); - - let _version = common::read_exact(&mut hdr_reader, 4)?; - - let segment_size_bytes = common::read_exact(&mut hdr_reader, 4)?; - let segment_size = u32::from_le_bytes(segment_size_bytes.try_into().unwrap()); - - println!("Pak {}: {}, offset: {}, size: {}, segment size: {}", i + 1, name, offset, size, segment_size); - - paks.push(Pak { offset, size, name }); + paks.push(Pak { offset: pak.offset + 128, size: pak.size, name: pak.name() }); } let mut signature_count = 0; diff --git a/src/formats/novatek.rs b/src/formats/novatek.rs index 038d4ff..6b322e4 100644 --- a/src/formats/novatek.rs +++ b/src/formats/novatek.rs @@ -7,8 +7,7 @@ use binrw::{BinRead, BinReaderExt}; use crate::common; -#[derive(Debug, BinRead)] -#[br(little)] +#[derive(BinRead)] struct Header { #[br(count = 4)] _magic_bytes: Vec, #[br(count = 4)] _flags: Vec, @@ -19,8 +18,7 @@ struct Header { #[br(count = 116)] _unknown2: Vec, } -#[derive(Debug, BinRead)] -#[br(little)] +#[derive(BinRead)] struct PartEntry { #[br(count = 16)] _unknown: Vec, index: u32, diff --git a/src/formats/pfl_upg.rs b/src/formats/pfl_upg.rs index 6a48c59..fb23844 100644 --- a/src/formats/pfl_upg.rs +++ b/src/formats/pfl_upg.rs @@ -12,8 +12,7 @@ use binrw::{BinRead, BinReaderExt}; use crate::common; use crate::keys; -#[derive(Debug, BinRead)] -#[br(little)] +#[derive(BinRead)] struct Header { #[br(count = 8)] _magic_bytes: Vec, header_size: u32, @@ -24,15 +23,13 @@ struct Header { _padding2: u32, #[br(count = 512)] description_bytes: Vec, } - impl Header { fn description(&self) -> String { common::string_from_bytes(&self.description_bytes) } } -#[derive(Debug, BinRead)] -#[br(little)] +#[derive(BinRead)] struct FileHeader { #[br(count = 60)] file_name_bytes: Vec, real_size: u32, @@ -40,7 +37,6 @@ struct FileHeader { _header_size: u32, _attributes: u32, } - impl FileHeader { fn file_name(&self) -> String { common::string_from_bytes(&self.file_name_bytes) diff --git a/src/formats/tpv_timg.rs b/src/formats/tpv_timg.rs index 1b505ca..04b8e06 100644 --- a/src/formats/tpv_timg.rs +++ b/src/formats/tpv_timg.rs @@ -9,7 +9,6 @@ use flate2::read::GzDecoder; use crate::common; #[derive(Debug, BinRead)] -#[br(little)] struct PIMG { #[br(count = 4)] _magic_bytes: Vec, _unknown1: u32, @@ -21,7 +20,6 @@ struct PIMG { #[br(count = 16)] comp_type_bytes: Vec, #[br(count = 1032)] _comment: Vec, } - impl PIMG { fn name(&self) -> String { common::string_from_bytes(&self.name_bytes) @@ -50,7 +48,6 @@ fn decompress_gzip(compressed_data: &[u8]) -> Result, Box Result<(), Box> { let _timg = common::read_exact(&mut file, 288)?; //TIMG magic + header