feat: Handle file variants

This commit is contained in:
Lucas Schwiderski 2022-12-11 12:09:31 +01:00
parent 764d9c00f2
commit f94a8c8731
Signed by: lucas
GPG key ID: AA12679AAA6DF4D8
2 changed files with 49 additions and 34 deletions

View file

@ -237,8 +237,8 @@ where
Box::new(bundle.files().iter()) Box::new(bundle.files().iter())
} else { } else {
let iter = bundle.files().iter().filter(|file| { let iter = bundle.files().iter().filter(|file| {
let name = file.name(false); let name = file.name(false, None);
let decompiled_name = file.name(true); let decompiled_name = file.name(true, None);
// When there is no `includes`, all files are included // When there is no `includes`, all files are included
let is_included = includes.is_empty() let is_included = includes.is_empty()
@ -275,7 +275,7 @@ where
let mut tasks = Vec::with_capacity(bundle.files().len()); let mut tasks = Vec::with_capacity(bundle.files().len());
for file in files { for file in files {
let name = file.name(options.decompile); let name = file.name(options.decompile, None);
let data = if options.decompile { let data = if options.decompile {
file.decompiled(ctx.clone()).await file.decompiled(ctx.clone()).await
} else { } else {

View file

@ -323,6 +323,7 @@ impl From<BundleFileType> for Murmur64 {
} }
struct BundleFileHeader { struct BundleFileHeader {
variant: u32,
size: usize, size: usize,
} }
@ -332,18 +333,10 @@ impl BundleFileHeader {
where where
R: AsyncRead + AsyncSeek + std::marker::Unpin, R: AsyncRead + AsyncSeek + std::marker::Unpin,
{ {
// NOTE: One of these must be the version number, or any kind of let variant = read_u32(r).await?;
// identifier between the different file entries. skip_u8(r, 0).await?;
// Back in VT2 days, these different 'files' were used to separate
// versions, e.g. different languages for the same `.strings` file.
skip_u32(r, 0).await?;
skip_u32(r, 0).await?;
skip_u32(r, 0).await?;
let size_1 = read_u32(r).await? as usize; let size_1 = read_u32(r).await? as usize;
skip_u8(r, 1).await?; skip_u8(r, 1).await?;
let size_2 = read_u32(r).await? as usize; let size_2 = read_u32(r).await? as usize;
tracing::debug!(size_1, size_2); tracing::debug!(size_1, size_2);
@ -355,7 +348,7 @@ impl BundleFileHeader {
size_1 size_1
}; };
Ok(Self { size }) Ok(Self { size, variant })
} }
} }
@ -396,12 +389,13 @@ impl BundleFile {
let hash = Murmur64::from(read_u64(r).await?); let hash = Murmur64::from(read_u64(r).await?);
let name = lookup_hash(ctx, hash, HashGroup::Filename).await; let name = lookup_hash(ctx, hash, HashGroup::Filename).await;
let header_count = read_u8(r) let header_count = read_u32(r)
.await .await
.with_section(|| format!("{}.{}", name, file_type.ext_name()).header("File:"))?; .with_section(|| format!("{}.{}", name, file_type.ext_name()).header("File:"))?;
let header_count = header_count as usize; let header_count = header_count as usize;
let mut headers = Vec::with_capacity(header_count); let mut headers = Vec::with_capacity(header_count);
skip_u32(r, 0).await?;
for _ in 0..header_count { for _ in 0..header_count {
let header = BundleFileHeader::read(r) let header = BundleFileHeader::read(r)
@ -438,19 +432,18 @@ impl BundleFile {
write_u64(w, *self.hash).await?; write_u64(w, *self.hash).await?;
let header_count = self.variants.len(); let header_count = self.variants.len();
write_u8(w, header_count as u8).await?; write_u32(w, header_count as u32).await?;
// TODO: Unknown what this is
write_u32(w, 0).await?;
for variant in self.variants.iter() { for variant in self.variants.iter() {
// TODO: Unknown what these are // TODO: Unknown what these are
write_u32(w, 0).await?; write_u32(w, variant.header.variant).await?;
write_u32(w, 0).await?; // TODO: Unknown what this is
write_u32(w, 0).await?; write_u8(w, 0).await?;
write_u32(w, variant.data.len() as u32).await?; write_u32(w, variant.data.len() as u32).await?;
// TODO: Unknown what this is // TODO: Unknown what this is
write_u8(w, 1).await?; write_u8(w, 1).await?;
// TODO: The previous size value and this one are somehow connected, // TODO: The previous size value and this one are somehow connected,
// but so far it is unknown how // but so far it is unknown how
write_u32(w, 0).await?; write_u32(w, 0).await?;
@ -467,12 +460,22 @@ impl BundleFile {
&self.name &self.name
} }
pub fn name(&self, decompiled: bool) -> String { pub fn name(&self, decompiled: bool, variant: Option<u32>) -> String {
if decompiled { let mut s = self.name.clone();
format!("{}.{}", self.name, self.file_type.decompiled_ext_name()) s.push('.');
} else {
format!("{}.{}", self.name, self.file_type.ext_name()) if let Some(variant) = variant {
s.push_str(&variant.to_string());
s.push('.');
} }
if decompiled {
s.push_str(&self.file_type.decompiled_ext_name());
} else {
s.push_str(&self.file_type.ext_name());
}
s
} }
pub fn matches_name<S>(&self, name: S) -> bool pub fn matches_name<S>(&self, name: S) -> bool
@ -480,7 +483,7 @@ impl BundleFile {
S: AsRef<str>, S: AsRef<str>,
{ {
let name = name.as_ref(); let name = name.as_ref();
self.name == name || self.name(false) == name || self.name(true) == name self.name == name || self.name(false, None) == name || self.name(true, None) == name
} }
pub fn hash(&self) -> Murmur64 { pub fn hash(&self) -> Murmur64 {
@ -503,9 +506,16 @@ impl BundleFile {
let files = self let files = self
.variants .variants
.iter() .iter()
.map(|variant| UserFile { .map(|variant| {
let name = if self.variants.len() > 1 {
self.name(false, Some(variant.header.variant))
} else {
self.name(false, None)
};
UserFile {
data: variant.data().to_vec(), data: variant.data().to_vec(),
name: Some(self.name(false)), name: Some(name),
}
}) })
.collect(); .collect();
@ -518,7 +528,7 @@ impl BundleFile {
if tracing::enabled!(tracing::Level::DEBUG) { if tracing::enabled!(tracing::Level::DEBUG) {
tracing::debug!( tracing::debug!(
name = self.name(true), name = self.name(true, None),
variants = self.variants.len(), variants = self.variants.len(),
"Attempting to decompile" "Attempting to decompile"
); );
@ -529,6 +539,11 @@ impl BundleFile {
async move { async move {
let data = variant.data(); let data = variant.data();
let name = if self.variants.len() > 1 {
self.name(true, Some(variant.header.variant))
} else {
self.name(true, None)
};
let res = match file_type { let res = match file_type {
BundleFileType::Lua => lua::decompile(ctx, data).await, BundleFileType::Lua => lua::decompile(ctx, data).await,
@ -538,7 +553,7 @@ impl BundleFile {
} }
_ => { _ => {
tracing::debug!("Can't decompile, unknown file type"); tracing::debug!("Can't decompile, unknown file type");
Ok(vec![UserFile::with_name(data.to_vec(), self.name(true))]) Ok(vec![UserFile::with_name(data.to_vec(), name.clone())])
} }
}; };
@ -547,7 +562,7 @@ impl BundleFile {
Err(err) => { Err(err) => {
let err = err let err = err
.wrap_err("failed to decompile file") .wrap_err("failed to decompile file")
.with_section(|| self.name(true).header("File:")); .with_section(|| name.header("File:"));
tracing::error!("{:?}", err); tracing::error!("{:?}", err);
vec![] vec![]
} }