diff --git a/lib/sdk/src/context.rs b/lib/sdk/src/context.rs index 8c10b3c..c565429 100644 --- a/lib/sdk/src/context.rs +++ b/lib/sdk/src/context.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use std::process::Command; use std::sync::Arc; -use crate::murmur::{Dictionary, HashGroup, IdString64, Murmur32, Murmur64}; +use crate::murmur::{Dictionary, HashGroup, IdString32, IdString64, Murmur32, Murmur64}; #[derive(Clone)] pub struct CmdLine { @@ -87,17 +87,17 @@ impl Context { } } - pub fn lookup_hash_short(&self, hash: M, group: HashGroup) -> String + pub fn lookup_hash_short(&self, hash: M, group: HashGroup) -> IdString32 where M: Into, { let hash = hash.into(); if let Some(s) = self.lookup.lookup_short(hash, group) { tracing::debug!(%hash, string = s, "Murmur32 lookup successful"); - s.to_owned() + s.to_string().into() } else { tracing::debug!(%hash, "Murmur32 lookup failed"); - format!("{hash:08X}") + hash.into() } } } diff --git a/lib/sdk/src/filetype/strings.rs b/lib/sdk/src/filetype/strings.rs index ca2ed8c..e58fca0 100644 --- a/lib/sdk/src/filetype/strings.rs +++ b/lib/sdk/src/filetype/strings.rs @@ -5,7 +5,7 @@ use color_eyre::{Report, Result}; use crate::binary::sync::ReadExt; use crate::bundle::file::{BundleFileVariant, UserFile}; -use crate::murmur::HashGroup; +use crate::murmur::{HashGroup, IdString32}; #[derive(Copy, Clone, PartialEq, Eq, Hash, serde::Serialize)] #[serde(untagged)] @@ -26,7 +26,7 @@ impl Language { } #[derive(serde::Serialize)] -pub struct Strings(HashMap>); +pub struct Strings(HashMap>); fn read_string(r: R) -> Result where @@ -42,7 +42,7 @@ where impl Strings { #[tracing::instrument(skip_all, fields(languages = variants.len()))] pub fn from_variants(ctx: &crate::Context, variants: &Vec) -> Result { - let mut map: HashMap> = HashMap::new(); + let mut map: HashMap> = HashMap::new(); for (i, variant) in variants.iter().enumerate() { let _span = tracing::trace_span!("variant {}", i); diff --git a/lib/sdk/src/filetype/texture.rs b/lib/sdk/src/filetype/texture.rs index a8c85cd..7486fb8 100644 --- a/lib/sdk/src/filetype/texture.rs +++ b/lib/sdk/src/filetype/texture.rs @@ -11,7 +11,7 @@ use tokio::fs; use crate::binary::sync::{ReadExt, WriteExt}; use crate::bundle::file::UserFile; -use crate::murmur::{IdString32, IdString64}; +use crate::murmur::{HashGroup, IdString32, IdString64}; use crate::{BundleFile, BundleFileType, BundleFileVariant}; bitflags! { @@ -86,8 +86,12 @@ struct Texture { } impl Texture { - #[tracing::instrument(skip(r, stream_r))] - fn from_binary(mut r: impl Read + Seek, mut stream_r: Option) -> Result { + #[tracing::instrument(skip(ctx, r, stream_r))] + fn from_binary( + ctx: &crate::Context, + mut r: impl Read + Seek, + mut stream_r: Option, + ) -> Result { // Looking at the executable in IDA, there is one other valid value: `2`. // If this ever comes up in the game data, I'll have to reverse engineer the // (de)compression algorithm through IDA. @@ -187,7 +191,7 @@ impl Texture { None }; - let category = r.read_u32().map(IdString32::from)?; + let category = ctx.lookup_hash_short(r.read_u32()?, HashGroup::TextureCategory); Ok(Self { category, @@ -265,8 +269,9 @@ struct TextureDefinitionOutput { category: String, } -#[tracing::instrument(skip(data), fields(buf_len = data.as_ref().len()))] +#[tracing::instrument(skip(ctx, data), fields(buf_len = data.as_ref().len()))] pub(crate) async fn decompile_data( + ctx: &crate::Context, name: String, data: impl AsRef<[u8]>, stream_file_name: Option, @@ -281,7 +286,7 @@ pub(crate) async fn decompile_data( None }; - let texture = Texture::from_binary(&mut r, stream_r.as_mut())?; + let texture = Texture::from_binary(ctx, &mut r, stream_r.as_mut())?; let files = texture.to_user_files(name); Ok(files) } @@ -300,7 +305,7 @@ pub(crate) async fn decompile( None => PathBuf::from("bundle").join(name), }); - return decompile_data(name, variant.data(), stream_file_name).await; + return decompile_data(ctx, name, variant.data(), stream_file_name).await; } let Some(file_name) = variant.data_file_name() else { @@ -323,7 +328,7 @@ pub(crate) async fn decompile( "Provide a game directory in the config file or make sure the `data` directory is next to the provided bundle." })?; - decompile_data(name, &data, None).await + decompile_data(ctx, name, &data, None).await } #[tracing::instrument(skip(sjson, name), fields(sjson_len = sjson.as_ref().len(), name = %name.display()))] diff --git a/lib/sdk/src/murmur/dictionary.rs b/lib/sdk/src/murmur/dictionary.rs index c1b5636..55e0966 100644 --- a/lib/sdk/src/murmur/dictionary.rs +++ b/lib/sdk/src/murmur/dictionary.rs @@ -12,12 +12,19 @@ pub enum HashGroup { Filename, Filetype, Strings, + TextureCategory, Other, } impl HashGroup { - pub fn all() -> [Self; 3] { - [Self::Filename, Self::Filetype, Self::Other] + pub fn all() -> [Self; 5] { + [ + Self::Filename, + Self::Filetype, + Self::Strings, + Self::TextureCategory, + Self::Other, + ] } } @@ -27,6 +34,7 @@ impl std::fmt::Display for HashGroup { HashGroup::Filename => write!(f, "filename"), HashGroup::Filetype => write!(f, "filetype"), HashGroup::Strings => write!(f, "strings"), + HashGroup::TextureCategory => write!(f, "texture-category"), HashGroup::Other => write!(f, "other"), } }