start rewriting to use binread

This commit is contained in:
lifning 2021-01-13 03:19:39 -08:00
parent 9d76a56506
commit b402893878
6 changed files with 172 additions and 154 deletions

109
Cargo.lock generated
View File

@ -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"

View File

@ -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" }

21
examples/onear.rs Normal file
View File

@ -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(())
}

7
src/lib.rs Normal file
View File

@ -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::*;

View File

@ -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(())
}

View File

@ -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()); }
}