diff --git a/repak/Cargo.toml b/repak/Cargo.toml index c9e412f..8c83e46 100644 --- a/repak/Cargo.toml +++ b/repak/Cargo.toml @@ -15,6 +15,7 @@ oodle_loader = ["dep:oodle_loader"] oodle_explicit = ["oodle"] oodle_implicit_dynamic = ["dep:oodle_loader", "oodle"] encryption = ["dep:aes"] +wuthering-waves = [] [dependencies] byteorder = "1.5" diff --git a/repak/src/entry.rs b/repak/src/entry.rs index b5f25e7..a0a1643 100644 --- a/repak/src/entry.rs +++ b/repak/src/entry.rs @@ -309,7 +309,21 @@ impl Entry { reader: &mut R, version: super::Version, ) -> Result { - let bits = reader.read_u32::()?; + + let bits = { + let tmp = reader.read_u32::()?; + #[cfg(not(feature = "wuthering-waves"))] + { tmp } + #[cfg(feature = "wuthering-waves")] + if version == Version::V12 { + reader.read_u8()?; + (tmp >> 16) & 0x3f | (tmp & 0xFFFF) << 6 | (tmp & (1 << 28)) >> 6 | + (tmp & 0x0FC00000) << 1 | tmp & 0xE0000000 + } else { + tmp + } + }; + let compression = match (bits >> 23) & 0x3f { 0 => None, n => Some(n - 1), @@ -333,8 +347,19 @@ impl Entry { }) }; - let offset = var_int(31)?; - let uncompressed = var_int(30)?; + let (offset, uncompressed) = { + let offset = var_int(31)?; + let uncompressed = var_int(30)?; + #[cfg(not(feature = "wuthering-waves"))] + { (offset, uncompressed) } + #[cfg(feature = "wuthering-waves")] + if version == Version::V12 { + (uncompressed, offset) + } else { + (offset, uncompressed) + } + }; + let compressed = match compression { None => uncompressed, _ => var_int(29)?, @@ -382,7 +407,7 @@ impl Entry { }) } - pub fn write_encoded(&self, writer: &mut W) -> Result<(), super::Error> { + pub fn write_encoded(&self, writer: &mut W, version: Version) -> Result<(), super::Error> { let mut compression_block_size = (self.compression_block_size >> 11) & 0x3f; if (compression_block_size << 11) != self.compression_block_size { compression_block_size = 0x3f; @@ -404,22 +429,61 @@ impl Entry { | ((is_uncompressed_size_32_bit_safe as u32) << 30) | ((is_offset_32_bit_safe as u32) << 31); + #[cfg(not(feature = "wuthering-waves"))] writer.write_u32::(flags)?; + #[cfg(feature = "wuthering-waves")] + if version == Version::V12 { + let tmp = ((flags & 0x3f) << 16) | ((flags >> 6) & 0xFFFF) | + ((flags << 6) & (1 << 28)) | ((flags >> 1) & 0x0FC00000) | flags & 0xE0000000; + writer.write_u32::(tmp)?; + writer.write_u8(0)?; + } else { + writer.write_u32::(flags)?; + } if compression_block_size == 0x3f { writer.write_u32::(self.compression_block_size)?; } - if is_offset_32_bit_safe { - writer.write_u32::(self.offset as u32)?; - } else { - writer.write_u64::(self.offset)?; - } + #[cfg(not(feature = "wuthering-waves"))] + { + if is_offset_32_bit_safe { + writer.write_u32::(self.offset as u32)?; + } else { + writer.write_u64::(self.offset)?; + } - if is_uncompressed_size_32_bit_safe { - writer.write_u32::(self.uncompressed as u32)? + if is_uncompressed_size_32_bit_safe { + writer.write_u32::(self.uncompressed as u32)? + } else { + writer.write_u64::(self.uncompressed)? + } + } + #[cfg(feature = "wuthering-waves")] + if version == Version::V12 { + if is_uncompressed_size_32_bit_safe { + writer.write_u32::(self.uncompressed as u32)? + } else { + writer.write_u64::(self.uncompressed)? + } + + if is_offset_32_bit_safe { + writer.write_u32::(self.offset as u32)?; + } else { + writer.write_u64::(self.offset)?; + } } else { - writer.write_u64::(self.uncompressed)? + if is_offset_32_bit_safe { + writer.write_u32::(self.offset as u32)?; + } else { + writer.write_u64::(self.offset)?; + } + + if is_uncompressed_size_32_bit_safe { + writer.write_u32::(self.uncompressed as u32)? + } else { + writer.write_u64::(self.uncompressed)? + } } if self.compression_slot.is_some() { diff --git a/repak/src/lib.rs b/repak/src/lib.rs index ec4292f..8fbf2f0 100644 --- a/repak/src/lib.rs +++ b/repak/src/lib.rs @@ -45,6 +45,8 @@ pub enum Version { V9, V10, V11, + #[cfg(feature = "wuthering-waves")] + V12, } #[repr(u32)] @@ -65,6 +67,8 @@ pub enum VersionMajor { FrozenIndex, // v9 frozen index byte included PathHashIndex, // v10 Fnv64BugFix, // v11 + #[cfg(feature = "wuthering-waves")] + WuwaCustom, // v12 } // strum shouldn't need to be installed by users @@ -115,6 +119,8 @@ impl Version { Version::V9 => VersionMajor::FrozenIndex, Version::V10 => VersionMajor::PathHashIndex, Version::V11 => VersionMajor::Fnv64BugFix, + #[cfg(feature = "wuthering-waves")] + Version::V12 => VersionMajor::WuwaCustom, } } } diff --git a/repak/src/pak.rs b/repak/src/pak.rs index e3825d0..f570527 100644 --- a/repak/src/pak.rs +++ b/repak/src/pak.rs @@ -479,7 +479,7 @@ impl Pak { let mut encoded_entries = io::Cursor::new(vec![]); for entry in self.index.entries.values() { offsets.push(encoded_entries.get_ref().len() as u32); - entry.write_encoded(&mut encoded_entries)?; + entry.write_encoded(&mut encoded_entries, self.version)?; } (encoded_entries.into_inner(), offsets) };