hcb2lua_decompiler/
main.rs1use std::fs;
2use std::path::{Path, PathBuf};
3
4use anyhow::Result;
5use clap::Parser as ClapParser;
6
7mod cfg;
8mod decode;
9mod lua;
10mod lua_opt;
11mod opcode;
12mod parser;
13
14use crate::decode::decode_program;
15use crate::lua::emit_lua_script;
16use crate::parser::{Nls, Parser};
17
18#[derive(ClapParser, Debug)]
19#[command(version, about = "HCB bytecode to Lua decompiler")]
20struct Args {
21 #[arg(short, long)]
22 input: PathBuf,
23
24 #[arg(short, long)]
25 output: PathBuf,
26
27 #[arg(short, long, default_value = "sjis")]
28 lang: Nls,
29}
30
31fn output_dir_from_file(output: &Path) -> PathBuf {
32 output
33 .parent()
34 .unwrap_or_else(|| Path::new("."))
35 .to_path_buf()
36}
37
38fn main() -> Result<()> {
39 let args = Args::parse();
40
41 if let Some(parent) = args.output.parent() {
42 if !parent.as_os_str().is_empty() {
43 fs::create_dir_all(parent)?;
44 }
45 }
46 let mut writer = fs::File::create(&args.output)?;
47
48 let parser = Parser::new(&args.input, args.lang)?;
49 let program = decode_program(&parser)?;
50 let mut functions = Vec::new();
51 for (_, func) in &program.functions {
52 functions.push((*func).clone());
53 }
54 emit_lua_script(&mut writer, &parser, &functions)?;
55
56 let name = parser.get_title();
57 let ymal_name = if name.is_empty() {
58 "output".to_string() + ".yaml"
59 } else {
60 name.to_string() + ".yaml"
61 };
62
63 let yaml_path = output_dir_from_file(&args.output).join(ymal_name);
64 parser.export_yaml(yaml_path)?;
65 Ok(())
66}