66 lines
2.0 KiB
Rust
66 lines
2.0 KiB
Rust
use binread::{FilePtr, NullString};
|
|
use prs_rust::prs;
|
|
use std::collections::BTreeMap;
|
|
use std::path::PathBuf;
|
|
use std::ffi::OsString;
|
|
use std::os::unix::ffi::OsStringExt;
|
|
use std::fmt::Formatter;
|
|
|
|
#[derive(BinRead)]
|
|
#[br(little, magic = b"ThisIsOneFile\0\0\0")]
|
|
pub struct JodOne {
|
|
// usually 0xCC... format version maybe?
|
|
// but i've seen 0xCA in Test04/disp/Test04.one and 0xCB in Test05/disp/stg2010_sun.one
|
|
_unknown1: u32,
|
|
// usually "Default" or "landData"
|
|
#[br(pad_size_to = 32)]
|
|
pub category: NullString,
|
|
#[br(pad_after = 128)]
|
|
pub count: u32,
|
|
#[br(count = count)]
|
|
pub entries: Vec<JodOneEntry>
|
|
}
|
|
|
|
#[derive(BinRead)]
|
|
#[br(little, assert(id_again == id))]
|
|
pub struct JodOneEntry {
|
|
pub _unknown1: u32,
|
|
pub id: u32,
|
|
pub size_cmp: u32,
|
|
pub _unknown2: u32,
|
|
pub size_dec: u32,
|
|
pub id_again: u32,
|
|
#[br(count = size_cmp)]
|
|
pub data: FilePtr<u32, Vec<u8>>,
|
|
#[br(pad_size_to = 188)]
|
|
pub name: NullString,
|
|
}
|
|
|
|
impl std::fmt::Debug for JodOneEntry {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "JodOneEntry{{id: {}, name: {:?}, size_cmp: {}, size_dec: {}, ..}}", self.id, self.name.to_string(), self.size_cmp, self.size_dec)
|
|
}
|
|
}
|
|
|
|
impl JodOne {
|
|
pub fn unpack(self) -> BTreeMap<PathBuf, Vec<u8>> {
|
|
let mut map = BTreeMap::new();
|
|
for entry in self.entries {
|
|
debug!("{:?}", entry);
|
|
let os_string = OsString::from_vec(entry.name.0.into_iter()
|
|
.map(|c| if char::from(c) == '\\' { std::path::MAIN_SEPARATOR as u8 } else { c })
|
|
.collect());
|
|
let key = PathBuf::from(os_string);
|
|
if entry.size_dec == 0 {
|
|
map.insert(key, entry.data.into_inner());
|
|
} else {
|
|
// TODO: improve prs crate to use size_dec hint?
|
|
let dec_buf = prs::decompress::Decompressor::new(&*entry.data).decompress();
|
|
map.insert(key, dec_buf);
|
|
}
|
|
}
|
|
map
|
|
}
|
|
}
|
|
|