Skip to content

Commit

Permalink
feat: reading and writing collections
Browse files Browse the repository at this point in the history
  • Loading branch information
francisdb committed Jul 13, 2023
1 parent 2d9aaa2 commit 77c731d
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/jsonmodel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,13 @@ pub fn table_json(table_info: &TableInfo) -> serde_json::Value {

serde_json::Value::Object(extended)
}

pub fn collection_json(collection: &crate::collection::Collection) -> serde_json::Value {
json!({
"name": collection.name,
"items": collection.items,
"fireEvents": collection.fire_events,
"stopSingleEvents": collection.stop_single_events,
"groupElements": collection.group_elements,
})
}
42 changes: 42 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ use vpx::tableinfo::{self};
use vpx::{extract_script, verify, VerifyResult};
use vpx::{extractvbs, font, read_gamedata, read_version, ExtractResult};

use crate::jsonmodel::collection_json;
use crate::vpx::collection;

// see https://github.com/fusion-engineering/rust-git-version/issues/21
const GIT_VERSION: &str = git_version!(args = ["--tags", "--always", "--dirty=-modified"]);

Expand Down Expand Up @@ -545,6 +548,7 @@ fn extract(vpx_file_path: &str, yes: bool) {
extract_images(&mut comp, &records, root_dir_path);
extract_sounds(&mut comp, &records, root_dir_path, version);
extract_fonts(&mut comp, &records, root_dir_path);
extract_collections(&mut comp, &records, root_dir_path);

// let mut file_version = String::new();
// comp.open_stream("/GameStg/Version")
Expand Down Expand Up @@ -621,6 +625,43 @@ fn extract_images(comp: &mut CompoundFile<File>, records: &[Record], root_dir_pa
}
}

fn extract_collections(comp: &mut CompoundFile<File>, records: &[Record], root_dir_path: &Path) {
// let result = parseGameData(&game_data_vec[..]);
// dump(result);

let collections_size = records
.iter()
.find_map(|r| match r {
Record::CollectionsSize(size) => Some(size),
_ => None,
})
.unwrap_or(&0)
.to_owned();

let collections_path = root_dir_path.join("collections");
std::fs::create_dir_all(&collections_path).unwrap();

println!(
"Writing {} collections to\n {}",
collections_size,
collections_path.display()
);

for index in 0..collections_size {
let path = format!("GameStg/Collection{}", index);
let mut input = Vec::new();
comp.open_stream(&path)
.unwrap()
.read_to_end(&mut input)
.unwrap();
let collection = collection::read(&input);
let collection_json = collection_json(&collection);
let json_path = collections_path.join(format!("Collection{}.json", index));
let mut json_file = std::fs::File::create(&json_path).unwrap();
serde_json::to_writer_pretty(&mut json_file, &collection_json).unwrap();
}
}

fn extract_sounds(
comp: &mut CompoundFile<File>,
records: &[Record],
Expand Down Expand Up @@ -720,6 +761,7 @@ fn extract_binaries(comp: &mut CompoundFile<std::fs::File>, root_dir_path: &Path
&& !entry.path().to_string_lossy().starts_with("/GameStg/Font")
&& !entry.path().to_string_lossy().starts_with("/GameStg/Image")
&& !entry.path().to_string_lossy().starts_with("/GameStg/Sound")
&& !entry.path().to_string_lossy().starts_with("/GameStg/Collection")
})
.map(|entry| {
let path = entry.path();
Expand Down
93 changes: 93 additions & 0 deletions src/vpx/collection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use super::biff::{self, BiffReader, BiffWriter};

// TODO comment here a vpx file that contains font data

#[derive(PartialEq, Debug)]
pub struct Collection {
pub name: String,
pub items: Vec<String>,
pub fire_events: bool,
pub stop_single_events: bool,
pub group_elements: bool,
}

pub fn read(input: &[u8]) -> Collection {
let mut reader = BiffReader::new(input);
let mut name: String = "".to_string();
let mut items: Vec<String> = vec![];
let mut fire_events: bool = false;
let mut stop_single_events: bool = false;
let mut group_elements: bool = false;
loop {
reader.next(biff::WARN);
if reader.is_eof() {
break;
}
let tag = reader.tag();
let tag_str = tag.as_str();
match tag_str {
"NAME" => {
name = reader.get_wide_string();
}
"ITEM" => {
let item = reader.get_wide_string();
items.push(item);
}
"EVNT" => {
fire_events = reader.get_bool();
}
"SSNG" => {
stop_single_events = reader.get_bool();
}
"GREL" => {
group_elements = reader.get_bool();
}
other => {
println!("Unknown tag: {}", other);
reader.skip_tag();
}
}
}
Collection {
name,
items,
fire_events,
stop_single_events,
group_elements,
}
}

pub fn write(collection: &Collection) -> Vec<u8> {
let mut writer = BiffWriter::new();
writer.write_tagged_wide_string("NAME", &collection.name);
for item in &collection.items {
writer.write_tagged_wide_string("ITEM", item);
}
writer.write_tagged_bool("EVNT", collection.fire_events);
writer.write_tagged_bool("SSNG", collection.stop_single_events);
writer.write_tagged_bool("GREL", collection.group_elements);
writer.close(true);
writer.get_data().to_owned()
}

#[cfg(test)]
mod test {
use super::*;
use pretty_assertions::assert_eq;

#[test]
fn write_read() {
use pretty_assertions::assert_eq;

let collection = Collection {
name: "Test Collection".to_string(),
items: vec!["Item 1".to_string(), "Item 2".to_string()],
fire_events: true,
stop_single_events: true,
group_elements: true,
};
let data = write(&collection);
let collection2 = read(&data);
assert_eq!(collection, collection2);
}
}
1 change: 1 addition & 0 deletions src/vpx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::vpx::biff::BiffReader;
use self::tableinfo::{write_tableinfo, TableInfo};

pub mod biff;
pub mod collection;
pub mod font;
pub mod gamedata;
pub mod image;
Expand Down

0 comments on commit 77c731d

Please sign in to comment.