param: WIP combination with paramdef
This commit is contained in:
parent
7ab1f763f9
commit
da80ff1d9a
|
@ -217,8 +217,21 @@ fn cmd_paramdef(args: &ArgMatches) -> i32 {
|
||||||
|
|
||||||
fn cmd_param(args: &ArgMatches) -> i32 {
|
fn cmd_param(args: &ArgMatches) -> i32 {
|
||||||
let file_path: &str = args.value_of("file").unwrap();
|
let file_path: &str = args.value_of("file").unwrap();
|
||||||
match unpackers::param::load_param_file(file_path) {
|
|
||||||
|
if let Some(paramdef_path) = args.value_of("paramdef") {
|
||||||
|
match unpackers::paramdef::load_paramdef_file(paramdef_path) {
|
||||||
|
Ok(paramdef) => {
|
||||||
|
match unpackers::param::load_param_file(file_path, Some(¶mdef)) {
|
||||||
|
Ok(param) => { unpackers::param::print_param(¶m); 0 }
|
||||||
|
Err(e) => { eprintln!("Failed to load PARAM: {:?}", e); 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => { eprintln!("Failed to load PARAMDEF: {:?}", e); 1 }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match unpackers::param::load_param_file(file_path, None) {
|
||||||
Ok(param) => { unpackers::param::print_param_no_data(¶m); 0 }
|
Ok(param) => { unpackers::param::print_param_no_data(¶m); 0 }
|
||||||
Err(e) => { eprintln!("Failed to load PARAM: {:?}", e); 1 }
|
Err(e) => { eprintln!("Failed to load PARAM: {:?}", e); 1 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -39,6 +39,13 @@ pub union VarSizeInt {
|
||||||
pub vu64: u64,
|
pub vu64: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl VarSizeInt {
|
||||||
|
/// Set u64 value if condition is true, else the u32 as u64.
|
||||||
|
pub fn u64_if(&self, c: bool) -> u64 {
|
||||||
|
if c { unsafe { self.vu64 } } else { unsafe { self.vu32 as u64 } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Debug for VarSizeInt {
|
impl fmt::Debug for VarSizeInt {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "VarSizeInt: {{ {}: u32, {}: u64 }}", unsafe { self.vu32 }, unsafe { self.vu64 })
|
write!(f, "VarSizeInt: {{ {}: u32, {}: u64 }}", unsafe { self.vu32 }, unsafe { self.vu64 })
|
||||||
|
|
|
@ -5,6 +5,7 @@ use nom::number::complete::*;
|
||||||
use nom::sequence::tuple;
|
use nom::sequence::tuple;
|
||||||
|
|
||||||
use crate::parsers::common::{sjis_to_string, take_cstring, take_cstring_from, VarSizeInt};
|
use crate::parsers::common::{sjis_to_string, take_cstring, take_cstring_from, VarSizeInt};
|
||||||
|
use crate::parsers::paramdef;
|
||||||
use crate::utils::bin::has_flag;
|
use crate::utils::bin::has_flag;
|
||||||
|
|
||||||
const FLAGS2D_UNK1: u8 = 0b00000001;
|
const FLAGS2D_UNK1: u8 = 0b00000001;
|
||||||
|
@ -103,17 +104,7 @@ pub struct ParamRow {
|
||||||
pub ofs_data: VarSizeInt,
|
pub ofs_data: VarSizeInt,
|
||||||
pub ofs_name: VarSizeInt,
|
pub ofs_name: VarSizeInt,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
}
|
pub data: Vec<u8>,
|
||||||
|
|
||||||
impl ParamRow {
|
|
||||||
/// Get a u64 for the name offset, regardless of the format.
|
|
||||||
pub fn get_ofs_name(&self, header: &ParamHeader) -> u64 {
|
|
||||||
if header.has_u64_ofs_data() {
|
|
||||||
unsafe { self.ofs_name.vu64 }
|
|
||||||
} else {
|
|
||||||
unsafe { self.ofs_name.vu32 as u64 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_row<'a>(i: &'a[u8], header: &ParamHeader) -> IResult<&'a[u8], ParamRow> {
|
fn parse_row<'a>(i: &'a[u8], header: &ParamHeader) -> IResult<&'a[u8], ParamRow> {
|
||||||
|
@ -128,7 +119,7 @@ fn parse_row<'a>(i: &'a[u8], header: &ParamHeader) -> IResult<&'a[u8], ParamRow>
|
||||||
(i, (id, VarSizeInt { vu32: ofs_data }, VarSizeInt { vu32: ofs_name }))
|
(i, (id, VarSizeInt { vu32: ofs_data }, VarSizeInt { vu32: ofs_name }))
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((i, ParamRow { id, ofs_data, ofs_name, name: None }))
|
Ok((i, ParamRow { id, ofs_data, ofs_name, name: None, data: vec!() }))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -137,7 +128,7 @@ pub struct Param {
|
||||||
pub rows: Vec<ParamRow>,
|
pub rows: Vec<ParamRow>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(i: &[u8]) -> IResult<&[u8], Param> {
|
pub fn parse<'a>(i: &'a[u8], paramdef: Option<¶mdef::Paramdef>) -> IResult<&'a[u8], Param> {
|
||||||
let full_file = i;
|
let full_file = i;
|
||||||
let (i, mut header) = parse_header(i)?;
|
let (i, mut header) = parse_header(i)?;
|
||||||
if header.has_ofs_string_name() && header.ofs_name.is_some() {
|
if header.has_ofs_string_name() && header.ofs_name.is_some() {
|
||||||
|
@ -149,7 +140,7 @@ pub fn parse(i: &[u8]) -> IResult<&[u8], Param> {
|
||||||
let (i, mut rows) = count(|i| parse_row(i, &header), header.num_rows as usize)(i)?;
|
let (i, mut rows) = count(|i| parse_row(i, &header), header.num_rows as usize)(i)?;
|
||||||
|
|
||||||
for row in &mut rows {
|
for row in &mut rows {
|
||||||
let ofs_name = row.get_ofs_name(&header) as usize;
|
let ofs_name = row.ofs_name.u64_if(header.has_u64_ofs_data()) as usize;
|
||||||
if ofs_name != 0 {
|
if ofs_name != 0 {
|
||||||
let (_, name) = take_cstring(&full_file[ofs_name..])?;
|
let (_, name) = take_cstring(&full_file[ofs_name..])?;
|
||||||
row.name = sjis_to_string(name).or_else(|| {
|
row.name = sjis_to_string(name).or_else(|| {
|
||||||
|
@ -159,5 +150,17 @@ pub fn parse(i: &[u8]) -> IResult<&[u8], Param> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if paramdef.is_some() {
|
||||||
|
let row_size = paramdef.unwrap().row_size();
|
||||||
|
for row in &mut rows {
|
||||||
|
let ofs_data = row.ofs_data.u64_if(header.has_u64_ofs_data()) as usize;
|
||||||
|
if ofs_data == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
let ofs_data_end = ofs_data + row_size;
|
||||||
|
row.data = full_file[ofs_data..ofs_data_end].to_vec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok((i, Param { header, rows }))
|
Ok((i, Param { header, rows }))
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ pub fn load_bhf_file(bhf_path: &str) -> Result<bhf::Bhf, UnpackError> {
|
||||||
load_bhf(&bhf_data)
|
load_bhf(&bhf_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load a BHF file from a bytes slice.
|
/// Load a BHF file from a byte slice.
|
||||||
pub fn load_bhf(bhf_data: &[u8]) -> Result<bhf::Bhf, UnpackError> {
|
pub fn load_bhf(bhf_data: &[u8]) -> Result<bhf::Bhf, UnpackError> {
|
||||||
match bhf::parse(&bhf_data) {
|
match bhf::parse(&bhf_data) {
|
||||||
Ok((_, bhf)) => Ok(bhf),
|
Ok((_, bhf)) => Ok(bhf),
|
||||||
|
|
|
@ -3,28 +3,56 @@ use std::path;
|
||||||
use nom::Err::{Error as NomError, Failure as NomFailure};
|
use nom::Err::{Error as NomError, Failure as NomFailure};
|
||||||
|
|
||||||
use crate::parsers::param;
|
use crate::parsers::param;
|
||||||
|
use crate::parsers::paramdef;
|
||||||
use crate::unpackers::errors::UnpackError;
|
use crate::unpackers::errors::UnpackError;
|
||||||
use crate::utils::fs as utils_fs;
|
use crate::utils::fs as utils_fs;
|
||||||
use crate::utils::str as utils_str;
|
use crate::utils::str as utils_str;
|
||||||
|
|
||||||
pub fn load_param_file(param_path: &str) -> Result<param::Param, UnpackError> {
|
/// Load a PARAM file from disk.
|
||||||
|
///
|
||||||
|
/// Wraps around `load_param` to load the PARAM from disk.
|
||||||
|
pub fn load_param_file(
|
||||||
|
param_path: &str,
|
||||||
|
paramdef: Option<¶mdef::Paramdef>
|
||||||
|
) -> Result<param::Param, UnpackError> {
|
||||||
let param_data = utils_fs::open_file_to_vec(path::Path::new(param_path))?;
|
let param_data = utils_fs::open_file_to_vec(path::Path::new(param_path))?;
|
||||||
Ok(load_param(¶m_data)?)
|
Ok(load_param(¶m_data, paramdef)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_param(param_data: &[u8]) -> Result<param::Param, UnpackError> {
|
/// Load a PARAM from a byte slice.
|
||||||
match param::parse(param_data) {
|
///
|
||||||
|
/// If paramdef is provided, it copies the right amount of bytes into
|
||||||
|
/// row data, without parsing them. Else it loads the PARAM with
|
||||||
|
/// empty row data.
|
||||||
|
pub fn load_param(
|
||||||
|
param_data: &[u8],
|
||||||
|
paramdef: Option<¶mdef::Paramdef>
|
||||||
|
) -> Result<param::Param, UnpackError> {
|
||||||
|
match param::parse(param_data, paramdef) {
|
||||||
Ok((_, result)) => Ok(result),
|
Ok((_, result)) => Ok(result),
|
||||||
Err(NomError(e)) | Err(NomFailure(e)) => Err(UnpackError::parsing_err("PARAM", e.1)),
|
Err(NomError(e)) | Err(NomFailure(e)) => Err(UnpackError::parsing_err("PARAM", e.1)),
|
||||||
Err(e) => Err(UnpackError::Unknown(format!("Unknown error: {:?}", e))),
|
Err(e) => Err(UnpackError::Unknown(format!("Unknown error: {:?}", e))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_param_no_data(param: ¶m::Param) {
|
fn print_param_intro(param: ¶m::Param) {
|
||||||
println!("{} -- {}", param.header.param_type,
|
println!(
|
||||||
utils_str::n_plural(param.header.num_rows as i32, "row", "rows"));
|
"{} -- {}",
|
||||||
|
param.header.param_type,
|
||||||
|
utils_str::n_pluralise(param.header.num_rows as i32, "row", "rows")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_param_no_data(param: ¶m::Param) {
|
||||||
|
print_param_intro(param);
|
||||||
for row in ¶m.rows {
|
for row in ¶m.rows {
|
||||||
println!(" - [{}] {}", row.id, row.name.as_ref().unwrap_or(&String::from("<noname>")));
|
println!(" - [{}] {}", row.id, row.name.as_ref().unwrap_or(&String::from("<noname>")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn print_param(param: ¶m::Param) {
|
||||||
|
print_param_intro(param);
|
||||||
|
for row in ¶m.rows {
|
||||||
|
println!("{:?}", row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,11 +7,15 @@ use crate::unpackers::errors::UnpackError;
|
||||||
use crate::utils::fs as utils_fs;
|
use crate::utils::fs as utils_fs;
|
||||||
use crate::utils::str as utils_str;
|
use crate::utils::str as utils_str;
|
||||||
|
|
||||||
|
/// Load a PARAMDEF file from disk.
|
||||||
|
///
|
||||||
|
/// Wraps around `load_paramdef` to load the PARAMDEF from disk.
|
||||||
pub fn load_paramdef_file(paramdef_path: &str) -> Result<paramdef::Paramdef, UnpackError> {
|
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))?;
|
let paramdef_data = utils_fs::open_file_to_vec(path::Path::new(paramdef_path))?;
|
||||||
Ok(load_paramdef(¶mdef_data)?)
|
Ok(load_paramdef(¶mdef_data)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Load a PARAMDEF file from a byte slice.
|
||||||
pub fn load_paramdef(paramdef_data: &[u8]) -> Result<paramdef::Paramdef, UnpackError> {
|
pub fn load_paramdef(paramdef_data: &[u8]) -> Result<paramdef::Paramdef, UnpackError> {
|
||||||
match paramdef::parse(paramdef_data) {
|
match paramdef::parse(paramdef_data) {
|
||||||
Ok((_, result)) => Ok(result),
|
Ok((_, result)) => Ok(result),
|
||||||
|
@ -20,6 +24,7 @@ pub fn load_paramdef(paramdef_data: &[u8]) -> Result<paramdef::Paramdef, UnpackE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Print brief data about a PARAMDEF.
|
||||||
pub fn print_paramdef_intro(paramdef: ¶mdef::Paramdef) {
|
pub fn print_paramdef_intro(paramdef: ¶mdef::Paramdef) {
|
||||||
println!(
|
println!(
|
||||||
"{} -- ver. {} -- format ver. {} -- {} fields -- {} per row",
|
"{} -- ver. {} -- format ver. {} -- {} fields -- {} per row",
|
||||||
|
@ -30,6 +35,7 @@ pub fn print_paramdef_intro(paramdef: ¶mdef::Paramdef) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Print verbose data about a PARAMDEF.
|
||||||
pub fn print_paramdef(paramdef: ¶mdef::Paramdef) {
|
pub fn print_paramdef(paramdef: ¶mdef::Paramdef) {
|
||||||
print_paramdef_intro(paramdef);
|
print_paramdef_intro(paramdef);
|
||||||
for field in ¶mdef.fields {
|
for field in ¶mdef.fields {
|
||||||
|
|
Reference in a new issue