2024-03-28 20:19:20 +08:00
|
|
|
#![feature(lazy_cell)]
|
2023-09-25 22:46:10 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
use std::path::PathBuf;
|
2024-03-01 23:02:58 +08:00
|
|
|
use std::time::Instant;
|
2024-03-28 20:19:20 +08:00
|
|
|
use std::{env, fs};
|
2023-10-20 13:23:43 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
use clap::*;
|
2023-10-26 13:41:34 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
use log::{info, Level};
|
2023-09-28 22:41:21 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
use memflow::prelude::v1::*;
|
2023-10-26 13:41:34 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
use simplelog::{ColorChoice, TermLogger};
|
2023-10-26 13:41:34 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
use config::CONFIG;
|
|
|
|
use error::Result;
|
|
|
|
use output::Results;
|
2023-09-25 22:46:10 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
mod analysis;
|
2023-09-25 22:46:10 +08:00
|
|
|
mod config;
|
2024-03-28 20:19:20 +08:00
|
|
|
mod error;
|
|
|
|
mod output;
|
|
|
|
mod source_engine;
|
2023-09-28 22:41:21 +08:00
|
|
|
|
2023-09-25 22:46:10 +08:00
|
|
|
fn main() -> Result<()> {
|
2024-03-28 20:19:20 +08:00
|
|
|
let start_time = Instant::now();
|
|
|
|
|
|
|
|
let matches = parse_args();
|
2024-03-29 21:11:34 +08:00
|
|
|
let (conn_name, conn_args, os_name, indent_size, out_dir) = extract_args(&matches)?;
|
2024-03-28 20:19:20 +08:00
|
|
|
|
|
|
|
// Create the output directory if it doesn't exist.
|
|
|
|
fs::create_dir_all(&out_dir)?;
|
|
|
|
|
|
|
|
let os = if let Some(conn_name) = conn_name {
|
|
|
|
let inventory = Inventory::scan();
|
|
|
|
|
|
|
|
inventory
|
|
|
|
.builder()
|
|
|
|
.connector(&conn_name)
|
|
|
|
.args(conn_args)
|
2024-03-29 21:11:34 +08:00
|
|
|
.os(&os_name)
|
2024-03-28 20:19:20 +08:00
|
|
|
.build()?
|
2023-10-01 12:43:48 +08:00
|
|
|
} else {
|
2024-03-28 20:19:20 +08:00
|
|
|
// Fallback to the native OS layer if no connector name was provided.
|
|
|
|
memflow_native::create_os(&Default::default(), Default::default())?
|
2023-10-01 12:43:48 +08:00
|
|
|
};
|
2023-09-28 22:41:21 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
let mut process = os.into_process_by_name(&CONFIG.executable)?;
|
2023-10-26 13:41:34 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
let buttons = analysis::buttons(&mut process)?;
|
|
|
|
let interfaces = analysis::interfaces(&mut process)?;
|
|
|
|
let offsets = analysis::offsets(&mut process)?;
|
|
|
|
let schemas = analysis::schemas(&mut process)?;
|
2023-10-01 12:43:48 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
let results = Results::new(buttons, interfaces, offsets, schemas);
|
2023-09-25 22:46:10 +08:00
|
|
|
|
2024-03-28 22:44:06 +08:00
|
|
|
results.dump_all(&mut process, &out_dir, indent_size)?;
|
2024-03-28 20:19:20 +08:00
|
|
|
|
|
|
|
info!("finished in {:?}", start_time.elapsed());
|
2023-09-25 22:46:10 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
Ok(())
|
|
|
|
}
|
2023-10-26 13:41:34 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
fn parse_args() -> ArgMatches {
|
|
|
|
Command::new("cs2-dumper")
|
|
|
|
.version(crate_version!())
|
|
|
|
.author(crate_authors!())
|
|
|
|
.arg(
|
|
|
|
Arg::new("verbose")
|
|
|
|
.help("Increase logging verbosity. Can be specified multiple times.")
|
|
|
|
.short('v')
|
|
|
|
.action(ArgAction::Count),
|
|
|
|
)
|
|
|
|
.arg(
|
|
|
|
Arg::new("connector")
|
|
|
|
.help("The name of the memflow connector to use.")
|
|
|
|
.long("connector")
|
|
|
|
.short('c')
|
|
|
|
.required(false),
|
|
|
|
)
|
|
|
|
.arg(
|
|
|
|
Arg::new("connector-args")
|
|
|
|
.help("Additional arguments to supply to the connector.")
|
|
|
|
.long("connector-args")
|
|
|
|
.short('a')
|
|
|
|
.required(false),
|
|
|
|
)
|
|
|
|
.arg(
|
2024-03-29 21:11:34 +08:00
|
|
|
Arg::new("os")
|
|
|
|
.help("The name of the target operating system.")
|
|
|
|
.long("os")
|
2024-03-28 20:19:20 +08:00
|
|
|
.short('o')
|
2024-03-29 21:11:34 +08:00
|
|
|
.required(false),
|
|
|
|
)
|
|
|
|
.arg(
|
|
|
|
Arg::new("directory")
|
|
|
|
.help("The output directory to write the generated files to.")
|
|
|
|
.long("directory")
|
|
|
|
.short('d')
|
2024-03-28 20:19:20 +08:00
|
|
|
.default_value("output")
|
|
|
|
.value_parser(value_parser!(PathBuf))
|
|
|
|
.required(false),
|
|
|
|
)
|
|
|
|
.arg(
|
|
|
|
Arg::new("indent-size")
|
|
|
|
.help("The number of spaces to use per indentation level.")
|
|
|
|
.long("indent-size")
|
|
|
|
.short('i')
|
|
|
|
.default_value("4")
|
|
|
|
.value_parser(value_parser!(usize))
|
|
|
|
.required(false),
|
|
|
|
)
|
|
|
|
.get_matches()
|
|
|
|
}
|
2023-12-12 10:53:24 +08:00
|
|
|
|
2024-03-29 21:11:34 +08:00
|
|
|
fn extract_args(
|
|
|
|
matches: &ArgMatches,
|
|
|
|
) -> Result<(Option<String>, ConnectorArgs, String, usize, &PathBuf)> {
|
2024-03-28 20:19:20 +08:00
|
|
|
use std::str::FromStr;
|
2023-09-28 22:41:21 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
let log_level = match matches.get_count("verbose") {
|
|
|
|
0 => Level::Error,
|
|
|
|
1 => Level::Warn,
|
|
|
|
2 => Level::Info,
|
|
|
|
3 => Level::Debug,
|
|
|
|
4 => Level::Trace,
|
|
|
|
_ => Level::Trace,
|
|
|
|
};
|
2023-09-28 22:41:21 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
TermLogger::init(
|
|
|
|
log_level.to_level_filter(),
|
|
|
|
Default::default(),
|
|
|
|
Default::default(),
|
|
|
|
ColorChoice::Auto,
|
|
|
|
)
|
|
|
|
.unwrap();
|
2023-09-25 22:46:10 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
let conn_name = matches
|
|
|
|
.get_one::<String>("connector")
|
|
|
|
.map(|s| s.to_string());
|
2023-09-25 22:46:10 +08:00
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
let conn_args = matches
|
|
|
|
.get_one::<String>("connector-args")
|
|
|
|
.map(|s| ConnectorArgs::from_str(&s).expect("unable to parse connector arguments"))
|
|
|
|
.unwrap_or_default();
|
2023-09-25 22:46:10 +08:00
|
|
|
|
2024-03-29 21:11:34 +08:00
|
|
|
let os_name = matches
|
|
|
|
.get_one::<String>("os")
|
|
|
|
.map(|s| s.to_string())
|
|
|
|
.unwrap_or_else(|| match env::consts::OS {
|
|
|
|
"linux" => "linux".to_string(),
|
|
|
|
"windows" => "win32".to_string(),
|
|
|
|
_ => panic!("unsupported os"),
|
|
|
|
});
|
|
|
|
|
2024-03-28 20:19:20 +08:00
|
|
|
let indent_size = *matches.get_one::<usize>("indent-size").unwrap();
|
2024-03-29 21:11:34 +08:00
|
|
|
let out_dir = matches.get_one::<PathBuf>("directory").unwrap();
|
2023-11-01 08:01:39 +08:00
|
|
|
|
2024-03-29 21:11:34 +08:00
|
|
|
Ok((conn_name, conn_args, os_name, indent_size, out_dir))
|
2023-11-01 08:01:39 +08:00
|
|
|
}
|