paramdef: WIP parsing
This commit is contained in:
parent
4777affc2b
commit
09151b6579
14
README.md
14
README.md
|
@ -16,8 +16,8 @@ Usage
|
||||||
|
|
||||||
The project contains 2 artefacts:
|
The project contains 2 artefacts:
|
||||||
|
|
||||||
- `librir`, a library containing all the parsing/unpacking features implemented.
|
- `ironring`, a library with all the parsing/unpacking features implemented.
|
||||||
- `ironring`, an executable to use main lib features from the CLI.
|
- `rir`, an executable to use main lib features from the CLI.
|
||||||
|
|
||||||
The goal is to make the lib compatible with FFI tools such as Python's ctypes,
|
The goal is to make the lib compatible with FFI tools such as Python's ctypes,
|
||||||
to ship a dynamic lib accessible for any language to easily script tasks and
|
to ship a dynamic lib accessible for any language to easily script tasks and
|
||||||
|
@ -26,10 +26,10 @@ ideas, but we're not there yet.
|
||||||
Ironring usage:
|
Ironring usage:
|
||||||
|
|
||||||
```
|
```
|
||||||
Iron Ring
|
Rusted Iron Ring
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
ironring [SUBCOMMAND]
|
rir [SUBCOMMAND]
|
||||||
|
|
||||||
FLAGS:
|
FLAGS:
|
||||||
-h, --help Prints help information
|
-h, --help Prints help information
|
||||||
|
@ -64,6 +64,12 @@ Repacking is not supported, maybe one day. It is not that useful when using
|
||||||
[yabber]: https://github.com/JKAnderson/Yabber
|
[yabber]: https://github.com/JKAnderson/Yabber
|
||||||
[sieglib]: https://github.com/Dece/DarkSoulsDev/tree/master/Programs/SiegLib
|
[sieglib]: https://github.com/Dece/DarkSoulsDev/tree/master/Programs/SiegLib
|
||||||
|
|
||||||
|
There is a demo Python binding for some `name_hashes` features in the
|
||||||
|
`bindings/python` dir, that uses [PyO3][pyo3] and thus requires nightly rustc to
|
||||||
|
build.
|
||||||
|
|
||||||
|
[pyo3]: https://pyo3.rs/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Credits
|
Credits
|
||||||
|
|
|
@ -73,6 +73,11 @@ fn main() {
|
||||||
.arg(Arg::with_name("overwrite")
|
.arg(Arg::with_name("overwrite")
|
||||||
.help("Overwrite existing files")
|
.help("Overwrite existing files")
|
||||||
.short("f").long("force").takes_value(false).required(false)))
|
.short("f").long("force").takes_value(false).required(false)))
|
||||||
|
.subcommand(SubCommand::with_name("paramdef")
|
||||||
|
.about("TODO")
|
||||||
|
.arg(Arg::with_name("file")
|
||||||
|
.help("PARAMDEF file path")
|
||||||
|
.takes_value(true).required(true)))
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
process::exit(match matches.subcommand() {
|
process::exit(match matches.subcommand() {
|
||||||
|
@ -82,6 +87,7 @@ fn main() {
|
||||||
("dcx", Some(s)) => { cmd_dcx(s) }
|
("dcx", Some(s)) => { cmd_dcx(s) }
|
||||||
("bnd", Some(s)) => { cmd_bnd(s) }
|
("bnd", Some(s)) => { cmd_bnd(s) }
|
||||||
("bhf", Some(s)) => { cmd_bhf(s) }
|
("bhf", Some(s)) => { cmd_bhf(s) }
|
||||||
|
("paramdef", Some(s)) => { cmd_paramdef(s) }
|
||||||
_ => { 0 }
|
_ => { 0 }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -191,3 +197,11 @@ fn cmd_bhf(args: &ArgMatches) -> i32 {
|
||||||
_ => 0
|
_ => 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cmd_paramdef(args: &ArgMatches) -> i32 {
|
||||||
|
let file_path: &str = args.value_of("file").unwrap();
|
||||||
|
match unpackers::paramdef::load_paramdef_file(file_path) {
|
||||||
|
Ok(paramdef) => { unpackers::paramdef::print_paramdef(¶mdef); 0 }
|
||||||
|
Err(e) => { eprintln!("Failed to load PARAMDEF: {:?}", e); 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ pub mod parsers {
|
||||||
pub mod bnd;
|
pub mod bnd;
|
||||||
pub mod common;
|
pub mod common;
|
||||||
pub mod dcx;
|
pub mod dcx;
|
||||||
|
pub mod paramdef;
|
||||||
}
|
}
|
||||||
pub mod unpackers {
|
pub mod unpackers {
|
||||||
pub mod bhd;
|
pub mod bhd;
|
||||||
|
@ -14,6 +15,7 @@ pub mod unpackers {
|
||||||
pub mod bnd;
|
pub mod bnd;
|
||||||
pub mod dcx;
|
pub mod dcx;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
|
pub mod paramdef;
|
||||||
}
|
}
|
||||||
pub mod utils {
|
pub mod utils {
|
||||||
pub mod bin;
|
pub mod bin;
|
||||||
|
|
56
src/parsers/paramdef.rs
Normal file
56
src/parsers/paramdef.rs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
use nom::IResult;
|
||||||
|
use nom::bytes::complete::{tag, take};
|
||||||
|
use nom::multi::count;
|
||||||
|
use nom::number::complete::*;
|
||||||
|
use nom::sequence::tuple;
|
||||||
|
|
||||||
|
use crate::parsers::common::{sjis_to_string, take_cstring};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ParamdefHeader {
|
||||||
|
pub file_size: u32,
|
||||||
|
pub header_size: u16,
|
||||||
|
pub data_version: u16,
|
||||||
|
pub num_entries: u16,
|
||||||
|
pub entry_size: u16,
|
||||||
|
pub param_name: Vec<u8>,
|
||||||
|
pub endianness: u8,
|
||||||
|
pub unicode: u8,
|
||||||
|
pub format_version: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_header(i: &[u8]) -> IResult<&[u8], ParamdefHeader> {
|
||||||
|
let p_u32 = if i[0x2C] == 0xFF { be_u32 } else { le_u32 };
|
||||||
|
let p_u16 = if i[0x2C] == 0xFF { be_u16 } else { le_u16 };
|
||||||
|
let (i, (file_size, header_size, data_version, num_entries, entry_size)) =
|
||||||
|
tuple((p_u32, p_u16, p_u16, p_u16, p_u16))(i)?;
|
||||||
|
let (_, param_name) = take_cstring(&i[..0x20])?;
|
||||||
|
let (i, (endianness, unicode, format_version)) =
|
||||||
|
tuple((le_u8, le_u8, p_u16))(&i[0x20..])?;
|
||||||
|
Ok((
|
||||||
|
i,
|
||||||
|
ParamdefHeader {
|
||||||
|
file_size,
|
||||||
|
header_size,
|
||||||
|
data_version,
|
||||||
|
num_entries,
|
||||||
|
entry_size,
|
||||||
|
param_name: param_name.to_vec(),
|
||||||
|
endianness,
|
||||||
|
unicode,
|
||||||
|
format_version,
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Paramdef {
|
||||||
|
pub header: ParamdefHeader,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse(i: &[u8]) -> IResult<&[u8], Paramdef> {
|
||||||
|
let (i, header) = parse_header(i)?;
|
||||||
|
Ok((i, Paramdef { header }))
|
||||||
|
}
|
|
@ -81,10 +81,9 @@ pub fn get_decompressed_path(dcx_path: &str, output_path: Option<&str>) -> Optio
|
||||||
if path::Path::new(&output_path).is_dir() {
|
if path::Path::new(&output_path).is_dir() {
|
||||||
output_path_valid = false;
|
output_path_valid = false;
|
||||||
if let Some(file_pb) = utils_fs::strip_extension(&path::PathBuf::from(&dcx_path)) {
|
if let Some(file_pb) = utils_fs::strip_extension(&path::PathBuf::from(&dcx_path)) {
|
||||||
if let Some(file_name) = file_pb.file_name() {
|
if let Some(file_name) = file_pb.file_name().and_then(|s| s.to_str()) {
|
||||||
if let Some(file_name_str) = file_name.to_str() {
|
|
||||||
let mut out_pb = path::PathBuf::from(&output_path);
|
let mut out_pb = path::PathBuf::from(&output_path);
|
||||||
out_pb.push(file_name_str);
|
out_pb.push(file_name);
|
||||||
if let Some(s) = out_pb.as_path().to_str() {
|
if let Some(s) = out_pb.as_path().to_str() {
|
||||||
output_path.clear();
|
output_path.clear();
|
||||||
output_path.push_str(s);
|
output_path.push_str(s);
|
||||||
|
@ -93,7 +92,6 @@ pub fn get_decompressed_path(dcx_path: &str, output_path: Option<&str>) -> Optio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if !output_path_valid {
|
if !output_path_valid {
|
||||||
eprintln!("Can't determine a valid output path: {}", dcx_path);
|
eprintln!("Can't determine a valid output path: {}", dcx_path);
|
||||||
return None
|
return None
|
||||||
|
|
24
src/unpackers/paramdef.rs
Normal file
24
src/unpackers/paramdef.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
use std::path;
|
||||||
|
|
||||||
|
use nom::Err::{Error as NomError, Failure as NomFailure};
|
||||||
|
|
||||||
|
use crate::parsers::paramdef;
|
||||||
|
use crate::unpackers::errors::UnpackError;
|
||||||
|
use crate::utils::fs as utils_fs;
|
||||||
|
|
||||||
|
pub fn load_paramdef_file(paramdef_path: &str) -> Result<paramdef::Paramdef, UnpackError> {
|
||||||
|
let paramdef_data = utils_fs::open_file_to_vec(path::Path::new(paramdef_path))?;
|
||||||
|
Ok(load_paramdef(¶mdef_data)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_paramdef(paramdef_data: &[u8]) -> Result<paramdef::Paramdef, UnpackError> {
|
||||||
|
match paramdef::parse(paramdef_data) {
|
||||||
|
Ok((_, result)) => Ok(result),
|
||||||
|
Err(NomError(e)) | Err(NomFailure(e)) => Err(UnpackError::parsing_err("PARAMDEF", e.1)),
|
||||||
|
e => Err(UnpackError::Unknown(format!("Unknown error: {:?}", e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_paramdef(paramdef: ¶mdef::Paramdef) {
|
||||||
|
println!("{:?}", paramdef);
|
||||||
|
}
|
Reference in a new issue