diff options
-rw-r--r-- | src/common_strings.rs | 109 | ||||
-rw-r--r-- | src/helper.rs | 15 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/main.rs | 91 |
4 files changed, 194 insertions, 22 deletions
diff --git a/src/common_strings.rs b/src/common_strings.rs new file mode 100644 index 0000000..d893c6f --- /dev/null +++ b/src/common_strings.rs @@ -0,0 +1,109 @@ +pub const COMMON_STRINGS: &[u8] = b"AABB\0\ +AnimationClip\0\ +AnimationCurve\0\ +AnimationState\0\ +Array\0\ +Base\0\ +BitField\0\ +bitset\0\ +bool\0\ +char\0\ +ColorRGBA\0\ +Component\0\ +data\0\ +deque\0\ +double\0\ +dynamic_array\0\ +FastPropertyName\0\ +first\0\ +float\0\ +Font\0\ +GameObject\0\ +Generic Mono\0\ +GradientNEW\0\ +GUID\0\ +GUIStyle\0\ +int\0\ +list\0\ +long long\0\ +map\0\ +Matrix4x4f\0\ +MdFour\0\ +MonoBehaviour\0\ +MonoScript\0\ +m_ByteSize\0\ +m_Curve\0\ +m_EditorClassIdentifier\0\ +m_EditorHideFlags\0\ +m_Enabled\0\ +m_ExtensionPtr\0\ +m_GameObject\0\ +m_Index\0\ +m_IsArray\0\ +m_IsStatic\0\ +m_MetaFlag\0\ +m_Name\0\ +m_ObjectHideFlags\0\ +m_PrefabInternal\0\ +m_PrefabParentObject\0\ +m_Script\0\ +m_StaticEditorFlags\0\ +m_Type\0\ +m_Version\0\ +Object\0\ +pair\0\ +PPtr<Component>\0\ +PPtr<GameObject>\0\ +PPtr<Material>\0\ +PPtr<MonoBehaviour>\0\ +PPtr<MonoScript>\0\ +PPtr<Object>\0\ +PPtr<Prefab>\0\ +PPtr<Sprite>\0\ +PPtr<TextAsset>\0\ +PPtr<Texture>\0\ +PPtr<Texture2D>\0\ +PPtr<Transform>\0\ +Prefab\0\ +Quaternionf\0\ +Rectf\0\ +RectInt\0\ +RectOffset\0\ +second\0\ +set\0\ +short\0\ +size\0\ +SInt16\0\ +SInt32\0\ +SInt64\0\ +SInt8\0\ +staticvector\0\ +string\0\ +TextAsset\0\ +TextMesh\0\ +Texture\0\ +Texture2D\0\ +Transform\0\ +TypelessData\0\ +UInt16\0\ +UInt32\0\ +UInt64\0\ +UInt8\0\ +unsigned int\0\ +unsigned long long\0\ +unsigned short\0\ +vector\0\ +Vector2f\0\ +Vector3f\0\ +Vector4f\0\ +m_ScriptingClassIdentifier\0\ +Gradient\0\ +Type*\0\ +int2_storage\0\ +int3_storage\0\ +BoundsInt\0\ +m_CorrespondingSourceObject\0\ +m_PrefabInstance\0\ +m_PrefabAsset\0\ +FileSize\0\ +Hash128"; diff --git a/src/helper.rs b/src/helper.rs index c2b9a92..0b126ad 100644 --- a/src/helper.rs +++ b/src/helper.rs @@ -8,6 +8,8 @@ pub enum Endianness { pub trait ReadExt { fn read_u8(&mut self) -> Result<u8>; + fn read_u16(&mut self, e: Endianness) -> Result<u16>; + fn read_u16_le(&mut self) -> Result<u16>; fn read_u16_be(&mut self) -> Result<u16>; fn read_i16(&mut self, e: Endianness) -> Result<i16>; fn read_i16_be(&mut self) -> Result<i16>; @@ -26,15 +28,26 @@ pub trait ReadExt { } impl<T: Read> ReadExt for T { fn read_u8(&mut self) -> Result<u8> { - let mut buf = [0; 2]; + let mut buf = [0; 1]; self.read_exact(&mut buf)?; Ok(buf[0]) } + fn read_u16(&mut self, e: Endianness) -> Result<u16> { + match e { + Endianness::Big => self.read_u16_be(), + Endianness::Little => self.read_u16_le(), + } + } fn read_u16_be(&mut self) -> Result<u16> { let mut buf = [0; 2]; self.read_exact(&mut buf)?; Ok(u16::from_be_bytes(buf)) } + fn read_u16_le(&mut self) -> Result<u16> { + let mut buf = [0; 2]; + self.read_exact(&mut buf)?; + Ok(u16::from_le_bytes(buf)) + } fn read_i16(&mut self, e: Endianness) -> Result<i16> { match e { Endianness::Big => self.read_i16_be(), @@ -1,2 +1,3 @@ pub mod unityfs; pub mod helper; +pub mod common_strings; diff --git a/src/main.rs b/src/main.rs index c1dcfd2..a0b35c3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,9 +2,10 @@ use log::debug; use std::{ env::args, fs::File, - io::{BufReader, Read}, + io::{BufReader, Cursor, Read}, }; use unity_tools::{ + common_strings::COMMON_STRINGS, helper::{Endianness, ReadExt}, unityfs::UnityFS, }; @@ -20,7 +21,7 @@ fn main() -> anyhow::Result<()> { } let mut cab = fs.read(&node)?; // let mut writer = File::create(format!("/tmp/{}", node.name))?; - // copy(&mut cab, &mut writer)?; + // std::io::copy(&mut cab, &mut writer)?; // continue; let mut metadata_size = cab.read_u32_be()?; @@ -54,39 +55,74 @@ fn main() -> anyhow::Result<()> { let has_type_trees = cab.read_u8()? != 0; let num_types = cab.read_u32(e)?; + debug!("has_type_trees={has_type_trees:?}"); + debug!("num_types={num_types}"); for _ in 0..num_types { - let mut class_id = cab.read_i32(e)?; + let class_id = cab.read_i32(e)?; let stripped_type = cab.read_u8()? != 0; - let script_id = cab.read_i16(e)?; + let script_index = cab.read_i16(e)?; + let mut script_id = 0; + // TODO reftype if class_id == 114 { - if script_id >= 0 { - class_id = -2 - script_id as i32; - } else { - class_id = -1; - } + script_id = cab.read_u128_be()?; } + let _old_hash = cab.read_u128_be()?; + eprintln!("class_id={class_id}"); eprintln!("stripped_type={stripped_type}"); + eprintln!("script_index={script_index}"); eprintln!("script_id={script_id}"); - let hash = if class_id < 0 { - (cab.read_u128_be()?, cab.read_u128_be()?) - } else { - (cab.read_u128_be()?, 0) - }; - eprintln!("{hash:032x?}"); - if has_type_trees { let num_nodes = cab.read_u32(e)?; - eprintln!("tree:num_nodes={num_nodes}"); let size = cab.read_u32(e)?; - assert!(format >= 19); + eprintln!("tree:num_nodes={num_nodes}"); + eprintln!("tree:size={size}"); + + let mut node_data = vec![0u8; num_nodes as usize * 32]; + cab.read_exact(&mut node_data)?; + let mut node_data = Cursor::new(node_data); + let mut string_data = vec![0u8; size as usize]; + cab.read_exact(&mut string_data)?; + + let get_string = |off: u32| { + let data = if off & 0x80000000 != 0 { + let off = off & 0x7fffffff; + &COMMON_STRINGS[(off & 0x7fffffff) as usize..] + } else { + &string_data[off as usize..] + }; + String::from_utf8( + data.iter() + .copied() + .take_while(|e| *e != 0) + .collect::<Vec<u8>>(), + ) + }; + + let mut nodes = Vec::new(); for _ in 0..num_nodes { - cab.read_u32(e)?; + nodes.push(TypeTreeNode { + version: node_data.read_u16(e)?, + level: node_data.read_u8()?, + type_flags: node_data.read_u8()?, + type_string: get_string(node_data.read_u32(e)?)?, + name_string: get_string(node_data.read_u32(e)?)?, + byte_size: node_data.read_i32(e)?, + index: node_data.read_i32(e)?, + flags: node_data.read_i32(e)?, + ref_type_hash: node_data.read_u64(e)?, + }); + } + eprintln!("{nodes:#?}"); + + if format >= 21 { + let num_deps = cab.read_u32(e)?; + for _ in 0..num_deps { + cab.read_u32(e)?; + } } - let mut data = vec![0u8; size as usize]; - cab.read_exact(&mut data)?; } if format > 21 { @@ -101,3 +137,16 @@ fn main() -> anyhow::Result<()> { Ok(()) } + +#[derive(Debug)] +struct TypeTreeNode { + version: u16, + level: u8, + type_flags: u8, + type_string: String, + name_string: String, + byte_size: i32, + index: i32, + flags: i32, + ref_type_hash: u64, +} |