aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-03-10 19:53:48 +0100
committermetamuffin <metamuffin@disroot.org>2025-03-10 19:53:48 +0100
commit42a5916cf742779d016eeefd1c59efbdfab64feb (patch)
tree25da747d72fcdf5ca8fcc2f7e7d7b3865a841b62 /src
parent556a9689682d407660fb4ddde91c155419dc84f7 (diff)
downloadunity-tools-42a5916cf742779d016eeefd1c59efbdfab64feb.tar
unity-tools-42a5916cf742779d016eeefd1c59efbdfab64feb.tar.bz2
unity-tools-42a5916cf742779d016eeefd1c59efbdfab64feb.tar.zst
successfully read all objects of a file
Diffstat (limited to 'src')
-rw-r--r--src/bin/debug.rs (renamed from src/bin/parse.rs)20
-rw-r--r--src/bin/json.rs35
-rw-r--r--src/helper.rs4
-rw-r--r--src/object.rs42
4 files changed, 78 insertions, 23 deletions
diff --git a/src/bin/parse.rs b/src/bin/debug.rs
index 273cffd..5da7c03 100644
--- a/src/bin/parse.rs
+++ b/src/bin/debug.rs
@@ -2,13 +2,9 @@ use log::debug;
use std::{
env::args,
fs::File,
- io::{BufReader, Read, Seek, SeekFrom},
-};
-use unity_tools::{
- object::{Value, read_value},
- serialized_file::{TypeTreeNode, read_serialized_file},
- unityfs::UnityFS,
+ io::{BufReader, Seek, SeekFrom},
};
+use unity_tools::{object::read_value, serialized_file::read_serialized_file, unityfs::UnityFS};
fn main() -> anyhow::Result<()> {
env_logger::init_from_env("LOG");
@@ -47,7 +43,7 @@ fn main() -> anyhow::Result<()> {
// }
// }
// fn print_crit_types(tt: &TypeTreeNode) {
- // let mut crit = tt.byte_size == -1;
+ // let mut crit = tt.byte_size == -1 || tt.children.is_empty();
// for c in &tt.children {
// print_crit_types(&c);
// crit &= c.byte_size != -1
@@ -56,11 +52,11 @@ fn main() -> anyhow::Result<()> {
// println!("{}", tt.type_string);
// }
// }
- if let Some(tree) = &typetree.type_tree {
- println!("{}", tree.type_string);
- // print_crit_types(tree);
- // print_types(tree);
- }
+ // if let Some(tree) = &typetree.type_tree {
+ // println!("{}", tree.type_string);
+ // print_crit_types(tree);
+ // print_types(tree);
+ // }
// eprintln!("{typetree:#?}");
let value = read_value(typetree.type_tree.as_ref().unwrap(), e, &mut cab)?;
diff --git a/src/bin/json.rs b/src/bin/json.rs
new file mode 100644
index 0000000..a9685ed
--- /dev/null
+++ b/src/bin/json.rs
@@ -0,0 +1,35 @@
+use std::{
+ env::args,
+ fs::File,
+ io::{BufReader, Seek, SeekFrom, stdout},
+};
+use unity_tools::{object::read_value, serialized_file::read_serialized_file, unityfs::UnityFS};
+
+fn main() -> anyhow::Result<()> {
+ env_logger::init_from_env("LOG");
+ let file = BufReader::new(File::open(args().nth(1).unwrap())?);
+ let mut fs = UnityFS::open(file)?;
+
+ for node in fs.nodes().to_vec() {
+ if node.name.ends_with(".resource") || node.name.ends_with(".resS") {
+ continue;
+ }
+ let mut cab = fs.read(&node)?;
+ let file = read_serialized_file(&mut cab)?;
+ let e = file.endianness;
+
+ for ob in file.objects {
+ cab.seek(SeekFrom::Start(ob.data_offset))?;
+ let typetree = if ob.type_id < 0 {
+ unimplemented!()
+ } else {
+ &file.types[ob.type_id as usize]
+ };
+ let value = read_value(typetree.type_tree.as_ref().unwrap(), e, &mut cab)?;
+ serde_json::to_writer(stdout(), &value.to_json()).unwrap();
+ println!()
+ }
+ }
+
+ Ok(())
+}
diff --git a/src/helper.rs b/src/helper.rs
index 48f3d2d..0681b62 100644
--- a/src/helper.rs
+++ b/src/helper.rs
@@ -9,6 +9,7 @@ pub enum Endianness {
pub trait ReadExt {
fn read_u8(&mut self) -> Result<u8>;
+ fn read_i8(&mut self) -> Result<i8>;
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>;
@@ -43,6 +44,9 @@ impl<T: Read> ReadExt for T {
self.read_exact(&mut buf)?;
Ok(buf[0])
}
+ fn read_i8(&mut self) -> Result<i8> {
+ Ok(self.read_u8()? as i8)
+ }
fn read_u16(&mut self, e: Endianness) -> Result<u16> {
match e {
Endianness::Big => self.read_u16_be(),
diff --git a/src/object.rs b/src/object.rs
index bdaf3ec..be76c18 100644
--- a/src/object.rs
+++ b/src/object.rs
@@ -9,11 +9,13 @@ use std::{collections::BTreeMap, io::Read};
pub enum Value {
Bool(bool),
U8(u8),
+ I8(i8),
U16(u16),
I16(i16),
U32(u32),
I32(i32),
F32(f32),
+ U64(u64),
I64(i64),
F64(f64),
Array(Vec<Value>),
@@ -21,6 +23,7 @@ pub enum Value {
class: String,
fields: BTreeMap<String, Value>,
},
+ Typeless(Vec<u8>),
String(String),
}
@@ -32,12 +35,20 @@ pub fn read_value(
let mut align = false;
let pos_before = data.stream_position()?;
let r = match ty.type_string.as_str() {
- "char" => Ok(Value::U8(data.read_u8()?)),
+ "char" => {
+ assert_eq!(ty.byte_size, 1);
+ Ok(Value::U8(data.read_u8()?))
+ }
+ "Type*" => Ok(Value::U32(data.read_u32(e)?)),
"int" => Ok(Value::I32(data.read_i32(e)?)),
"unsigned int" => Ok(Value::U32(data.read_u32(e)?)),
"UInt8" => Ok(Value::U8(data.read_u8()?)),
"UInt16" => Ok(Value::U16(data.read_u16(e)?)),
+ "UInt32" => Ok(Value::U32(data.read_u32(e)?)),
+ "UInt64" => Ok(Value::U64(data.read_u64(e)?)),
+ "SInt8" => Ok(Value::I8(data.read_i8()?)),
"SInt16" => Ok(Value::I16(data.read_i16(e)?)),
+ "SInt32" => Ok(Value::I32(data.read_i32(e)?)),
"SInt64" => Ok(Value::I64(data.read_i64(e)?)),
"bool" => Ok(Value::Bool(data.read_u8()? != 0)),
"float" => {
@@ -54,33 +65,34 @@ pub fn read_value(
};
let bytes = arr
.into_iter()
- .map(|e| {
- if let Value::U8(x) = e {
- x
- } else {
- unreachable!()
- }
+ .map(|e| match e {
+ Value::U8(x) => x,
+ _ => unreachable!(),
})
.collect::<Vec<_>>();
Ok(Value::String(String::from_utf8(bytes)?))
}
"Array" => {
align |= ty.children[0].post_align();
+ assert_eq!(ty.byte_size, -1);
let Value::I32(size) = read_value(&ty.children[0], e, data)? else {
unreachable!()
};
trace!("array of size {size}");
- if size > 10000 {
- eprintln!("{ty:#?}");
- }
let mut elems = Vec::new();
for _ in 0..size {
elems.push(read_value(&ty.children[1], e, data)?);
}
Ok(Value::Array(elems))
}
+ "TypelessData" => {
+ let len = data.read_u32(e)?;
+ let mut buf = vec![0u8; len as usize];
+ data.read_exact(&mut buf)?;
+ Ok(Value::Typeless(buf))
+ }
_ => {
- if ty.children.is_empty() && ty.byte_size != -1 {
+ if ty.children.is_empty() && ty.byte_size != 0 {
todo!("need type {:?}", ty.type_string);
}
let mut fields = BTreeMap::new();
@@ -113,9 +125,11 @@ impl Value {
match self {
Value::Bool(x) => serde_json::Value::Bool(x),
Value::U8(x) => serde_json::Value::Number(x.into()),
+ Value::I8(x) => serde_json::Value::Number(x.into()),
Value::U16(x) => serde_json::Value::Number(x.into()),
Value::I16(x) => serde_json::Value::Number(x.into()),
Value::U32(x) => serde_json::Value::Number(x.into()),
+ Value::U64(x) => serde_json::Value::Number(x.into()),
Value::I32(x) => serde_json::Value::Number(x.into()),
Value::F32(x) => serde_json::Value::Number(
serde_json::Number::from_f64(x as f64).unwrap_or(0.into()),
@@ -123,6 +137,12 @@ impl Value {
Value::I64(x) => serde_json::Value::Number(x.into()),
Value::F64(x) => serde_json::Value::Number(serde_json::Number::from_f64(x).unwrap()),
Value::String(x) => serde_json::Value::String(x),
+ Value::Typeless(values) => serde_json::Value::Array(
+ values
+ .into_iter()
+ .map(|e| serde_json::Value::Number(e.into()))
+ .collect(),
+ ),
Value::Array(values) => {
serde_json::Value::Array(values.into_iter().map(Value::to_json).collect())
}