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.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# 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]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "one-rust"
|
name = "one-rust"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"binread",
|
||||||
"prs-rust 0.1.0",
|
"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]]
|
[[package]]
|
||||||
name = "prs-rust"
|
name = "prs-rust"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[metadata]
|
[[package]]
|
||||||
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
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>"]
|
authors = ["lifning <lifning+git@pm.me>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
binread = "1"
|
||||||
|
binwrite = "0.2"
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
prs-rust = { path = "../prs-rust" }
|
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;
|
use binread::{FilePtr, NullString};
|
||||||
extern crate prs_rust;
|
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};
|
#[derive(BinRead)]
|
||||||
use self::prs_rust::prs;
|
#[br(little, magic = b"ThisIsOneFile\0\0\0")]
|
||||||
use std::fs::File;
|
pub struct JodOne {
|
||||||
use std::io::{Read, Seek, SeekFrom, Write};
|
_unknown1: u32,
|
||||||
use std::str;
|
#[br(pad_size_to = 32)]
|
||||||
|
pub category: NullString,
|
||||||
pub struct OneJodArchive<R: Read + Seek> {
|
#[br(pad_after = 128)]
|
||||||
read_handle: R,
|
pub count: u32,
|
||||||
_header: OneJodHead,
|
#[br(count = count)]
|
||||||
entries: Vec<OneJodEntry>,
|
pub entries: Vec<JodOneEntry>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read + Seek> OneJodArchive<R> {
|
#[derive(BinRead)]
|
||||||
pub fn from_file(mut input: R) -> std::io::Result<OneJodArchive<R>> {
|
#[br(little, assert(id_again == id))]
|
||||||
let mut magic = [0; 16];
|
pub struct JodOneEntry {
|
||||||
input.read_exact(&mut magic)?;
|
pub _unknown1: u32,
|
||||||
let _unknown1 = input.read_u32::<LittleEndian>()?;
|
pub id: u32,
|
||||||
let mut category = [0; 32];
|
pub size_cmp: u32,
|
||||||
input.read_exact(&mut category)?;
|
pub _unknown2: u32,
|
||||||
let file_count = input.read_u32::<LittleEndian>()?;
|
pub size_dec: u32,
|
||||||
let mut reserved = [0; 128];
|
pub id_again: u32,
|
||||||
input.read_exact(&mut reserved)?;
|
#[br(count = size_cmp)]
|
||||||
let head = OneJodHead {
|
pub data: FilePtr<u32, Vec<u8>>,
|
||||||
magic,
|
#[br(pad_size_to = 188)]
|
||||||
_unknown1,
|
pub name: NullString,
|
||||||
category,
|
}
|
||||||
file_count,
|
|
||||||
reserved,
|
|
||||||
};
|
|
||||||
assert_eq!(head.magic(), b"ThisIsOneFile\0\0\0");
|
|
||||||
|
|
||||||
let mut entries = Vec::new();
|
impl JodOne {
|
||||||
for i in 0..head.file_count() {
|
pub fn extract(&mut self) -> BTreeMap<PathBuf, Vec<u8>> {
|
||||||
let _unknown1 = input.read_u32::<LittleEndian>()?;
|
let mut map = BTreeMap::new();
|
||||||
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<()> {
|
|
||||||
for entry in &self.entries {
|
for entry in &self.entries {
|
||||||
let mut cmp_buf = vec![0u8; entry.size_cmp() as usize];
|
// TODO: improve prs crate to use size_dec hint?
|
||||||
self.read_handle.seek(SeekFrom::Start(entry.offset() as u64))?;
|
let dec_buf = prs::decompress::Decompressor::new(&*entry.data).decompress();
|
||||||
self.read_handle.read_exact(cmp_buf.as_mut_slice())?;
|
map.insert(PathBuf::from(OsStr::from_bytes(&entry.name.0)), dec_buf);
|
||||||
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)?;
|
|
||||||
}
|
}
|
||||||
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