Skip to main content

hcb2lua_decompiler/
main.rs

1use 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}