104 lines
2.7 KiB
Rust
104 lines
2.7 KiB
Rust
use std::{
|
|
collections::HashMap,
|
|
fs::{read_dir, read_to_string, File},
|
|
};
|
|
|
|
use truth::{context::RootEmitter, io::BinReader, AnmFile, Game, Mapfile, StdFile};
|
|
|
|
fn parse_files(
|
|
game_folder: &str,
|
|
game: Game,
|
|
map_file_name: &str,
|
|
ext: &str,
|
|
csv_path: &str,
|
|
hit_file: impl Fn(&mut BinReader) -> Vec<u16>,
|
|
) {
|
|
let map_file = Mapfile::load(map_file_name, Some(game), &RootEmitter::new_stderr(), |_| {
|
|
Ok((None, read_to_string(map_file_name).unwrap()))
|
|
})
|
|
.unwrap();
|
|
let dir = read_dir(format!("assets/{game_folder}")).unwrap();
|
|
let mut map = HashMap::new();
|
|
for file in dir {
|
|
let file = file.unwrap();
|
|
if file.path().extension().unwrap_or_default() != ext {
|
|
continue;
|
|
}
|
|
|
|
log::info!("file: {file:?}");
|
|
for op in hit_file(&mut BinReader::from_reader(
|
|
&RootEmitter::new_stderr(),
|
|
&file.file_name().to_string_lossy().to_owned(),
|
|
&File::open(file.path()).unwrap(),
|
|
)) {
|
|
*map.entry(op).or_insert(0) += 1;
|
|
}
|
|
}
|
|
|
|
let mut csv = csv::Writer::from_path(csv_path).unwrap();
|
|
let mut vec = map.into_iter().collect::<Vec<_>>();
|
|
vec.sort_by_key(|c| c.0);
|
|
for (op, count) in vec {
|
|
log::info!("hitting op {op}");
|
|
let str_name = map_file
|
|
.ins_names
|
|
.iter()
|
|
.find(|i| i.0 == op as i32)
|
|
.map(|v| v.1.value.as_str().to_owned())
|
|
.unwrap_or(format!("unk_inst_{op}"));
|
|
csv.write_field(str_name).unwrap();
|
|
csv.write_field(op.to_string()).unwrap();
|
|
csv.write_field(count.to_string()).unwrap();
|
|
csv.write_record(None::<&[u8]>).unwrap();
|
|
}
|
|
|
|
csv.flush().unwrap();
|
|
}
|
|
|
|
fn parse_game(game_folder: &str, game: Game) {
|
|
let thver = format!("th{}", game.as_number());
|
|
|
|
parse_files(
|
|
game_folder,
|
|
game,
|
|
&format!("utils/{thver}.eclm"),
|
|
"ecl",
|
|
&format!("target/{game_folder}_ecl_inst.csv"),
|
|
|reader| {
|
|
let file = truth::StackEclFile::read_from_stream(reader, game).unwrap();
|
|
|
|
file.subs.values().flat_map(|sub| sub.iter().map(|f| f.opcode)).collect()
|
|
},
|
|
);
|
|
parse_files(
|
|
game_folder,
|
|
game,
|
|
&format!("utils/{thver}.stdm"),
|
|
"std",
|
|
&format!("target/{game_folder}_std_inst.csv"),
|
|
|reader| {
|
|
let file = StdFile::read_from_stream(reader, game).unwrap();
|
|
|
|
file.script.into_iter().map(|f| f.opcode).collect()
|
|
},
|
|
);
|
|
parse_files(
|
|
game_folder,
|
|
game,
|
|
&format!("utils/{thver}.anmm"),
|
|
"anm",
|
|
&format!("target/{game_folder}_anm_inst.csv"),
|
|
|reader| {
|
|
let file = AnmFile::read_from_stream(reader, game, false).unwrap();
|
|
|
|
file.entries.iter().flat_map(|f| f.scripts.values()).flat_map(|f| f.instrs.iter()).map(|f| f.opcode).collect()
|
|
},
|
|
);
|
|
}
|
|
|
|
fn main() {
|
|
env_logger::init();
|
|
parse_game("sa", Game::Th11);
|
|
parse_game("mof", Game::Th10);
|
|
}
|