Skip to content

Research Report R4 Console Commands

LopeKinz edited this page Oct 1, 2026 · 1 revision

R4 Research Report: The Console Command Gate (TNC)

Static disassembly of a read-only snapshot of the running NewColossus_x64vk.exe process (no debugger attached, no game launched by this track). Builds on the command-table and cvar-table research already on the wiki.

Summary

The question was whether the retail console's ~34-command limit can be bypassed to reach commands like map, devmap, teleport, killMonsters, give, spawn, noclip and god without patching the executable. The gate turned out to be a single process-wide integer shared by the command and cvar systems: at rest it is 0 (unrestricted, all 234 commands / 3,256 cvars searchable), and only narrow, self-restoring windows — one console keystroke, one exec, one startup line — force it to 1 (the restricted, 34-command list) and then put it back. The already-proven command resourceExec <file> -s is the one built-in command that deliberately drops the level to 0 for the duration of the file it runs, making every registered command and cvar reachable with no code patch. All of this is static analysis of the executable image; nothing below was confirmed with the game actually running. Correction applied to this report's own earlier claim: SpawnAI is not a registered command in this retail build, the same as give, spawn, noclip and lowercase god — none of these five names appear anywhere in the 234-entry command table, under any flag.

1. The shared gate

idCmdSystemLocal (RVA 0x4104420) holds two command lists — "all" (234 entries) and "exposed" (34 entries) — plus a restriction-level field at +0x200b8 (RVA 0x41244d8). idCVarSystemLocal shares the identical global for its own 3,256-entry / 304-exposed split. The dispatcher (0x1265150) picks which list to search with one cmp/cmove against that global:

level == 0  -> search all 234 commands / 3,256 cvars
level != 0  -> search only the 34 exposed commands / 304 exposed cvars

A command not in the active list prints Unknown command '%s' — this is the entire reason map/devmap/teleport/killMonsters fail from a normal console line even though they are registered.

2. What sets the level, and that it always comes back

Six built-in entry points write 1 to the level: both console-input handlers, the +-prefixed startup-argument parser, the startup-config exec, the exec command itself, and the one-time engine Init() call. All six were disassembled in full: every one of them saves the old value and restores it before returning. Nothing in the binary ever leaves the level changed after it returns, and the constructor default is 0 — so for nearly the entire session the level simply sits at 0, unrestricted, except for the handful of instructions it takes to process one keystroke or one config line.

resourceExec (one of the 34 already-exposed commands, callback 0xa7a040) is the one path that deliberately sets the level to 0 while a resource-archive file it reads runs, then restores it afterward — this is the mechanism the existing custom-map/decl-edit route already relies on.

3. DevGUI: a second route, with a caveat

The compiled-in ImGui debug menu (idDevGuiMainPage_*/idDevGuiChildPage_*) calls the dispatcher directly from 74 call sites across 28 functions, and — unlike the six entry points above — without its own save/restore bracket, so a DevGUI click runs at whatever level is currently ambient (which is 0 essentially always). Of those 74 calls: 12 already work from the plain console (exposed), 41 are real registered-but-non-exposed commands/cvar toggles that become clickable once DevGUI is drawing, and 18 — including the DevGUI's own "Give Ammo", "Give Grenades" and "spawn %s" buttons — reference names that are not registered at all; those buttons are dead code, consistent with give/spawn not existing as commands.

devgui is itself a non-exposed cvar (needs the same level-0 window once to turn on, e.g. devgui 4), but after that its buttons keep working for the rest of the session with no further resourceExec call needed.

4. devMode_enable is a real gate, but an unreachable one

The dispatcher has a second branch, after a found command executes, that checks devMode_enable: if 0, it prints "Dev Mode is not enabled..." and returns without executing the command; if 1, it warns and executes anyway. This branch only fires for a command found at level !=0 that lacks the exposed bit — a combination none of the documented entry points (console, +args, exec, resourceExec) or the DevGUI calls ever produce (at level 1 only exposed commands are found; at level 0 the dispatcher already took its execute-immediately exit before this branch). So the branch is real but practically dead on every reachable path. devMode_enable and com_gameMode are themselves exposed, retail-settable cvars — a live process snapshot showed both already set to non-default values (1 and 5/GAMEMODE_MOD) with no crash — but neither one affects the restriction level.

