From cb9a60f45cb8438c58c2f1ecb2f59611dc5d515a Mon Sep 17 00:00:00 2001 From: metamuffin Date: Wed, 12 Mar 2025 10:56:16 +0100 Subject: extracted streaming data --- src/bin/textures.rs | 84 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 29 deletions(-) (limited to 'src/bin/textures.rs') diff --git a/src/bin/textures.rs b/src/bin/textures.rs index 5cfaaa7..83ffb07 100644 --- a/src/bin/textures.rs +++ b/src/bin/textures.rs @@ -1,10 +1,12 @@ +use anyhow::anyhow; +use log::warn; use std::{ env::args, fs::{File, create_dir_all}, - io::{BufReader, Seek, SeekFrom}, + io::{BufReader, Read, Seek, SeekFrom}, }; use unity_tools::{ - classes::{FromValue, texture2d::Texture2d}, + classes::{FromValue, texture2d::Texture2D}, object::read_value, serialized_file::read_serialized_file, unityfs::UnityFS, @@ -12,37 +14,61 @@ use unity_tools::{ 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)?; + let file = || BufReader::new(File::open(args().nth(1).unwrap()).unwrap()); + let mut fs = UnityFS::open(file())?; + let mut fs2 = UnityFS::open(file())?; let mut i = 0; create_dir_all("/tmp/tex").unwrap(); - 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)?; - 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] - }; - if let Some(typetree) = &typetree.type_tree { - if typetree.type_string != "Texture2D" { - continue; - } - let value = read_value(typetree, file.endianness, &mut cab)?; - let texture = Texture2d::from_value(value).unwrap(); - if texture.image_data.len() > 0 { - let path = format!("/tmp/tex/{i}.png"); - println!("{path}"); - texture.to_image().unwrap().save(path).unwrap(); - i += 1; - } + + let cabfile = fs + .nodes() + .iter() + .find(|n| !n.name.ends_with(".resource") && !n.name.ends_with(".resS")) + .ok_or(anyhow!("no CAB file found"))? + .to_owned(); + let ressfile = fs2 + .nodes() + .iter() + .find(|n| n.name.ends_with(".resS")) + .ok_or(anyhow!("no resS file found"))? + .to_owned(); + + let mut cab = fs.read(&cabfile)?; + let mut ress = fs2.read(&ressfile)?; + let file = read_serialized_file(&mut cab)?; + 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] + }; + if let Some(typetree) = &typetree.type_tree { + if typetree.type_string != "Texture2D" { + continue; + } + let value = read_value(typetree, file.endianness, &mut cab)?; + let mut texture = Texture2D::from_value(value).unwrap(); + if texture.image_data.len() == 0 { + ress.seek(SeekFrom::Start(texture.stream_data.offset as u64))?; + ress.by_ref() + .take(texture.stream_data.size as u64) + .read_to_end(&mut texture.image_data)?; + } + let path = format!( + "/tmp/tex/{}_{i}.png", + texture.name.replace("/", "-").replace(".", "-") + ); + println!( + "{path} {}x{} {:?}", + texture.width, texture.height, texture.format + ); + match texture.to_image() { + Ok(im) => im.save(path).unwrap(), + Err(e) => warn!("{e}"), } + i += 1; } } -- cgit v1.2.3-70-g09d2