aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--exporter/src/bin/debug.rs4
-rw-r--r--exporter/src/bin/json.rs2
-rw-r--r--exporter/src/bin/typegraph.rs2
-rw-r--r--exporter/src/bin/yaml.rs2
-rw-r--r--src/assetbundle.rs14
-rw-r--r--src/classes/pptr.rs60
-rw-r--r--src/classes/streaminginfo.rs5
-rw-r--r--src/object/helper.rs2
-rw-r--r--src/object/mod.rs1
-rw-r--r--src/object/parser.rs2
-rw-r--r--src/object/read.rs16
-rw-r--r--src/serialized_file.rs11
12 files changed, 75 insertions, 46 deletions
diff --git a/exporter/src/bin/debug.rs b/exporter/src/bin/debug.rs
index 3f87ccf..b1d8d12 100644
--- a/exporter/src/bin/debug.rs
+++ b/exporter/src/bin/debug.rs
@@ -8,9 +8,9 @@ fn main() -> anyhow::Result<()> {
let node = fs.find_main_file().unwrap().to_owned();
let mut cab = fs.read(&node)?;
- let file = SerializedFile::read(&mut cab)?;
+ let file = SerializedFile::read(&mut cab, 0)?;
let shared_assets = if let Some(n) = file.find_fs_shared_assets(&fs) {
- Some(SerializedFile::read(fs.read(&n)?)?)
+ Some(SerializedFile::read(fs.read(&n)?, 1)?)
} else {
None
};
diff --git a/exporter/src/bin/json.rs b/exporter/src/bin/json.rs
index e03642b..57a0edc 100644
--- a/exporter/src/bin/json.rs
+++ b/exporter/src/bin/json.rs
@@ -14,7 +14,7 @@ fn main() -> anyhow::Result<()> {
let node = fs.find_main_file().unwrap().to_owned();
let mut cab = fs.read(&node)?;
- let mut file = SerializedFile::read(&mut cab)?;
+ let mut file = SerializedFile::read(&mut cab, 0)?;
for ob in file.objects.clone() {
if let Some(f) = &filter {
if file.get_object_type_tree(&ob)?.type_string != *f && ob.path_id.to_string() != *f {
diff --git a/exporter/src/bin/typegraph.rs b/exporter/src/bin/typegraph.rs
index 0d6568a..388f36f 100644
--- a/exporter/src/bin/typegraph.rs
+++ b/exporter/src/bin/typegraph.rs
@@ -19,7 +19,7 @@ fn main() -> anyhow::Result<()> {
let mut edges = BTreeSet::new();
let node = fs.find_main_file().unwrap().to_owned();
let mut cab = fs.read(&node)?;
- let file = SerializedFile::read(&mut cab)?;
+ let file = SerializedFile::read(&mut cab, 0)?;
for ob in file.objects {
let typetree = if ob.type_id < 0 {
diff --git a/exporter/src/bin/yaml.rs b/exporter/src/bin/yaml.rs
index bc9e57e..26cd04b 100644
--- a/exporter/src/bin/yaml.rs
+++ b/exporter/src/bin/yaml.rs
@@ -15,7 +15,7 @@ fn main() -> anyhow::Result<()> {
let node = fs.find_main_file().unwrap().to_owned();
let mut cab = fs.read(&node)?;
- let mut file = SerializedFile::read(&mut cab)?;
+ let mut file = SerializedFile::read(&mut cab,0)?;
for ob in file.objects.clone() {
if let Some(f) = &filter {
if file.get_object_type_tree(&ob)?.type_string != *f && ob.path_id.to_string() != *f {
diff --git a/src/assetbundle.rs b/src/assetbundle.rs
index db7ad97..8f6af15 100644
--- a/src/assetbundle.rs
+++ b/src/assetbundle.rs
@@ -24,10 +24,10 @@ impl<T: Read + Seek> AssetBundle<T> {
.find_main_file()
.ok_or(anyhow!("AssetBundle seems to lack main file"))?;
debug!("detected {:?} as main file", main_ni.name);
- let main = SerializedFile::read(fs.read(main_ni)?)?;
+ let main = SerializedFile::read(fs.read(main_ni)?, 0)?;
let shared_assets = if let Some(n) = main.find_fs_shared_assets(&fs) {
debug!("detect {:?} as shared assets", n.name);
- Some(SerializedFile::read(fs.read(&n)?)?)
+ Some(SerializedFile::read(fs.read(&n)?, 1)?)
} else {
None
};
@@ -50,9 +50,10 @@ impl<T: Read + Seek> AssetBundle<T> {
.into_iter()
.flatten(),
)
- .map(|(fi, o)| PPtr {
+ .map(|(si, o)| PPtr {
class: "".to_string(),
- file_id: fi,
+ source_file: si,
+ file_id: 0,
path_id: o.path_id,
_class: PhantomData,
})
@@ -69,9 +70,10 @@ impl<T: Read + Seek> AssetBundle<T> {
.into_iter()
.flatten(),
)
- .map(|(fi, o)| PPtr {
+ .map(|(si, o)| PPtr {
class: class_name.to_owned(),
- file_id: fi,
+ source_file: si,
+ file_id: 0,
path_id: o.path_id,
_class: PhantomData,
})
diff --git a/src/classes/pptr.rs b/src/classes/pptr.rs
index 366e17c..0e66b5f 100644
--- a/src/classes/pptr.rs
+++ b/src/classes/pptr.rs
@@ -15,13 +15,19 @@ pub struct PPtr<T = Value> {
#[serde(skip, default)]
pub(crate) _class: PhantomData<T>,
pub class: String,
+ pub source_file: usize,
pub file_id: i32,
pub path_id: i64,
}
impl<T> FromValue for PPtr<T> {
fn from_value(v: Value) -> Result<Self> {
- let Value::Object { class, fields } = v else {
+ let Value::Object {
+ class,
+ fields,
+ file,
+ } = v
+ else {
bail!("PPtr expected but not an object")
};
let inner = class
@@ -32,6 +38,7 @@ impl<T> FromValue for PPtr<T> {
Ok(PPtr {
class: inner.to_owned(),
_class: PhantomData,
+ source_file: file,
file_id: fields["m_FileID"]
.as_i32()
.ok_or(anyhow!("PPtr m_FileID is not i32"))?,
@@ -47,6 +54,7 @@ impl<T: FromValue> PPtr<T> {
PPtr {
_class: PhantomData,
class: self.class,
+ source_file: self.source_file,
file_id: self.file_id,
path_id: self.path_id,
}
@@ -59,30 +67,32 @@ impl<T: FromValue> PPtr<T> {
"loading PPtr<{}> file_id={} path_id={}",
self.class, self.file_id, self.path_id
);
- match self.file_id {
- 0 => {
- let ob = bundle
- .main
- .objects
- .iter()
- .find(|o| o.path_id == self.path_id)
- .ok_or(anyhow!("object with path id {} not found", self.path_id))?
- .to_owned();
- bundle.main.read_object(ob)?.parse()
- }
- 1 => {
- let file = bundle.shared_assets.as_mut().ok_or(anyhow!(
- "shared assets referenced but not included in bundle"
- ))?;
- let ob = file
- .objects
- .iter()
- .find(|o| o.path_id == self.path_id)
- .ok_or(anyhow!("object with path id {} not found", self.path_id))?
- .to_owned();
- file.read_object(ob)?.parse()
- }
- _ => unimplemented!(),
+ let main_file = match (self.source_file, self.file_id) {
+ (0, 0) => true,
+ (0, 1) => false,
+ (1, 0) => false,
+ _ => unreachable!(),
+ };
+ if main_file {
+ let ob = bundle
+ .main
+ .objects
+ .iter()
+ .find(|o| o.path_id == self.path_id)
+ .ok_or(anyhow!("object with path id {} not found", self.path_id))?
+ .to_owned();
+ bundle.main.read_object(ob)?.parse()
+ } else {
+ let file = bundle.shared_assets.as_mut().ok_or(anyhow!(
+ "shared assets referenced but not included in bundle"
+ ))?;
+ let ob = file
+ .objects
+ .iter()
+ .find(|o| o.path_id == self.path_id)
+ .ok_or(anyhow!("object with path id {} not found", self.path_id))?
+ .to_owned();
+ file.read_object(ob)?.parse()
}
}
}
diff --git a/src/classes/streaminginfo.rs b/src/classes/streaminginfo.rs
index e308f1c..d593a5b 100644
--- a/src/classes/streaminginfo.rs
+++ b/src/classes/streaminginfo.rs
@@ -28,7 +28,10 @@ impl FromValue for StreamingInfo {
impl StreamingInfo {
pub fn read(&self, fs: &UnityFS<impl Read + Seek>) -> Result<Vec<u8>> {
if !self.path.starts_with("archive:") {
- bail!("StreamingInfo path does not start on archive:")
+ bail!(
+ "StreamingInfo path does not start on 'archive:' ({:?})",
+ self.path
+ )
}
let nodeinfo = fs
.header
diff --git a/src/object/helper.rs b/src/object/helper.rs
index 74d18ea..4aba67d 100644
--- a/src/object/helper.rs
+++ b/src/object/helper.rs
@@ -104,7 +104,7 @@ impl Value {
V::Array(values.into_iter().map(|e| V::Number(e.into())).collect())
}
Value::Array(values) => V::Array(values.into_iter().map(Value::to_json).collect()),
- Value::Object { class, fields } => V::Object(
+ Value::Object { class, fields, .. } => V::Object(
fields
.into_iter()
.map(|(k, v)| (k, v.to_json()))
diff --git a/src/object/mod.rs b/src/object/mod.rs
index efc1544..08f76cd 100644
--- a/src/object/mod.rs
+++ b/src/object/mod.rs
@@ -21,6 +21,7 @@ pub enum Value {
Array(Vec<Value>),
Object {
class: String,
+ file: usize,
fields: BTreeMap<String, Value>,
},
Typeless(Vec<u8>),
diff --git a/src/object/parser.rs b/src/object/parser.rs
index b9cc1d4..27cb975 100644
--- a/src/object/parser.rs
+++ b/src/object/parser.rs
@@ -11,7 +11,7 @@ impl Value {
T::from_value(self)
}
pub fn as_class(self, name: &'static str) -> Result<Fields> {
- if let Value::Object { class, fields } = self {
+ if let Value::Object { class, fields, .. } = self {
if class == name {
Ok(Fields {
class: name,
diff --git a/src/object/read.rs b/src/object/read.rs
index 641bdcc..c41163a 100644
--- a/src/object/read.rs
+++ b/src/object/read.rs
@@ -7,7 +7,12 @@ use std::io::Seek;
use std::{collections::BTreeMap, io::Read};
impl Value {
- pub fn read(ty: &TypeTreeNode, e: Endianness, data: &mut (impl Read + Seek)) -> Result<Value> {
+ pub fn read(
+ ty: &TypeTreeNode,
+ e: Endianness,
+ file: usize,
+ data: &mut (impl Read + Seek),
+ ) -> Result<Value> {
let mut align = false;
let pos_before = data.stream_position()?;
let r = match ty.type_string.as_str() {
@@ -36,7 +41,7 @@ impl Value {
Ok(Value::F64(data.read_f64(e)?))
}
"string" => {
- let Value::Array(arr) = Value::read(&ty.children[0], e, data)? else {
+ let Value::Array(arr) = Value::read(&ty.children[0], e, file, data)? else {
unreachable!()
};
let bytes = arr
@@ -51,13 +56,13 @@ impl Value {
"Array" => {
align |= ty.children[0].post_align();
assert_eq!(ty.byte_size, -1);
- let Value::I32(size) = Value::read(&ty.children[0], e, data)? else {
+ let Value::I32(size) = Value::read(&ty.children[0], e, file, data)? else {
unreachable!()
};
trace!("array of size {size}");
let mut elems = Vec::new();
for _ in 0..size {
- elems.push(Value::read(&ty.children[1], e, data)?);
+ elems.push(Value::read(&ty.children[1], e, file, data)?);
}
Ok(Value::Array(elems))
}
@@ -73,10 +78,11 @@ impl Value {
}
let mut fields = BTreeMap::new();
for c in &ty.children {
- fields.insert(c.name_string.clone(), Value::read(&c, e, data)?);
+ fields.insert(c.name_string.clone(), Value::read(&c, e, file, data)?);
}
Ok(Value::Object {
fields,
+ file,
class: ty.type_string.clone(),
})
}
diff --git a/src/serialized_file.rs b/src/serialized_file.rs
index fa17b24..a37ff46 100644
--- a/src/serialized_file.rs
+++ b/src/serialized_file.rs
@@ -58,6 +58,7 @@ pub struct External {
pub struct SerializedFile<T> {
pub file: T,
+ pub file_source_id: usize,
pub header: SerializedFileHeader,
pub types: Vec<SeralizedType>,
pub externals: Vec<External>,
@@ -138,7 +139,7 @@ impl SerializedFileHeader {
}
impl<T: Read + Seek> SerializedFile<T> {
- pub fn read(mut file: T) -> Result<SerializedFile<T>> {
+ pub fn read(mut file: T, file_source_id: usize) -> Result<SerializedFile<T>> {
let h = SerializedFileHeader::read(&mut file)?;
let e = h.endianness;
@@ -318,6 +319,7 @@ impl<T: Read + Seek> SerializedFile<T> {
objects,
scripts,
user_string,
+ file_source_id,
})
}
@@ -356,7 +358,12 @@ impl<T: Read + Seek> SerializedFile<T> {
.type_tree
.as_ref()
.ok_or(anyhow!("type tree missing"))?;
- Value::read(typetree, self.endianness, &mut self.file)
+ Value::read(
+ typetree,
+ self.endianness,
+ self.file_source_id,
+ &mut self.file,
+ )
}
pub fn all_objects_of_class(&self, class_name: &str) -> impl Iterator<Item = &ObjectInfo> {