Add support for wuthering waves custom format

This commit is contained in:
xavo95 2025-01-13 05:42:11 +01:00
parent cd349a95f5
commit 44d90fad11
4 changed files with 84 additions and 13 deletions

View file

@ -15,6 +15,7 @@ oodle_loader = ["dep:oodle_loader"]
oodle_explicit = ["oodle"] oodle_explicit = ["oodle"]
oodle_implicit_dynamic = ["dep:oodle_loader", "oodle"] oodle_implicit_dynamic = ["dep:oodle_loader", "oodle"]
encryption = ["dep:aes"] encryption = ["dep:aes"]
wuthering-waves = []
[dependencies] [dependencies]
byteorder = "1.5" byteorder = "1.5"

View file

@ -309,7 +309,21 @@ impl Entry {
reader: &mut R, reader: &mut R,
version: super::Version, version: super::Version,
) -> Result<Self, super::Error> { ) -> Result<Self, super::Error> {
let bits = reader.read_u32::<LE>()?;
let bits = {
let tmp = reader.read_u32::<LE>()?;
#[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 { let compression = match (bits >> 23) & 0x3f {
0 => None, 0 => None,
n => Some(n - 1), n => Some(n - 1),
@ -333,8 +347,19 @@ impl Entry {
}) })
}; };
let offset = var_int(31)?; let (offset, uncompressed) = {
let uncompressed = var_int(30)?; 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 { let compressed = match compression {
None => uncompressed, None => uncompressed,
_ => var_int(29)?, _ => var_int(29)?,
@ -382,7 +407,7 @@ impl Entry {
}) })
} }
pub fn write_encoded<W: io::Write>(&self, writer: &mut W) -> Result<(), super::Error> { pub fn write_encoded<W: io::Write>(&self, writer: &mut W, version: Version) -> Result<(), super::Error> {
let mut compression_block_size = (self.compression_block_size >> 11) & 0x3f; let mut compression_block_size = (self.compression_block_size >> 11) & 0x3f;
if (compression_block_size << 11) != self.compression_block_size { if (compression_block_size << 11) != self.compression_block_size {
compression_block_size = 0x3f; compression_block_size = 0x3f;
@ -404,22 +429,61 @@ impl Entry {
| ((is_uncompressed_size_32_bit_safe as u32) << 30) | ((is_uncompressed_size_32_bit_safe as u32) << 30)
| ((is_offset_32_bit_safe as u32) << 31); | ((is_offset_32_bit_safe as u32) << 31);
#[cfg(not(feature = "wuthering-waves"))]
writer.write_u32::<LE>(flags)?; writer.write_u32::<LE>(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::<LE>(tmp)?;
writer.write_u8(0)?;
} else {
writer.write_u32::<LE>(flags)?;
}
if compression_block_size == 0x3f { if compression_block_size == 0x3f {
writer.write_u32::<LE>(self.compression_block_size)?; writer.write_u32::<LE>(self.compression_block_size)?;
} }
if is_offset_32_bit_safe { #[cfg(not(feature = "wuthering-waves"))]
writer.write_u32::<LE>(self.offset as u32)?; {
} else { if is_offset_32_bit_safe {
writer.write_u64::<LE>(self.offset)?; writer.write_u32::<LE>(self.offset as u32)?;
} } else {
writer.write_u64::<LE>(self.offset)?;
}
if is_uncompressed_size_32_bit_safe { if is_uncompressed_size_32_bit_safe {
writer.write_u32::<LE>(self.uncompressed as u32)? writer.write_u32::<LE>(self.uncompressed as u32)?
} else {
writer.write_u64::<LE>(self.uncompressed)?
}
}
#[cfg(feature = "wuthering-waves")]
if version == Version::V12 {
if is_uncompressed_size_32_bit_safe {
writer.write_u32::<LE>(self.uncompressed as u32)?
} else {
writer.write_u64::<LE>(self.uncompressed)?
}
if is_offset_32_bit_safe {
writer.write_u32::<LE>(self.offset as u32)?;
} else {
writer.write_u64::<LE>(self.offset)?;
}
} else { } else {
writer.write_u64::<LE>(self.uncompressed)? if is_offset_32_bit_safe {
writer.write_u32::<LE>(self.offset as u32)?;
} else {
writer.write_u64::<LE>(self.offset)?;
}
if is_uncompressed_size_32_bit_safe {
writer.write_u32::<LE>(self.uncompressed as u32)?
} else {
writer.write_u64::<LE>(self.uncompressed)?
}
} }
if self.compression_slot.is_some() { if self.compression_slot.is_some() {

View file

@ -45,6 +45,8 @@ pub enum Version {
V9, V9,
V10, V10,
V11, V11,
#[cfg(feature = "wuthering-waves")]
V12,
} }
#[repr(u32)] #[repr(u32)]
@ -65,6 +67,8 @@ pub enum VersionMajor {
FrozenIndex, // v9 frozen index byte included FrozenIndex, // v9 frozen index byte included
PathHashIndex, // v10 PathHashIndex, // v10
Fnv64BugFix, // v11 Fnv64BugFix, // v11
#[cfg(feature = "wuthering-waves")]
WuwaCustom, // v12
} }
// strum shouldn't need to be installed by users // strum shouldn't need to be installed by users
@ -115,6 +119,8 @@ impl Version {
Version::V9 => VersionMajor::FrozenIndex, Version::V9 => VersionMajor::FrozenIndex,
Version::V10 => VersionMajor::PathHashIndex, Version::V10 => VersionMajor::PathHashIndex,
Version::V11 => VersionMajor::Fnv64BugFix, Version::V11 => VersionMajor::Fnv64BugFix,
#[cfg(feature = "wuthering-waves")]
Version::V12 => VersionMajor::WuwaCustom,
} }
} }
} }

View file

@ -479,7 +479,7 @@ impl Pak {
let mut encoded_entries = io::Cursor::new(vec![]); let mut encoded_entries = io::Cursor::new(vec![]);
for entry in self.index.entries.values() { for entry in self.index.entries.values() {
offsets.push(encoded_entries.get_ref().len() as u32); 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) (encoded_entries.into_inner(), offsets)
}; };