Wolfenstein Modloader Buy me a coffeeKaffee spendieren

Wiki / Latest research roundsNeueste Forschungsrunden

TNO Cvar Registry, Loader Audit, and Delivery Fix

Partly solvedTeilweise gelöst Original page in the GitHub wikiOriginalseite im GitHub-Wiki

In plain wordsIn einfachen Worten

This report walked the full list of console settings (cvars) in the decrypted program code of Wolfenstein: The New Order (TNO): 3,194 of them, 2,865 marked as cheat. It also traced the startup order and found that the game wipes cheat settings after reading the start arguments, so many of the project loader's tweaks, like run speed or gravity, never took effect. The loader now also sends cheat settings as +toggle name value value, which runs after that reset. The list and the loader checks are proven by code and offline tests, and +g_showHud 0 and +toggle devgui were measured in the game earlier, but the new +toggle route has not been run in game yet.

  • 3,194 cvars: 2,865 CHEAT and 329 NOCHEAT, 8 ROM, 38 INIT, 169 ARCHIVE; none of the 192 console commands is also a cvar.
  • Start arguments are applied before and again after the config files, so a +name value beats the user's wolfConfig.cfg; after that the cheat reset wipes cheat values.
  • Cheat cvars set by the loader (such as g_infiniteAmmo, g_gravity, pm_runspeed) were wiped and are now also sent as +toggle; g_permaGodMode is not a cheat cvar and always worked, which corrects round 7.
  • god, noclip, notarget, give and spawn are neither commands nor cvars; F3 now toggles the free camera g_freeCam, and the god-mode equivalent is toggle g_permaGodMode 0 1.
  • Open: nobody has run +toggle name value value in game yet, and it is unproven that the intro video is really skipped; a one-launch test is described.

Dieser Bericht hat die vollständige Liste der Konsoleneinstellungen (Cvars) im entschlüsselten Programmcode von Wolfenstein: The New Order (TNO) durchlaufen: 3.194 Stück, davon 2.865 als Cheat markiert. Er hat außerdem die Startreihenfolge verfolgt und festgestellt, dass das Spiel Cheat-Einstellungen nach dem Einlesen der Startargumente zurücksetzt, sodass viele Tweaks des Projekt-Loaders, etwa Laufgeschwindigkeit oder Schwerkraft, nie wirkten. Der Loader schickt Cheat-Einstellungen jetzt zusätzlich als +toggle name value value, was nach diesem Zurücksetzen läuft. Die Liste und die Loader-Prüfungen sind durch Code und Offline-Tests belegt, und +g_showHud 0 sowie +toggle devgui wurden früher im Spiel gemessen, aber der neue +toggle-Weg wurde im Spiel noch nicht ausprobiert.

  • 3.194 Cvars: 2.865 CHEAT und 329 NOCHEAT, 8 ROM, 38 INIT, 169 ARCHIVE; keiner der 192 Konsolenbefehle ist zugleich eine Cvar.
  • Startargumente werden vor und noch einmal nach den Konfigurationsdateien angewendet, daher schlägt ein +name value die wolfConfig.cfg des Nutzers; danach löscht der Cheat-Reset die Cheat-Werte.
  • Vom Loader gesetzte Cheat-Cvars (etwa g_infiniteAmmo, g_gravity, pm_runspeed) wurden gelöscht und werden jetzt zusätzlich als +toggle geschickt; g_permaGodMode ist keine Cheat-Cvar und hat immer funktioniert, was Runde 7 korrigiert.
  • god, noclip, notarget, give und spawn sind weder Befehle noch Cvars; F3 schaltet jetzt die freie Kamera g_freeCam um, und das Gegenstück zum Gottmodus ist toggle g_permaGodMode 0 1.
  • Offen: +toggle name value value hat noch niemand im Spiel ausgeführt, und dass das Intro-Video wirklich übersprungen wird, ist unbewiesen; ein Test mit einem einzigen Spielstart ist beschrieben.

Technical detailsTechnische Details

Der technische Teil ist auf Englisch – so, wie er im Wiki steht. Unterstrichene Begriffe haben eine Erklärung auf Deutsch.

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.

  1. 0x13365c: FUN_130b70(args, 1) runs over every +name value pair. For each name that is a cvar, it calls Set(cvar, value, force=1) (0x9dd3f0 -> 0x9dd2d0), INIT cvars included.
  2. 0x1337ad: com_skipIntroVideo is read here (cmp [0x161e248],0, the flag goes to the intro start).
  3. build.cfg, then FUN_130b70 again (0x13397b). Then exec default.cfg (4 devices), wolfConfig.cfg (gated lines), and an inline third pass of +cvar pairs that skips INIT cvars and force-sets the rest (0x133d99). So a +name value beats the user's wolfConfig.cfg.
  4. 0x133e22: ResetFlaggedVariables(CHEAT), the cheat reset.
  5. After Init: the startup commands (+toggle, +bind). Measured: +toggle devgui survives 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 v always ends at v: on a match it takes argv[3], otherwise it wraps to argv[2]. It logs name = 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, give and spawn exist neither as commands nor as cvars.
  • devgui is a cvar.
  • kill, teleport (an entity name, not coordinates), devmap, map, toggle, screenshot, killMonsters and restartmap exist.
  • The bind F3 noclip printed "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 from docs/cvars_tno.json (lazy, cached):
      • plain sends +name value.
      • cheat sends +name value and then +toggle name value value. The early +arg is kept for readers that run during startup, such as com_skipIntroVideo.
      • drop covers names that are not cvars, plus ROM cvars.
      • The registered spelling is used. Without the file, RETAIL_BLOCKED decides.
    • build_args(settings, binds, title_key=None) routes only when title_key == "tno".
    • blocked_for("tno") now means "needs the +toggle route".
    • TNO_BINDS and binds_for(title): F3 becomes toggle g_freeCam 0 1. TNC keeps DEFAULT_BINDS unchanged.
    • COMMANDS rewritten 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 passes binds_for(title) and title_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/play pass binds_for(title) and the title. The tweaks text and the --console help are corrected.
  • wolfsdk/mod.py: docstring sentence only.
  • tools/build_release.py: ships docs/cvars_tno.json. Without it, the release would fall back to RETAIL_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 v with values in game. The code path is decompiled, and +toggle devgui without values is measured. Where the startup commands run (after Init) 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 1 now takes effect and halves the factor (default 2.0). Clear it, or use e.g. 4.
    • com_allowConsole 1 now 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.
  • devgui via +toggle at 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.py still lists noclip and notarget. It writes debugmenu.txt, which has no consumer in TNO (r7 P2.5), so it was left alone.

7. In-game test for the maintainer (one launch)

  1. In the loader (The New Order): clear g_goreBloodyMess and com_allowConsole. Set Run speed = 600 and FOV = 95, leave the key bindings on, then press Start.
  2. Did the intro logos play? Expected: no.
  3. Load a save and run. Expected: clearly faster than normal (600 vs 260). Press F3. Expected: a free camera. Press F3 again to return.
  4. Optional: Ctrl+^ should open the console. Type toggle g_permaGodMode 0 1.
  5. Quit and search %USERPROFILE%\Saved Games\MachineGames\Wolfenstein The New Order\base\qconsole.log for pm_runspeed. Expected: Resetting cheat cvar: pm_runspeed, later followed by pm_runspeed = 600. There should be no CANNOT be set in retail and no Unknown command for 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.