add a subcommand to describe .one archives

This commit is contained in:
lifning 2021-01-16 04:00:50 -08:00
parent ccc06c81d1
commit 202f6cd640
2 changed files with 48 additions and 7 deletions

View File

@ -18,7 +18,8 @@ struct Args {
#[derive(FromArgs)]
#[argh(subcommand)]
enum Action {
ExtractFile(ExtractFile)
ExtractFile(ExtractFile),
DescribeFile(DescribeFile),
}
/// Unpack and decompress the files inside a .one archive.
@ -30,14 +31,23 @@ struct ExtractFile {
file: PathBuf,
}
/// Describe the metadata of a .one archive.
#[derive(FromArgs)]
#[argh(subcommand, name = "tf")]
struct DescribeFile {
/// path to the .one file
#[argh(positional)]
file: PathBuf,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Args = argh::from_env();
match args.action {
Action::ExtractFile(ex) => {
let mut infile = File::open(&ex.file)?;
Action::ExtractFile(subcmd) => {
let mut infile = File::open(&subcmd.file)?;
let archive: JodOne = infile.read_le()?;
let entries = archive.unpack();
let dir = PathBuf::from(format!("{}.d", ex.file.to_string_lossy()));
let dir = PathBuf::from(format!("{}.d", subcmd.file.to_string_lossy()));
for (name, data) in entries {
let full_path = dir.join(name);
if let Some(path) = full_path.parent() {
@ -46,6 +56,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
File::create(full_path)?.write_all(&data)?;
}
}
Action::DescribeFile(subcmd) => {
let mut infile = File::open(&subcmd.file)?;
let archive: JodOne = infile.read_le()?;
println!("{:?}", archive);
for entry in archive.entries {
println!("{:?}", entry);
}
}
}
Ok(())
}

View File

@ -1,6 +1,5 @@
use binread::{FilePtr, NullString};
use prs_rust::prs;
use std::ffi::OsString;
use std::fmt::Formatter;
use std::path::PathBuf;
@ -46,7 +45,7 @@ pub struct JodOneEntry {
pub _unknown1: u32,
pub id: u32,
pub size_cmp: u32,
pub _unknown2: u32,
pub is_compressed: u32,
pub size_dec: u32,
pub id_again: u32,
#[br(count = size_cmp)]
@ -57,14 +56,38 @@ pub struct JodOneEntry {
pub name: String,
}
impl std::fmt::Debug for JodOne {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "JodOne{{_unknown1: 0x{:x}, category: {}, count: {}, ..}}", self._unknown1, self.category, self.count)
}
}
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)
write!(
f,
"JodOneEntry{{_unknown1: 0x{:x}, id: {}, is_compressed: {}, name: {:?}, size_cmp: {}, size_dec: {}, ..}}",
self._unknown1, self.id, self.is_compressed != 0, self.name.to_string(), self.size_cmp, self.size_dec,
)
}
}
impl JodOne {
pub fn pack(inputs: impl Iterator<Item = (PathBuf, Vec<u8>)>, category: Option<&str>) -> Self {
let mut entries = Vec::new();
for (id, (path, data)) in inputs.enumerate() {
entries.push(JodOneEntry {
_unknown1: 0,
id: id as u32,
size_cmp: data.len() as u32,
is_compressed: 0,
size_dec: 0,
id_again: id as u32,
data: FilePtr { ptr: 0, value: Some(data) },
name: path.to_string_lossy().replace(std::path::MAIN_SEPARATOR, "\\"),
})
}
JodOne {
_unknown1: 0xCC,
category: category.unwrap_or("Default").to_string(),