aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-02-14 20:10:00 +0100
committermetamuffin <metamuffin@disroot.org>2025-02-14 20:10:00 +0100
commitd116a1df8fe14edc8de157bf8088244261fca30f (patch)
tree6e6b0c2eb62f035a38bc4a14df2c9fa76b92aec9 /src
parentb3ae58d1ab1f3b35b4a86234e424b3675af323e5 (diff)
downloadunity-tools-d116a1df8fe14edc8de157bf8088244261fca30f.tar
unity-tools-d116a1df8fe14edc8de157bf8088244261fca30f.tar.bz2
unity-tools-d116a1df8fe14edc8de157bf8088244261fca30f.tar.zst
trying to read objects
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs1
-rw-r--r--src/main.rs26
-rw-r--r--src/object.rs4
-rw-r--r--src/serialized_file.rs22
-rw-r--r--src/unityfs.rs36
5 files changed, 74 insertions, 15 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 5022d0d..c456e91 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,3 +2,4 @@ pub mod unityfs;
pub mod helper;
pub mod common_strings;
pub mod serialized_file;
+pub mod object;
diff --git a/src/main.rs b/src/main.rs
index beab8a1..450f4a7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,8 @@
-use std::{env::args, fs::File, io::BufReader};
+use std::{
+ env::args,
+ fs::File,
+ io::{BufReader, Read, Seek, SeekFrom},
+};
use unity_tools::{serialized_file::read_serialized_file, unityfs::UnityFS};
fn main() -> anyhow::Result<()> {
@@ -10,12 +14,28 @@ fn main() -> anyhow::Result<()> {
if node.name.ends_with(".resource") || node.name.ends_with(".resS") {
continue;
}
- let cab = fs.read(&node)?;
+ let mut cab = fs.read(&node)?;
// let mut writer = File::create(format!("/tmp/{}", node.name))?;
// std::io::copy(&mut cab, &mut writer)?;
// continue;
- let file = read_serialized_file(cab)?;
+ let file = read_serialized_file(&mut cab)?;
+
+ for ob in file.objects {
+ cab.seek(SeekFrom::Start(ob.data_offset))?;
+ let ob_data = cab.by_ref().take(ob.data_size as u64);
+
+ eprintln!("{:#?}", ob);
+ let typetree = if ob.type_id < 0 {
+ unimplemented!()
+ } else {
+ file.types
+ .iter()
+ .find(|t| t.class_id == ob.type_id)
+ .expect("unknown type")
+ };
+ }
+ // eprintln!("{:#?}", file.types);
}
Ok(())
diff --git a/src/object.rs b/src/object.rs
new file mode 100644
index 0000000..9875517
--- /dev/null
+++ b/src/object.rs
@@ -0,0 +1,4 @@
+use crate::serialized_file::TypeTreeNode;
+use std::io::Read;
+
+pub fn read_value(ty: TypeTreeNode, data: &mut impl Read) {}
diff --git a/src/serialized_file.rs b/src/serialized_file.rs
index f32b3a3..4b348e0 100644
--- a/src/serialized_file.rs
+++ b/src/serialized_file.rs
@@ -17,6 +17,8 @@ pub struct TypeTreeNode {
pub index: i32,
pub flags: i32,
pub ref_type_hash: u64,
+
+ pub children: Vec<TypeTreeNode>,
}
#[derive(Debug)]
@@ -26,7 +28,7 @@ pub struct SeralizedType {
pub script_type_index: i16,
pub script_id: u128,
- pub type_tree: Vec<TypeTreeNode>,
+ pub type_tree: Option<TypeTreeNode>,
pub type_deps: Vec<u32>,
}
@@ -115,7 +117,7 @@ pub fn read_serialized_file(mut file: impl Read + Seek) -> Result<SerializedFile
trace!("script_id={script_id}");
let mut type_deps = Vec::new();
- let mut type_tree = Vec::new();
+ let mut type_tree = None;
if has_type_trees {
let num_nodes = file.read_u32(e)?;
let size = file.read_u32(e)?;
@@ -143,8 +145,9 @@ pub fn read_serialized_file(mut file: impl Read + Seek) -> Result<SerializedFile
)
};
+ let mut parents: Vec<TypeTreeNode> = vec![];
for _ in 0..num_nodes {
- type_tree.push(TypeTreeNode {
+ let node = TypeTreeNode {
version: node_data.read_u16(e)?,
level: node_data.read_u8()?,
type_flags: node_data.read_u8()?,
@@ -154,8 +157,19 @@ pub fn read_serialized_file(mut file: impl Read + Seek) -> Result<SerializedFile
index: node_data.read_i32(e)?,
flags: node_data.read_i32(e)?,
ref_type_hash: node_data.read_u64(e)?,
- });
+ children: vec![],
+ };
+ while parents.len() > node.level as usize {
+ let n = parents.pop().unwrap();
+ parents.last_mut().unwrap().children.push(n)
+ }
+ parents.push(node);
+ }
+ while parents.len() > 1 {
+ let n = parents.pop().unwrap();
+ parents.last_mut().unwrap().children.push(n)
}
+ type_tree = parents.pop();
if format >= 21 {
let num_deps = file.read_u32(e)?;
diff --git a/src/unityfs.rs b/src/unityfs.rs
index d7659b8..bd0c7bb 100644
--- a/src/unityfs.rs
+++ b/src/unityfs.rs
@@ -1,7 +1,7 @@
use crate::helper::{AlignExt, ReadExt};
use anyhow::{Result, anyhow, bail};
use log::{debug, info, trace};
-use std::io::{Cursor, ErrorKind, Read, Seek, SeekFrom, Take};
+use std::io::{Cursor, Error, ErrorKind, Read, Seek, SeekFrom};
pub struct UnityFS<T> {
nodes: Vec<NodeInfo>,
@@ -23,7 +23,9 @@ struct BlockInfo {
}
pub struct NodeReader<'a, T> {
- inner: Take<&'a mut BlocksReader<T>>,
+ inner: &'a mut BlocksReader<T>,
+ position: u64,
+ offset: u64,
size: u64,
}
@@ -131,7 +133,9 @@ impl<T: Read + Seek> UnityFS<T> {
self.reader.seek(SeekFrom::Start(node.offset))?;
Ok(NodeReader {
size: node.size,
- inner: (&mut self.reader).take(node.size),
+ offset: node.offset,
+ position: 0,
+ inner: &mut self.reader,
})
}
}
@@ -213,10 +217,14 @@ impl<T: Seek + Read> Seek for BlocksReader<T> {
let block_off = pos - decomp_off;
debug!("target is block={i} offset={block_off}");
- debug!("seek comp to {comp_off}");
self.inner.seek(SeekFrom::Start(comp_off))?;
- self.nblock_index = i;
- self.load_next_block()?;
+ if self.nblock_index == i + 1 {
+ debug!("intra-block seek")
+ } else {
+ debug!("seek comp to {comp_off}");
+ self.nblock_index = i;
+ self.load_next_block()?;
+ }
self.cblock_off = block_off as usize;
Ok(pos)
@@ -225,7 +233,11 @@ impl<T: Seek + Read> Seek for BlocksReader<T> {
impl<T: Read> Read for NodeReader<'_, T> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
- self.inner.read(buf)
+ let bytes_left = self.size - self.position;
+ let end = buf.len().min(bytes_left as usize);
+ let size = self.inner.read(&mut buf[..end])?;
+ self.position += size as u64;
+ Ok(size)
}
}
impl<T: Seek + Read> Seek for NodeReader<'_, T> {
@@ -237,11 +249,19 @@ impl<T: Seek + Read> Seek for NodeReader<'_, T> {
}
Ok(self.stream_position()?)
}
+ SeekFrom::Start(n) => {
+ debug!("seek node to {n} (off={})", self.offset);
+ if n > self.size {
+ return Err(Error::new(ErrorKind::NotSeekable, "seek out of bounds"));
+ }
+ self.position = n;
+ self.inner.seek(SeekFrom::Start(self.offset + n))
+ }
_ => unimplemented!(),
}
}
fn stream_position(&mut self) -> std::io::Result<u64> {
- Ok(self.size - self.inner.limit())
+ Ok(self.position)
}
}