From 002eda061260915798dd51a1a9a2093a7650126e Mon Sep 17 00:00:00 2001 From: G2-Games Date: Thu, 11 Jul 2024 22:36:55 -0500 Subject: [PATCH] Fixed an edge case If the offset size was equal to 2048, the program set it to 2048 instead of 0 incorrectly --- luca_pak/src/entry.rs | 4 ++++ luca_pak/src/header.rs | 5 +++-- luca_pak/src/lib.rs | 40 +++++++++++++++++++++++++++++----------- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/luca_pak/src/entry.rs b/luca_pak/src/entry.rs index 8a110ce..bb7d443 100644 --- a/luca_pak/src/entry.rs +++ b/luca_pak/src/entry.rs @@ -33,6 +33,10 @@ impl Entry { &self.name } + pub fn index(&self) -> usize { + self.index + } + pub fn id(&self) -> u32 { self.id } diff --git a/luca_pak/src/header.rs b/luca_pak/src/header.rs index d019cba..88d2ded 100644 --- a/luca_pak/src/header.rs +++ b/luca_pak/src/header.rs @@ -14,7 +14,8 @@ pub struct Header { pub(super) id_start: u32, pub(super) block_size: u32, - pub(super) unknown1: u32, + /// The offset of the subdirectory name within the PAK + pub(super) subdir_offset: u32, pub(super) unknown2: u32, pub(super) unknown3: u32, pub(super) unknown4: u32, @@ -28,7 +29,7 @@ impl Header { output.write_u32::(self.entry_count)?; output.write_u32::(self.id_start)?; output.write_u32::(self.block_size)?; - output.write_u32::(self.unknown1)?; + output.write_u32::(self.subdir_offset)?; output.write_u32::(self.unknown2)?; output.write_u32::(self.unknown3)?; output.write_u32::(self.unknown4)?; diff --git a/luca_pak/src/lib.rs b/luca_pak/src/lib.rs index 9222a27..73ed4d0 100644 --- a/luca_pak/src/lib.rs +++ b/luca_pak/src/lib.rs @@ -33,6 +33,8 @@ pub enum PakError { /// A full PAK file with a header and its contents #[derive(Debug, Clone)] pub struct Pak { + subdirectory: Option, + /// The path of the PAK file, can serve as an identifier or name as the /// header has no name for the file. path: PathBuf, @@ -72,7 +74,7 @@ impl Pak { entry_count: input.read_u32::()?, id_start: input.read_u32::()?, block_size: input.read_u32::()?, - unknown1: input.read_u32::()?, + subdir_offset: input.read_u32::()?, unknown2: input.read_u32::()?, unknown3: input.read_u32::()?, unknown4: input.read_u32::()?, @@ -130,16 +132,15 @@ impl Pak { // Read all the file names let mut file_names = None; + let mut subdirectory = None; if header.flags.has_names() { debug!("READING: file_names"); - let mut string_buf = Vec::new(); + if header.subdir_offset != 0 { + subdirectory = Some(read_cstring(&mut input)?); + } file_names = Some(Vec::new()); for _ in 0..header.entry_count() { - string_buf.clear(); - input.read_until(0x00, &mut string_buf)?; - string_buf.pop(); - - let strbuf = String::from_utf8_lossy(&string_buf).to_string(); + let strbuf = read_cstring(&mut input)?; file_names.as_mut().unwrap().push(strbuf.clone()); } } @@ -189,6 +190,7 @@ impl Pak { debug!("Entry list contains {} entries", entries.len()); Ok(Pak { + subdirectory, header, unknown_pre_data, entries, @@ -237,6 +239,11 @@ impl Pak { // Write names if the flags indicate it should have them if self.header.flags().has_names() { + if let Some(subdir) = &self.subdirectory { + output.write_all( + CString::new(subdir.as_bytes()).unwrap().to_bytes_with_nul() + )?; + } for entry in self.entries() { let name = entry.name.as_ref().unwrap(); output.write_all( @@ -251,11 +258,14 @@ impl Pak { for entry in self.entries() { let block_size = entry.data.len().div_ceil(self.header().block_size as usize); - let remainder = 2048 - entry.data.len().rem_euclid(self.header().block_size as usize); + let mut remainder = 2048 - entry.data.len().rem_euclid(self.header().block_size as usize); + if remainder == 2048 { + remainder = 0; + } - debug!("entry {:?} len {}", entry.name(), entry.data.len()); - debug!("remainder {}", remainder); - debug!("block_offset {} - expected offset {}", block_offset, entry.offset); + println!("entry len {}", entry.data.len()); + println!("remainder {}", remainder); + println!("block_offset {} - expected offset {}", block_offset, entry.offset); output.write_all(&entry.data)?; output.write_all(&vec![0u8; remainder])?; block_offset += block_size as u32; @@ -384,3 +394,11 @@ impl Pak { .is_some_and(|n| n == name)) } } + +fn read_cstring(input: &mut T) -> Result { + let mut string_buf = vec![]; + input.read_until(0x00, &mut string_buf)?; + string_buf.pop(); + + Ok(String::from_utf8_lossy(&string_buf).to_string()) +}