143 lines
4.8 KiB
Rust
143 lines
4.8 KiB
Rust
extern crate byteorder;
|
|
extern crate prs_rust;
|
|
|
|
use self::byteorder::{ReadBytesExt, WriteBytesExt, BigEndian, LittleEndian};
|
|
use self::prs_rust::prs;
|
|
use std::str;
|
|
use std::fs::File;
|
|
use std::io::{Read, Seek, SeekFrom, Write};
|
|
|
|
pub struct OneJod<R: Read + Seek> {
|
|
read_handle: R,
|
|
header: OneJodHead,
|
|
entries: Vec<OneJodEntry>,
|
|
}
|
|
|
|
impl<R> OneJod<R>
|
|
where
|
|
R: Read + Seek,
|
|
{
|
|
pub fn from_archive(mut input: R) -> OneJod<R> {
|
|
let mut head = OneJodHead {
|
|
magic: [0; 16],
|
|
_unknown1: 0,
|
|
category: [0; 32],
|
|
file_count: 0,
|
|
reserved: [0; 128],
|
|
};
|
|
input.read_exact(&mut head.magic);
|
|
assert_eq!(head.magic(), b"ThisIsOneFile\0\0\0");
|
|
head._unknown1 = input.read_u32::<byteorder::LittleEndian>().unwrap();
|
|
input.read_exact(&mut head.category);
|
|
head.file_count = input.read_u32::<byteorder::LittleEndian>().unwrap();
|
|
input.read_exact(&mut head.reserved);
|
|
|
|
let mut entries = Vec::new();
|
|
for i in 0..head.file_count() {
|
|
let mut entry = OneJodEntry {
|
|
_unknown1: 0,
|
|
id: 0,
|
|
size_cmp: 0,
|
|
_unknown2: 0,
|
|
size_dec: 0,
|
|
id_again: 0,
|
|
offset: 0,
|
|
file_name: [0; 188],
|
|
};
|
|
entry._unknown1 = input.read_u32::<byteorder::LittleEndian>().unwrap();
|
|
entry.id = input.read_u32::<byteorder::LittleEndian>().unwrap();
|
|
entry.size_cmp = input.read_u32::<byteorder::LittleEndian>().unwrap();
|
|
entry._unknown2 = input.read_u32::<byteorder::LittleEndian>().unwrap();
|
|
entry.size_dec = input.read_u32::<byteorder::LittleEndian>().unwrap();
|
|
entry.id_again = input.read_u32::<byteorder::LittleEndian>().unwrap();
|
|
entry.offset = input.read_u32::<byteorder::LittleEndian>().unwrap();
|
|
input.read_exact(&mut entry.file_name);
|
|
assert_eq!(entry.id(), i);
|
|
entries.push(entry);
|
|
}
|
|
|
|
OneJod{
|
|
read_handle: input,
|
|
header: head,
|
|
entries,
|
|
}
|
|
}
|
|
|
|
pub fn extract(&mut self) {
|
|
for entry in &self.entries {
|
|
let mut cmp_buf = vec![0u8; entry.size_cmp() as usize];
|
|
self.read_handle.seek(SeekFrom::Start(entry.offset() as u64));
|
|
self.read_handle.read_exact(cmp_buf.as_mut_slice());
|
|
let mut dec_buf = prs::decompress::Decompressor::new(&cmp_buf).decompress();
|
|
println!("{}", entry.file_name());
|
|
let mut file_out = File::create(entry.file_name()).unwrap();
|
|
file_out.write_all(&dec_buf);
|
|
}
|
|
}
|
|
}
|
|
|
|
struct OneJodHead {
|
|
magic: [u8; 16],
|
|
_unknown1: u32,
|
|
category: [u8; 32],
|
|
file_count: u32,
|
|
reserved: [u8; 128],
|
|
}
|
|
|
|
impl OneJodHead {
|
|
fn magic(&self) -> &[u8] { &self.magic }
|
|
fn magic_mut(&mut self) -> &mut [u8] { &mut self.magic }
|
|
|
|
fn _unknown1(&self) -> u32 { self._unknown1 }
|
|
fn set_unknown1(&mut self, n: u32) { self._unknown1 = n; }
|
|
|
|
// NB: may not really be utf8? should probably be ascii, though...
|
|
fn category(&self) -> &str { str::from_utf8(&self.category).unwrap() }
|
|
fn category_mut(&mut self) -> &mut str { str::from_utf8_mut(&mut self.category).unwrap() }
|
|
fn set_category(&mut self, n: &str) { self.category.copy_from_slice(n.as_bytes()); }
|
|
|
|
fn file_count(&self) -> u32 { self.file_count }
|
|
fn set_file_count(&mut self, n: u32) { self.file_count = n; }
|
|
|
|
fn reserved(&self) -> &[u8] { &self.reserved }
|
|
fn reserved_mut(&mut self) -> &mut [u8] { &mut self.reserved }
|
|
}
|
|
|
|
struct OneJodEntry {
|
|
_unknown1: u32,
|
|
id: u32,
|
|
size_cmp: u32,
|
|
_unknown2: u32,
|
|
size_dec: u32,
|
|
id_again: u32,
|
|
offset: u32,
|
|
file_name: [u8; 188],
|
|
}
|
|
|
|
impl OneJodEntry {
|
|
fn _unknown1(&self) -> u32 { self._unknown1 }
|
|
fn set_unknown1(&mut self, n: u32) { self._unknown1 = n; }
|
|
|
|
fn id(&self) -> u32 { assert_eq!(self.id, self.id_again); self.id }
|
|
fn set_id(&mut self, n: u32) { self.id = n; self.id_again = n; }
|
|
|
|
fn size_cmp(&self) -> u32 { self.size_cmp }
|
|
fn set_size_cmp(&mut self, n: u32) { self.size_cmp = n; }
|
|
|
|
fn _unknown2(&self) -> u32 { self._unknown2 }
|
|
fn set_unknown2(&mut self, n: u32) { self._unknown2 = n; }
|
|
|
|
fn size_dec(&self) -> u32 { self.size_dec }
|
|
fn set_size_dec(&mut self, n: u32) { self.size_dec = n; }
|
|
|
|
fn offset(&self) -> u32 { self.offset }
|
|
fn set_offset(&mut self, n: u32) { self.offset = n; }
|
|
|
|
fn file_name(&self) -> &str {
|
|
let idx = self.file_name.iter().position(|x| *x == 0u8).unwrap();
|
|
str::from_utf8(&self.file_name[0..idx]).unwrap()
|
|
}
|
|
fn file_name_mut(&mut self) -> &mut str { str::from_utf8_mut(&mut self.file_name).unwrap() }
|
|
fn set_file_name(&mut self, n: &str) { self.file_name.copy_from_slice(n.as_bytes()); }
|
|
}
|