read what the binary says about itself: names, signatures, prototypes; gen v2
All checks were successful
CI / lint (push) Successful in 17s
CI / fuzz (push) Successful in 1m52s
CI / test (push) Successful in 24s

This commit is contained in:
Kamal Tufekcic 2026-07-29 20:09:21 +03:00
commit c458b4cb50
34 changed files with 58363 additions and 192 deletions

View file

@ -15,6 +15,7 @@ use std::path::PathBuf;
#[derive(Parser)]
#[command(
name = "source2rosetta-gen",
version,
about = "Render a source2rosetta monolith into a framework gamedata format"
)]
struct Cli {
@ -24,9 +25,17 @@ struct Cli {
/// The typed `netvars-<game>.json` (for a SCHEMA --format: cs-sdk/netvars).
#[arg(long)]
netvars: Option<PathBuf>,
/// The prototype manifest `abi-<game>.json` — renders CALL SHAPES (declared parameter and return
/// types, verified against the build) instead of locators. Reuses the framework --format ids: the
/// INPUT chooses what is rendered, so `--abi … --format cssharp` emits typed call sites while
/// `--from … --format cssharp` emits the gamedata those calls resolve through.
#[arg(long)]
abi: Option<PathBuf>,
/// Output format. GAMEDATA (needs --from): cssharp | metamod | modsharp | swiftly | plugify | model.
/// SCHEMA (needs --netvars): cs-sdk (typed C# SDK) | netvars (flat offset map). cssharp = the
/// `//`-bannered CS# combined file; metamod also covers SourceMod (the VDF `.games.txt`).
/// SCHEMA (needs --netvars): cs-sdk (typed C# SDK) | netvars (flat offset map). ABI (needs --abi):
/// cssharp | metamod | modsharp | swiftly | plugify. cssharp = the `//`-bannered CS# combined file;
/// the metamod gamedata format also covers SourceMod (the VDF `.games.txt`), while its ABI format is
/// a C++ header, because Metamod plugins are C++ and declare prototypes in source.
#[arg(long, default_value = "cssharp")]
format: String,
/// Confidence tier for a gamedata format (cumulative): core | high_confidence | experimental. Defaults to
@ -42,7 +51,18 @@ fn main() -> Result<()> {
let cli = Cli::parse();
let fmt = cli.format.as_str();
let text = if render::SCHEMA_FORMAT_IDS.contains(&fmt) {
// The INPUT selects the emitter family, which is why `cssharp` can name three different outputs.
let text = if let Some(path) = cli.abi.as_ref() {
let man: model::AbiManifest = serde_json::from_str(&std::fs::read_to_string(path)?)
.with_context(|| format!("parse abi manifest json {}", path.display()))?;
let e = render::abi_by_id(fmt).with_context(|| {
format!(
"unknown ABI --format `{fmt}` (known: {})",
render::ABI_FORMAT_IDS.join(" | ")
)
})?;
e.render(&man)
} else if render::SCHEMA_FORMAT_IDS.contains(&fmt) {
// schema formats render the typed netvars (class -> field -> offset/type), not the gamedata monolith.
let path = cli.netvars.as_ref().context(
"a schema --format (cs-sdk | netvars) requires --netvars <netvars-<game>.json>",