bhd: hashes, tests and stuff

This commit is contained in:
Dece 2020-04-14 02:40:21 +02:00
parent de2513e22a
commit 019818f5f0
6 changed files with 6365 additions and 16 deletions

38
Cargo.lock generated
View file

@ -26,6 +26,11 @@ dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "autocfg"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.2.1" version = "1.2.1"
@ -96,6 +101,33 @@ dependencies = [
"version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "num-bigint"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-integer"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-traits"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "rustc_version" name = "rustc_version"
version = "0.2.3" version = "0.2.3"
@ -110,6 +142,8 @@ version = "0.1.0"
dependencies = [ dependencies = [
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nom 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "nom 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -186,6 +220,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
@ -195,6 +230,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" "checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
"checksum nom 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b471253da97532da4b61552249c521e01e736071f71c1a4f7ebbfbf0a06aad6" "checksum nom 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b471253da97532da4b61552249c521e01e736071f71c1a4f7ebbfbf0a06aad6"
"checksum num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum ryu 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" "checksum ryu 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"

View file

@ -9,3 +9,5 @@ edition = "2018"
[dependencies] [dependencies]
clap = "2.33" clap = "2.33"
nom = "5" nom = "5"
num-bigint = "0.2"
num-traits = "0.2"

6240
res/namefile.txt Normal file

File diff suppressed because it is too large Load diff

View file

@ -9,12 +9,14 @@ use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
//extern crate nom; //extern crate nom;
use nom::Err::{Error as NomError, Failure as NomFailure}; use nom::Err::{Error as NomError, Failure as NomFailure};
mod name_hashes;
mod parsers { mod parsers {
pub mod bhd; pub mod bhd;
} }
use parsers::*; use parsers::*;
fn main() { fn main() {
let default_namefilepath: &str = &get_default_namefilepath();
let matches = App::new("Rusted Iron Ring") let matches = App::new("Rusted Iron Ring")
.setting(AppSettings::ArgRequiredElseHelp) .setting(AppSettings::ArgRequiredElseHelp)
.subcommand(SubCommand::with_name("bhd") .subcommand(SubCommand::with_name("bhd")
@ -31,7 +33,8 @@ fn main() {
.short("n") .short("n")
.long("names") .long("names")
.takes_value(true) .takes_value(true)
.required(false))) .required(false)
.default_value(default_namefilepath)))
.get_matches(); .get_matches();
match matches.subcommand() { match matches.subcommand() {
@ -40,17 +43,25 @@ fn main() {
} }
} }
fn get_default_namefilepath() -> String {
let programpath: PathBuf = current_exe().unwrap();
let programdir: &Path = programpath.parent().unwrap();
let mut namefilepath: PathBuf = PathBuf::from(programdir);
namefilepath.push("res/namefile.json");
String::from(namefilepath.to_str().unwrap())
}
fn cmd_bhd(args: &ArgMatches) -> Result::<(), Error> { fn cmd_bhd(args: &ArgMatches) -> Result::<(), Error> {
let filepath: &str = args.value_of("file").unwrap(); let filepath: &str = args.value_of("file").unwrap();
let outputpath: &str = args.value_of("output").unwrap(); let outputpath: &str = args.value_of("output").unwrap();
let namefilepath: &str = args.value_of("namefile").unwrap_or(&get_default_namefilepath()); let namefilepath: &str = args.value_of("namefile").unwrap();
let mut bhd_file: File = File::open(filepath)?; let mut bhd_file = File::open(filepath)?;
let file_len = bhd_file.metadata()?.len() as usize; let file_len = bhd_file.metadata()?.len() as usize;
let mut bhd_data = vec![0u8; file_len]; let mut bhd_data = vec![0u8; file_len];
bhd_file.read_exact(&mut bhd_data)?; bhd_file.read_exact(&mut bhd_data)?;
let bhd = match bhd::parse(&bhd_data) { let bhd = match bhd::parse(&bhd_data) {
Ok((_, bhd)) => { println!("BHD: {:?}", bhd); bhd } Ok((_, bhd)) => { bhd }
Err(NomError(e)) | Err(NomFailure(e)) => { Err(NomError(e)) | Err(NomFailure(e)) => {
let (_, kind) = e; let (_, kind) = e;
let reason = format!("{:?} {:?}", kind, kind.description()); let reason = format!("{:?} {:?}", kind, kind.description());
@ -61,13 +72,12 @@ fn cmd_bhd(args: &ArgMatches) -> Result::<(), Error> {
} }
}; };
let names = name_hashes::load_name_map(&namefilepath)?;
let bdt_filepath = PathBuf::from(filepath).with_extension("bdt");
let bdt_file = File::open(bdt_filepath.to_str().unwrap())?;
bhd::extract(&bhd, &bdt_file, &names, &outputpath);
Ok(()) Ok(())
} }
fn get_default_namefilepath() -> String {
let programpath: PathBuf = current_exe().unwrap();
let programdir: &Path = programpath.parent().unwrap();
let mut namefilepath: PathBuf = PathBuf::from(programdir);
namefilepath.push("res/namefile.json");
String::from(namefilepath.to_str().unwrap())
}

58
src/name_hashes.rs Normal file
View file

@ -0,0 +1,58 @@
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufRead, BufReader, Error};
extern crate num_bigint;
use num_bigint::BigUint;
extern crate num_traits;
use num_traits::identities::Zero;
/// Compute the weird hash for a string. Same mechanic since DeS.
pub fn hash(s: &str) -> u32 {
let s = s.to_lowercase();
let mut val = BigUint::zero();
for c in s.chars() {
val *= 37u8;
val += c as u32;
}
val.to_u32_digits()[0]
}
/// Get the string representation for this hash.
pub fn hash_as_string(h: u32) -> String {
format!("{:08X}", h)
}
/// Load a namelist file into a map.
///
/// Format for the input file should be the following for every line:
/// CAFECAFE: /chr/whatever.ext
pub fn load_name_map(path: &str) -> Result<HashMap<String, String>, Error> {
let mut names = HashMap::new();
let namefile = File::open(path)?;
for line_ in BufReader::new(namefile).lines() {
if let Ok(line) = line_ {
let (hash, name) = line.split_at(8);
names.insert(hash.to_string(), name[2..].to_string());
}
}
println!("{:?}", names);
Ok(names)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hash() {
assert_eq!(hash("/chr/c0000.anibnd.dcx"), 0xF8630FB1);
assert_eq!(hash("/param/DrawParam/default_DrawParam.parambnd.dcx"), 0xD9209D30);
}
#[test]
fn test_hash_as_string() {
assert_eq!(hash_as_string(0xCAFECAFE), "CAFECAFE");
assert_eq!(hash_as_string(0xDECE), "0000DECE");
}
}

View file

@ -1,3 +1,6 @@
use std::collections::HashMap;
use std::fs::File;
extern crate nom; extern crate nom;
use nom::{IResult}; use nom::{IResult};
use nom::combinator::verify; use nom::combinator::verify;
@ -78,7 +81,6 @@ pub fn parse(i: &[u8]) -> IResult<&[u8], Bhd> {
let mut buckets: Vec<Vec<BhdFile>> = vec!(); let mut buckets: Vec<Vec<BhdFile>> = vec!();
for b in 0..header.num_buckets { for b in 0..header.num_buckets {
println!("Bucket {}", b);
let bucket_info = &bucket_infos[b as usize]; let bucket_info = &bucket_infos[b as usize];
let bucket_data = &full_file[bucket_info.offset as usize..]; let bucket_data = &full_file[bucket_info.offset as usize..];
let (_, bucket) = count(parse_file, bucket_info.count as usize)(bucket_data)?; let (_, bucket) = count(parse_file, bucket_info.count as usize)(bucket_data)?;
@ -89,7 +91,6 @@ pub fn parse(i: &[u8]) -> IResult<&[u8], Bhd> {
} }
/// Extract files from a BHD/BDT pair. /// Extract files from a BHD/BDT pair.
pub fn extract(bhd: Bhd, bdt_path: &str) { pub fn extract(bhd: &Bhd, bdt_file: &File, names: &HashMap<String, String>, outputpath: &str) {
// TODO
} }