Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions crates/war/src/darksiders1/code/vigil/gfc/io/binaryobjectreader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ impl<'s> BinaryObjectReader<'s> {
let string = self.read_string(input)?;
Ok(gfc::Value::String(string))
}
0x6 => {
let string = self.read_wstring(input)?;
// TODO: add a specific `gfc::Value` variant so the type isn't lost
Ok(gfc::Value::String(string))
}
0x7 => {
let id = input.read_i32()?;
let obj = self.read_obj(input)?;
Expand Down Expand Up @@ -188,6 +193,13 @@ impl<'s> BinaryObjectReader<'s> {
Ok(gfc::InputStream::read_string(input)?)
}

fn read_wstring(
&mut self,
input: &mut ByteOrdered<impl Read, Endianness>,
) -> Result<String, Error> {
Ok(gfc::InputStream::read_wstring(input)?)
}

fn read_hstring(
&mut self,
input: &mut ByteOrdered<impl Read, Endianness>,
Expand Down
12 changes: 12 additions & 0 deletions crates/war/src/darksiders1/code/vigil/gfc/io/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ impl InputStream {
stream.read_exact(&mut buf)?;
Ok(String::from_windows_1252(buf))
}

pub fn read_wstring(
stream: &mut ByteOrdered<impl Read, impl Endian>,
) -> io::Result<String> {
let length = stream.read_u16()?;
let length = usize::try_from(length).map_err(|_| derailed())?;
let mut buf = Vec::with_capacity(length);
for _ in 0..length {
buf.push(stream.read_u16()?);
}
Ok(String::from_utf16(&buf).map_err(|_| derailed())?)
}
}

pub struct OutputStream {
Expand Down
31 changes: 26 additions & 5 deletions crates/war/src/darksiders1/code/vigil/gfc/oc/occlassmanager.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::{
darksiders1::gfc,
utils::parsing::{derailed, expect},
utils::{
parsing::{derailed, expect},
windows1252::StringWindows1252Ext,
},
};
use byteordered::{ByteOrdered, Endianness};
use failure::Error;
Expand Down Expand Up @@ -55,11 +58,11 @@ impl OCClassManager {
// Propagate the new endianness to callers as well.
replace_with_or_abort(stream, |stream| stream.into_endianness(endianness));

expect(stream.read_i32()? == 7)?;
expect(stream.read_i32()? == 12)?;
let packed_compiled = stream.read_i32()? != 0;
expect(packed_compiled)?;
let original_names = stream.read_i32()? != 0;
expect(original_names)?;
// let original_names = stream.read_i32()? != 0;
// expect(original_names)?;
let num_scripts = stream.read_i32()?;
let _scripts_pos = stream.read_i32()?;
let mut scripts = IndexMap::with_capacity(num_scripts.try_into()?);
Expand All @@ -69,7 +72,14 @@ impl OCClassManager {
hstring_manager.read_string_table(&mut strings, stream)?;

for _ in 0..num_scripts {
let name = hstring_manager.read_u64_hstring(stream)?;
let _unknown = stream.read_i32()?;
let _name_hash = hstring_manager.read_u64_hstring(stream)?;

let name_len = stream.read_i16()?;
let mut name = vec![0; name_len.try_into().unwrap()];
stream.read_exact(&mut name)?;
let name = String::from_windows_1252(name);

let file_offset = stream.read_i32()?;
let file_length = stream.read_i32()?;
let package_id = stream.read_u16()?;
Expand All @@ -82,13 +92,23 @@ impl OCClassManager {
relative_path,
};

let _unknown = stream.read_i32()?;

// There are more after this, but list_politic_p01_animations has a bunch of
// extra data I'm not sure what it is. Skip for now.
let wip_skip = name == "list_politic_p01_animations";

scripts.insert(name, OCClassManager__ScriptInfo {
file_offset,
file_length,
package_id,
typ: typ.try_into()?,
unpacked,
});

if wip_skip {
break;
}
}
Ok(scripts)
}
Expand All @@ -103,6 +123,7 @@ impl OCClassManager {
hstring_manager.read_string_table(&mut strings, stream)?;

let script_name = hstring_manager.read_u64_hstring(stream)?;
let _unknown = stream.read_i32()?;
let package_name = hstring_manager.read_u64_hstring(stream)?;
let parent_name = hstring_manager.read_u64_hstring(stream)?;

Expand Down
22 changes: 20 additions & 2 deletions crates/war/src/obsp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ use std::{
io::{Read, Seek},
};

macro_rules! wip_skip_continue {
($var:ident, $info:expr) => {
let $var = match $var {
Ok(x) => x,
Err(_) => {
eprintln!(
"bailing out of {} with unknown data format: {:?}",
stringify!($var),
$info.unpacked.name,
);
continue;
}
};
};
}

// Loosely based on `gfc::OCClassManager::loadScripts`
pub fn read(file: impl Read + Seek) -> Result<Vec<(String, String)>, Error> {
let mut packfile = ByteOrdered::new(file, Endianness::Little);
Expand All @@ -22,7 +38,8 @@ pub fn read(file: impl Read + Seek) -> Result<Vec<(String, String)>, Error> {
};

if info.typ == gfc::OCClassManager__Types::Script {
let class = gfc::OCClassManager::read_script(&mut packfile, &info)?;
let class = gfc::OCClassManager::read_script(&mut packfile, &info);
wip_skip_continue!(class, info);
let json = serde_json::to_string_pretty(&Lossy(&class))?;
files.push((path.clone() + ".json", json));

Expand All @@ -31,7 +48,8 @@ pub fn read(file: impl Read + Seek) -> Result<Vec<(String, String)>, Error> {
files.push((path + ".s", listing));
}
} else {
let object = gfc::OCClassManager::read_object(&mut packfile, &info)?;
let object = gfc::OCClassManager::read_object(&mut packfile, &info);
wip_skip_continue!(object, info);
let json = serde_json::to_string_pretty(&Lossy(&object))?;
files.push((path + ".json", json));
}
Expand Down