5. Verdict per name

Name Registered? Exposed? Reachable without a patch?
map, devmap, cmap, fastmap, and the other map-load variants yes no yes, via resourceExec level-0 window
teleport, setviewpos, killMonsters, killAI, killAllAI yes no yes, via resourceExec
getviewpos, listCmds, exec, vid_restart, BuildInfo yes yes already works in the plain console
God, InfiniteHealth, NoPlayerDeath, Notarget yes (flag 0x200000) no yes, via resourceExec; no internal gate in the callback itself beyond "is a game active"
god (lowercase), noclip, spawn, give/give all, SpawnAI no — does not exist in this build at all — a code patch would be required to add it

listCmds is a cheap, non-destructive way to confirm the model in game: typed into the plain console it must print exactly 34 names; called from inside a resourceExec'd file it should print all 234.

6. Cvar equivalents for "give all" / infinite ammo / noclip

The cvar system shares the same gate, so these non-exposed CVAR_CHEAT cvars are reachable the same way, from inside a resourceExec'd file:

Cvar Description
g_infiniteAmmo 1 = infinite ammo for player/AI/turrets, 2 = infinite backpack ammo
g_infiniteEnergy / g_infiniteThrowItems infinite energy / infinite grenades
g_demoAmmo fully replenishes weapon ammo on every pickup
snapEdit_devMode "Sets dev mode on match parms. This will give the player ALL THE THINGS" — closest literal match to "give all"; untested, inferred to need setting before the map loads
pm_noclipspeed / pm_noclipfriction confirm a noclip mode exists in the engine, but no command named noclip triggers it in this build — likely only reachable from a DevGUI page not individually traced

7. The decl route (already proven, bypasses this gate entirely)

Decls are a completely separate subsystem from the command/cvar restriction level — they are data the resource loader reads, not something idCmdSystemLocal touches. For give/spawn, which do not exist as commands under any flag, the decl route (starting-inventory/pickup decls) is the actual mechanism the game uses, not a workaround.

Recipe

  1. Add a small script file reachable through the already-proven dlc_0-precedence mod route, e.g. sandbox.cfg:
    devgui 4
    devmap <map>
    
  2. From the normal, restricted console (which can still run resourceExec, it is one of the 34 exposed commands): resourceExec sandbox.cfg -s. Both lines run at level 0. devgui 4 is a one-time switch; afterward its ~50 confirmed-live buttons (g_infiniteAmmo, killAI/killAllAI, dozens of toggle <debug cvar> switches) work without any further resourceExec call.
  3. For anything DevGUI doesn't cover, or to batch several lines (God 1, Notarget 1, snapEdit_devMode 1, devmap <map>), put them in one file and call it the same way.
  4. For actually giving weapons/items (give/spawn do not exist as commands): use the decl/starting-inventory route instead — see the pickups report.

Open questions

  • Whether resourceExec resolves a brand-new filename from a mod archive the same way it resolves an overridden existing name — untested.
  • Where the noclip mode implied by pm_noclipspeed/pm_noclipfriction is actually toggled if not by a console command.
  • Whether snapEdit_devMode truly grants "ALL THE THINGS", and at what point it is consumed.
  • Whether idCmdSystemLocal::Find's name lookup is case-sensitive (would decide whether some DevGUI button strings with different casing than the registered name are themselves silently dead).
  • A generic ExecuteCommandTextAtLevel-style helper (RVA 0x1265800) is called from ~14 places across the engine beyond Init()/DevGUI; whether any of the untraced call sites passes level 0 with a mod-controllable string during normal gameplay — independent of resourceExec and DevGUI — was not resolved.

Clone this wiki locally