hcb2lua_decompiler/
main.rs

1use std::fs;
2use std::path::{Path, PathBuf};
3
4use anyhow::Result;
5use clap::Parser as ClapParser;
6
7mod decode;
8mod cfg;
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
31
32fn output_dir_from_file(output: &Path) -> PathBuf {
33    output
34        .parent()
35        .unwrap_or_else(|| Path::new("."))
36        .to_path_buf()
37}
38
39fn main() -> Result<()> {
40    let args = Args::parse();
41
42    if let Some(parent) = args.output.parent() {
43        if !parent.as_os_str().is_empty() {
44            fs::create_dir_all(parent)?;
45        }
46    }
47    let mut writer = fs::File::create(&args.output)?;
48
49    let parser = Parser::new(&args.input, args.lang)?;
50    let program = decode_program(&parser)?;
51    let mut functions = Vec::new();
52    for (_, func) in &program.functions {
53        functions.push((*func).clone());
54    }
55    emit_lua_script(&mut writer, &parser, &functions)?;
56
57    let name = parser.get_title();
58    let ymal_name = if name.is_empty() {
59        "output".to_string() + ".yaml"
60    } else {
61        name.to_string() + ".yaml"
62    };
63
64    let yaml_path = output_dir_from_file(&args.output).join(ymal_name);
65    parser.export_yaml(yaml_path)?;
66    Ok(())
67}