start rewriting to use binread
This commit is contained in:
parent
9d76a56506
commit
b402893878
|
@ -1,21 +1,122 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "binread"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "258d2d861723c05ad02956cae4878ceddb5e05b0dc2841ca73a3479ab7a46f4d"
|
||||
dependencies = [
|
||||
"binread_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "binread_derive"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d63ec80ac459fd10ae68854c26ee1c5ab5ac93866dba8f8a95cabbfeaa79b284"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "binwrite"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42c3da1db1f384ad643e27cb6ba4f08f2a7cd8753bef8dd95c39fe45d7a474c8"
|
||||
dependencies = [
|
||||
"binwrite_derive",
|
||||
"paste",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "binwrite_derive"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "476f17c19ce04226ba997c229ce8fb96eaef1c0e0745ec91d8df35f723aae353"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
||||
|
||||
[[package]]
|
||||
name = "one-rust"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"prs-rust 0.1.0",
|
||||
"binread",
|
||||
"binwrite",
|
||||
"byteorder",
|
||||
"prs-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880"
|
||||
dependencies = [
|
||||
"paste-impl",
|
||||
"proc-macro-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste-impl"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prs-rust"
|
||||
version = "0.1.0"
|
||||
|
||||
[metadata]
|
||||
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||
|
|
|
@ -4,5 +4,7 @@ version = "0.1.0"
|
|||
authors = ["lifning <lifning+git@pm.me>"]
|
||||
|
||||
[dependencies]
|
||||
binread = "1"
|
||||
binwrite = "0.2"
|
||||
byteorder = "1"
|
||||
prs-rust = { path = "../prs-rust" }
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
extern crate one_rust;
|
||||
extern crate binread;
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use binread::prelude::*;
|
||||
use one_rust::JodOne;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
for arg in &args[1..] {
|
||||
let mut infile = File::open(arg)?;
|
||||
let mut archive: JodOne = infile.read_le()?;
|
||||
let entries = archive.extract();
|
||||
for (name, data) in entries {
|
||||
File::create(name)?.write_all(&data)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
extern crate byteorder;
|
||||
extern crate prs_rust;
|
||||
#[macro_use] extern crate binread;
|
||||
#[macro_use] extern crate binwrite;
|
||||
|
||||
mod one;
|
||||
pub use one::*;
|
13
src/main.rs
13
src/main.rs
|
@ -1,13 +0,0 @@
|
|||
use std::env;
|
||||
use std::fs::File;
|
||||
|
||||
pub mod one;
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
for arg in &args[1..] {
|
||||
let mut infile = File::open(arg)?;
|
||||
one::OneJodArchive::from_file(&mut infile)?.extract()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
174
src/one/mod.rs
174
src/one/mod.rs
|
@ -1,146 +1,46 @@
|
|||
extern crate byteorder;
|
||||
extern crate prs_rust;
|
||||
use binread::{FilePtr, NullString};
|
||||
use prs_rust::prs;
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::PathBuf;
|
||||
use std::ffi::OsStr;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
|
||||
use self::byteorder::{ReadBytesExt, LittleEndian};
|
||||
use self::prs_rust::prs;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
use std::str;
|
||||
|
||||
pub struct OneJodArchive<R: Read + Seek> {
|
||||
read_handle: R,
|
||||
_header: OneJodHead,
|
||||
entries: Vec<OneJodEntry>,
|
||||
#[derive(BinRead)]
|
||||
#[br(little, magic = b"ThisIsOneFile\0\0\0")]
|
||||
pub struct JodOne {
|
||||
_unknown1: u32,
|
||||
#[br(pad_size_to = 32)]
|
||||
pub category: NullString,
|
||||
#[br(pad_after = 128)]
|
||||
pub count: u32,
|
||||
#[br(count = count)]
|
||||
pub entries: Vec<JodOneEntry>
|
||||
}
|
||||
|
||||
impl<R: Read + Seek> OneJodArchive<R> {
|
||||
pub fn from_file(mut input: R) -> std::io::Result<OneJodArchive<R>> {
|
||||
let mut magic = [0; 16];
|
||||
input.read_exact(&mut magic)?;
|
||||
let _unknown1 = input.read_u32::<LittleEndian>()?;
|
||||
let mut category = [0; 32];
|
||||
input.read_exact(&mut category)?;
|
||||
let file_count = input.read_u32::<LittleEndian>()?;
|
||||
let mut reserved = [0; 128];
|
||||
input.read_exact(&mut reserved)?;
|
||||
let head = OneJodHead {
|
||||
magic,
|
||||
_unknown1,
|
||||
category,
|
||||
file_count,
|
||||
reserved,
|
||||
};
|
||||
assert_eq!(head.magic(), b"ThisIsOneFile\0\0\0");
|
||||
#[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,
|
||||
}
|
||||
|
||||
let mut entries = Vec::new();
|
||||
for i in 0..head.file_count() {
|
||||
let _unknown1 = input.read_u32::<LittleEndian>()?;
|
||||
let id = input.read_u32::<LittleEndian>()?;
|
||||
let size_cmp = input.read_u32::<LittleEndian>()?;
|
||||
let _unknown2 = input.read_u32::<LittleEndian>()?;
|
||||
let size_dec = input.read_u32::<LittleEndian>()?;
|
||||
let id_again = input.read_u32::<LittleEndian>()?;
|
||||
let offset = input.read_u32::<LittleEndian>()?;
|
||||
let mut file_name = [0u8; 188];
|
||||
input.read_exact(&mut file_name)?;
|
||||
let entry = OneJodEntry {
|
||||
_unknown1,
|
||||
id,
|
||||
size_cmp,
|
||||
_unknown2,
|
||||
size_dec,
|
||||
id_again,
|
||||
offset,
|
||||
file_name,
|
||||
};
|
||||
assert_eq!(entry.id(), i);
|
||||
entries.push(entry);
|
||||
}
|
||||
|
||||
Ok(OneJodArchive {
|
||||
read_handle: input,
|
||||
_header: head,
|
||||
entries,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn extract(&mut self) -> std::io::Result<()> {
|
||||
impl JodOne {
|
||||
pub fn extract(&mut self) -> BTreeMap<PathBuf, Vec<u8>> {
|
||||
let mut map = BTreeMap::new();
|
||||
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 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)?;
|
||||
// TODO: improve prs crate to use size_dec hint?
|
||||
let dec_buf = prs::decompress::Decompressor::new(&*entry.data).decompress();
|
||||
map.insert(PathBuf::from(OsStr::from_bytes(&entry.name.0)), dec_buf);
|
||||
}
|
||||
Ok(())
|
||||
map
|
||||
}
|
||||
}
|
||||
|
||||
struct OneJodHead {
|
||||
magic: [u8; 16],
|
||||
_unknown1: u32,
|
||||
category: [u8; 32],
|
||||
file_count: u32,
|
||||
reserved: [u8; 128],
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
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],
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
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()); }
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue