Round-8 pass on The New Order's cvar registry, read from the decrypted runtime image: the full registered cvar list with flags and ranges, the startup order of command-line cvars, the cheat reset and the startup commands, and the force path behind toggle. It audits every TNO cvar the loader can emit and documents the resulting loader change: cheat cvars are now also sent as +toggle name value value, which survives the reset. Static only; the one-launch in-game test at the end has not been run.
Static only. Nothing launched or attached to, and nothing written under the game folder or Saved
Games. Source: the decrypted runtime capture re_probes/runtime_tno_186352 (base 0x7ff74a390000)
plus Ghidra (tools/decomp.py --gzf D:/wolf-decomp/ghidra/tno_runtime.gzf --snapshot re_probes/runtime_tno_186352).
1. Registry: method and counts
The registry walk worked, so nothing had to fall back to string mining.
idCVar::Init (RVA 0x9dea10) links every cvar into one list:
mov rax,[0x1ef6cf0]; mov [rbx+0x70],rax; mov [0x1ef6cf0],rbx. The cheat reset in
idCommonLocal::Init walks this same list (r7). Every node is a static object in .data.
The layout comes from the constructor's own stores: +0x00 value idStr, +0x28 int, +0x2c
float, +0x30 name, +0x38 reset string, +0x40 description, +0x48 flags, +0x4c min,
+0x50 max, +0x58 value-string list, +0x60 completion, +0x70 next. "No range" is
min > max (1, -1).
tools/extract_cvars_tno.py pins those constructor bytes. It walks the list and writes
docs/cvars_tno.json ({source, count, cvars:[{name, description, value(=reset/default), type,
flags, min, max, values}]}, sorted). --self-check re-walks the list and compares the result
with the file.
| cvars | 3194, 0 duplicates, the walk ends at NULL, every node lies inside the image |
| CHEAT / NOCHEAT | 2865 / 329. Every entry has exactly one of the two, as the constructor's test edi,0x1c010 predicts |
| ROM / INIT / ARCHIVE | 8 / 38 / 169. Flag bits 0x20-0x2000 are never used |
| ranges / value lists | 130 / 4 |
| plausibility | TNC's registrar dump has 3256 cvars (same engine family). 3132 of the 4543 prefix_name-shaped .rdata strings are registered (the rest are entity keys, decls and so on). 807 of the 877 kind=cvar entries of the old adjacency miner (tno_cmdtable.json) are registered. 692 of its 1154 kind=cmd entries are actually cvars, so that table's cmd/cvar split is unreliable |
| negative check | 0 of the 192 real commands (re_probes/tnocommands/commands.json) are cvars. map devmap toggle kill teleport exec bind god noclip notarget give are all absent |
| known cvars | com_allowConsole BOOL CHEAT, devgui INTEGER CHEAT 0..2 (both as r7 P2.2 predicts). g_permaGodMode BOOL NOCHEAT ARCHIVE, g_fov INTEGER NOCHEAT 10..100, pm_runspeed FLOAT CHEAT |
Correction to r7 P2.4: g_permaGodMode and g_permaInfiniteAmmo are not cheat cvars. Both are
ARCHIVE, and therefore NOCHEAT.
2. Startup order (new, decompiled idCommonLocal::Init 0x133380 and FUN 0x130b70)
This also answers r7's open question about where the command-line +cvar parser lives.
0x13365c:FUN_130b70(args, 1)runs over every+name valuepair. For each name that is a cvar, it callsSet(cvar, value, force=1)(0x9dd3f0->0x9dd2d0), INIT cvars included.0x1337ad:com_skipIntroVideois read here (cmp [0x161e248],0, the flag goes to the intro start).build.cfg, thenFUN_130b70again (0x13397b). Thenexec default.cfg(4 devices),wolfConfig.cfg(gated lines), and an inline third pass of+cvarpairs that skips INIT cvars and force-sets the rest (0x133d99). So a+name valuebeats the user's wolfConfig.cfg.0x133e22:ResetFlaggedVariables(CHEAT), the cheat reset.- After
Init: the startup commands (+toggle,+bind). Measured:+toggle devguisurvives the reset (docs/limits.md).
toggle (0x9ddc00, decompiled):
- With 2 or 3 arguments it is a float toggle (non-zero -> 0, else the value).
- With 4 or more arguments it cycles through the values, comparing them with the current string.
- It sets through cvar-system slot
+0x38, the force path (r7 P2.1). - So
toggle name v valways ends atv: on a match it takesargv[3], otherwise it wraps toargv[2]. It logsname = v.
3. Audit: every TNO cvar the loader can emit
Emitters: the catalogue (31), ALWAYS (com_skipIntroVideo), cli launch --god/--ammo/--console/--skip-intro/--fov
(all catalogue names), the saved config.json tweaks (catalogue names), and the free-text box.
No TNO mod carries cvars.
| cvar | loader (old): kind / default / range | registry: type / default / range | flags | old +name v result |
new delivery |
|---|---|---|---|---|---|
| g_permaGodMode | bool / 0 / | bool / 0 / | NOCHEAT ARCHIVE | works (force-set after wolfConfig.cfg) | +name v |
| g_permaInfiniteAmmo | bool / 0 / | bool / 0 / | NOCHEAT ARCHIVE | works | +name v |
| g_infiniteAmmo | bool / 0 / | bool / 0 / | CHEAT | broken: set, then wiped by the reset | +name v + +toggle name v v |
| g_damageScale | float / 1 / 0..10 | float / 1 / | NOCHEAT ARCHIVE | works (damage taken, the note was wrong) | +name v |
| ai_damageScale | float / 1 / 0..10 | float / 1.0 / | CHEAT | broken | + toggle |
| ai_invulnerable | bool / 0 / | bool / 0 / | CHEAT | broken | + toggle |
| g_AimAssist_Disable_All | bool / 0 / | bool / 0 / | CHEAT | broken | + toggle |
| g_playerHealthRegenSpeed | float / ? / 0..1000 | float / 5.75 / | CHEAT | broken | + toggle |
| g_playerHealthRegenDelay | float / ? / 0..10000 | float / 3 / | CHEAT | broken | + toggle |
| g_gravity | float / ? / -2000..2000 | float / 1066 / | CHEAT | broken | + toggle |
| g_gameDifficulty | choice 0-3 "easy..very hard" | int / -1 / -1..4 | CHEAT | broken, choices wrong (-1 = game's own, 0 very easy .. 4 nightmare) | + toggle |
| g_fov | int / 80 / 60..130 | int / 80 / 10..100 | NOCHEAT | works; values >100 are clamped (UpdateValue 0x9dcf10 reads min/max) |
+name v |
| pm_noBob | bool / 0 / | bool / 0 / | CHEAT | broken | + toggle |
| pm_togglesprint | bool / 0 / | bool / 1 / | NOCHEAT ARCHIVE | works; default was wrong | +name v |
| pm_autoSprint | bool / 0 / | bool / 0 / | CHEAT | broken | + toggle |
| com_skipIntroVideo (ALWAYS) | bool / 0 / | bool / 0 / | CHEAT | probably works: read at 0x1337ad, before the reset (r6's "does not work" came from the reset log line only) |
+name v kept, toggle harmless |
| com_allowConsole | bool / 0 / | bool / 0 / | CHEAT | broken, and the label was false: it does not gate the console (r7 P2.4); its only reader is game init -> achievement check | + toggle; note says leave it off |
| com_showFPS | bool / 0 / | int / 0 / 0..2 | NOCHEAT ARCHIVE | works | +name v |
| r_swapInterval | choice / -1 / | int / -1 / | NOCHEAT | works | +name v |
| g_showHud | bool / 1 / | bool / 1 / | NOCHEAT ARCHIVE | works (+g_showHud 0 verified in game) |
+name v |
| g_EnableGore | bool / 1 / | int / 1 / | CHEAT | broken; actually 0 blood only / 1 gore / 2 none | + toggle |
| g_bloodEffects | bool / 1 / | bool / 1 / | NOCHEAT ARCHIVE | works | +name v |
| g_goreBloodyMess | bool "Maximum gore" / 0 | float / 2.0 / | CHEAT | broken, and wrong meaning: a perk gore-probability factor, so "1" lowers it | + toggle; now a float entry |
| pm_runspeed / walk / sprint / crouch | float / ? | float / 260 / 140 / 450 / 115 | CHEAT | broken | + toggle |
| pm_jumpheight | float / ? | float / 62 | CHEAT | broken | + toggle |
| pm_noclipspeed | float / ? | float / 400 | CHEAT | broken, and pointless: there is no noclip command | + toggle |
| pm_sprintMaxTime | float / ? / 0..100000 | int / 1500 / 1..100000 | CHEAT | broken | + toggle |
| g_freeCamSpeed | float / ? | float / 1.0 | CHEAT | broken | + toggle |
Cross-check against the measured lists: 0 mismatches. All 26 RETAIL_BLOCKED names are CHEAT,
including devgui, g_debugGore, g_showThinks and g_useSavegameDifficulty, which are not in
the catalogue. All 9 measured-accepted names in docs/limits.md are NOCHEAT. All 31 catalogue
names exist, and none is ROM or INIT.
Commands and binds, checked against commands.json:
god,noclip,notarget,giveandspawnexist neither as commands nor as cvars.devguiis a cvar.kill,teleport(an entity name, not coordinates),devmap,map,toggle,screenshot,killMonstersandrestartmapexist.- The bind
F3 noclipprinted "Unknown command". - The closest working substitute is
g_freeCam(CHEAT, "enable debug camera (free move)"). - The god-mode equivalent is
toggle g_permaGodMode 0 1.
Do the force-set values act? For all 22 catalogue CHEAT cvars plus g_freeCam and devgui, no
function that reads the cvar also reads the cheat global 0x1df21c8. This is a same-function
heuristic: callers were not checked. One exception: the read site of g_gameDifficulty
(0x853b12) lies outside any .pdata function and was not checked.
4. What changed
wolfsdk/cvars.py:tno_route(key)takes the routing fromdocs/cvars_tno.json(lazy, cached):plainsends+name value.cheatsends+name valueand then+toggle name value value. The early+argis kept for readers that run during startup, such ascom_skipIntroVideo.dropcovers names that are not cvars, plus ROM cvars.- The registered spelling is used. Without the file,
RETAIL_BLOCKEDdecides.
build_args(settings, binds, title_key=None)routes only whentitle_key == "tno".blocked_for("tno")now means "needs the +toggle route".TNO_BINDSandbinds_for(title): F3 becomestoggle g_freeCam 0 1. TNC keepsDEFAULT_BINDSunchanged.COMMANDSrewritten to commands that exist.- Catalogue corrections: g_fov range, pm_togglesprint default, g_gameDifficulty choices, g_EnableGore as a choice, g_goreBloodyMess as a float, pm_sprintMaxTime as an int, the missing defaults, and the com_allowConsole/g_permaGodMode/g_damageScale notes.
- Docstring updated. Dead
is_blocked()removed.
wolfsdk/gui.py: Start passesbinds_for(title)andtitle_key, and names the dropped names in the status line. The TNO row tag "✕ blocked in retail" is now "↻ cheat cvar - also sent as +toggle at start". The Info tab text is corrected (Ctrl+^, real commands, TNO binds).wolfsdk/cli.py:launch/playpassbinds_for(title)and the title. Thetweakstext and the--consolehelp are corrected.wolfsdk/mod.py: docstring sentence only.tools/build_release.py: shipsdocs/cvars_tno.json. Without it, the release would fall back toRETAIL_BLOCKED.- New:
docs/cvars_tno.json,tools/extract_cvars_tno.py,tools/verify_tno_tweaks.py.
5. Checks
python tools/extract_cvars_tno.py --self-check
3194 cvars (2865 CHEAT, 329 NOCHEAT, 8 ROM, 38 INIT, 169 ARCHIVE); 0 of 192 console commands collide
self-check: OK
python tools/verify_tno_tweaks.py -> 25 PASS, "all checks passed" (exit 0)
incl. "PASS TNC +args identical to the pre-change capture" (args captured before any edit)
mutation run (cheat->plain, old binds): 5 FAIL, so the checks can fail
python tools/verify_gui.py -> "Alles in Ordnung." (exit 0)
python tools/verify_loader_english.py -> "Alles in Ordnung." (exit 0)
python -m py_compile (cvars, gui, cli, mod, build_release, extract_cvars_tno, verify_tno_tweaks) -> OK
6. Open points (only the game can settle these)
- Nobody has run
+toggle name v vwith values in game. The code path is decompiled, and+toggle devguiwithout values is measured. Where the startup commands run (afterInit) is known only from that measurement, not from code. com_skipIntroVideo: the read before the reset is code-proven. That the 0x200 flag really skips the intro is not.- The maintainer's saved TNO tweaks change behaviour now.
g_goreBloodyMess 1now takes effect and halves the factor (default 2.0). Clear it, or use e.g. 4.com_allowConsole 1now takes effect, and per r7 it feeds the achievement check. Clear it.
- ARCHIVE cvars (
g_permaGodMode,g_fov,g_showHud, ...) are written to wolfConfig.cfg by the game. Unticking one in the loader sends nothing, so the last value sticks. Set it back to its default once instead. devguivia+toggleat startup is zeroed at the main menu by the DevGUI gate (r7 P2.5). It only works inside a level, through the console or a bind.devmenu.pystill listsnoclipandnotarget. It writesdebugmenu.txt, which has no consumer in TNO (r7 P2.5), so it was left alone.
7. In-game test for the maintainer (one launch)
- In the loader (The New Order): clear
g_goreBloodyMessandcom_allowConsole. Set Run speed = 600 and FOV = 95, leave the key bindings on, then press Start. - Did the intro logos play? Expected: no.
- Load a save and run. Expected: clearly faster than normal (600 vs 260). Press F3. Expected: a free camera. Press F3 again to return.
- Optional: Ctrl+^ should open the console. Type
toggle g_permaGodMode 0 1. - Quit and search
%USERPROFILE%\Saved Games\MachineGames\Wolfenstein The New Order\base\qconsole.logforpm_runspeed. Expected:Resetting cheat cvar: pm_runspeed, later followed bypm_runspeed = 600. There should be noCANNOT be set in retailand noUnknown commandfor F3.
If pm_runspeed = 600 appears but running is not faster, the reader is gated somewhere upstream
(see the heuristic in §3).
Related: Research Report: R7 Tno Cheat Gate, Research Report: R7 Tno Commands, Modding Limits, TNO CVar Catalog.