bhd: hashes, tests and stuff
This commit is contained in:
parent
de2513e22a
commit
019818f5f0
38
Cargo.lock
generated
38
Cargo.lock
generated
|
@ -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"
|
||||||
|
|
|
@ -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
6240
res/namefile.txt
Normal file
File diff suppressed because it is too large
Load diff
34
src/main.rs
34
src/main.rs
|
@ -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
58
src/name_hashes.rs
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue