hcb2lua_decompiler/
main.rs1use 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}