Wolfenstein Modloader Buy me a coffeeKaffee spendieren

Wiki / Latest research roundsNeueste Forschungsrunden

TNO Console Commands: Registration, Flags, and What's Reachable Right Now

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

In plain wordsIn einfachen Worten

This report read the decrypted program code of Wolfenstein: The New Order (TNO) to list every registered console command. It found 192 real commands, including map, devmap, kill, teleport and screenshot, and showed that TNO's command registration has no place for cheat or lock flags at all, unlike Wolfenstein II. The well-known cheat names god, noclip, notarget, give and spawn are not commands; they only appear as button text in the hidden DevGUI menu, which corrects an earlier report. Everything here is static analysis; the suggested key-bind test with start arguments has not been run in the game.

  • 192 real commands were found by two independent methods: 147 from direct registration calls and 45 from a self-registering list, with no name overlap.
  • Registration takes only a name, a function, a description and auto-completion; there is no flags field, so there is no split into exposed and hidden commands as in Wolfenstein II.
  • 8 DevGUI rows (such as God Mode, No Clip, No Target and Give Grenades) point to commands that were never registered; this corrects round 6.
  • timescale is a setting (cvar) with default 1, not a command, and the real description of map is 'loads a combo map'.
  • Open: whether the console can be opened at all in retail (com_allowConsole); the +bind key test (F5 to F10) has not been run in game.

Dieser Bericht hat den entschlüsselten Programmcode von Wolfenstein: The New Order (TNO) gelesen, um jeden registrierten Konsolenbefehl aufzulisten. Er fand 192 echte Befehle, darunter map, devmap, kill, teleport und screenshot, und zeigte, dass die Befehlsregistrierung in TNO überhaupt keinen Platz für Cheat- oder Sperr-Flags hat, anders als in Wolfenstein II. Die bekannten Cheat-Namen god, noclip, notarget, give und spawn sind keine Befehle; sie stehen nur als Schaltflächentext im versteckten DevGUI-Menü, was einen früheren Bericht korrigiert. Alles hier ist statische Analyse; der vorgeschlagene Tastentest mit Startargumenten wurde im Spiel noch nicht ausgeführt.

  • 192 echte Befehle wurden mit zwei unabhängigen Methoden gefunden: 147 aus direkten Registrierungsaufrufen und 45 aus einer selbstregistrierenden Liste, ohne doppelte Namen.
  • Die Registrierung nimmt nur einen Namen, eine Funktion, eine Beschreibung und eine Autovervollständigung; ein Flag-Feld gibt es nicht, also auch keine Trennung in freigegebene und versteckte Befehle wie in Wolfenstein II.
  • 8 DevGUI-Zeilen (etwa God Mode, No Clip, No Target und Give Grenades) verweisen auf Befehle, die nie registriert wurden; das korrigiert Runde 6.
  • timescale ist eine Einstellung (Cvar) mit Standardwert 1, kein Befehl, und die echte Beschreibung von map lautet „loads a combo map“.
  • Offen: ob sich die Konsole in der Verkaufsversion überhaupt öffnen lässt (com_allowConsole); der Tastentest mit +bind (F5 bis F10) wurde im Spiel nicht ausgeführt.

Technical detailsTechnische Details

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

Round-7 research pass on The New Order's console commands, read from decompiled code: the registration call has no flags parameter at all, and every registered command was enumerated (from direct call sites plus a self-registering list Ghidra's xrefs missed). map, devmap, kill, teleport, setviewpos, screenshot and many more are real commands; god, noclip, notarget, give and spawn are not — they exist only as DevGUI label text, which corrects round 6. timescale is a cvar. Static only; the start-argument test at the end has not been run.

Track tnocommands. Builds on re_probes/agent_reports/r6_tnoconsole.md (TNO's restriction model, static-only: no runtime image existed yet, DevGUI table mined from raw .rdata string adjacency). This track has something r6 didn't: TNO now has a decrypted, live runtime capture (re_probes/runtime_tno_186352/module.bin, base 0x7ff74a390000, pid 186352, .text/.rdata/.data/.pdata all captured) and a Ghidra decompiler over it (tools/decomp.py ... --gzf D:/wolf-decomp/ghidra/tno_runtime.gzf). Everything below is either decompiled C read straight out of that capture, or bytes read directly from the capture's .data (which holds real, live pointer values from the process that was running when it was captured, not static-image placeholders) — not string adjacency. Read-only throughout: nothing was launched, nothing attached, no file was written outside re_probes/tnocommands/ and this report. New files: re_probes/tnocommands/mine_commands.py (the miner, reproducible, --self-check-free but every address it prints is independently re-derivable from the comments inline) and re_probes/tnocommands/commands.json (192 commands: name, flags, description, callback RVA, arg-completion RVA, source).

Question

Find TNO's command registration call (AddCommand-equivalent: name/callback/ flags/description), dump every registered command with its flags, and determine which of map/devmap/god/noclip/notarget/give/spawn/ kill/teleport/setviewpos/timescale/screenshot are usable from the retail console right now.

Answer (short)

idCmdSystem::AddCommand genuinely has no flags parameter in TNO — proven from decompiled code, not inferred from an absent string. The singleton is idCmdSystemLocal (RVA 0x15ba120, vtable RVA 0x104fa68, identity confirmed against docs/ghidra/rtti_tno.json, not just by convention). Its AddCommand (vtable slot +0x18, RVA 0x9edf30) takes exactly four arguments — (name, callback, description, argCompletion) — read directly out of its own decompiled body (§1) and confirmed again by independently reading every one of 192 distinct real call sites this track found (§2/§3): not one passes a fifth, integer "flags" argument; the slot is either 0 or an argCompletion function pointer. There is no CMD_EXPOSE/CMD_CHEAT/CMD_SHIPPINGDISABLED bit to find because the call simply has nowhere to put one — this closes out r6's inference ("no CMD_* enum found by string search") with the stronger claim the task asked for: the registration call itself has no such parameter, full stop.

map/devmap/cmap/checkmap/kill/teleport/setviewpos/getviewpos/ centerview/where/screenshot/rawscreenshot/envshot/toggle/bind/ unbind/reset/exec/vstr/listCmds/killMonsters and 172 more are all real, registered commands (full table in commands.json), and since there is no flags concept at all, there is no "exposed vs. non-exposed" split the way TNC has — once the console/dispatcher is reached at all (the still-open com_allowConsole question from r6 §2), any of these 192 should be callable by name with no further per-command gate.

god, noclip, notarget, give, spawn, killPlayer (bare), changeTeam, NoPlayerDeath are not in this table — this corrects r6, which called some of these "clean, wired Label→Action pairs." §4 shows exactly where those strings actually live: inside the DevGUI row-builder function, passed to a widget constructor that itself calls idCmdSystemLocal's lookup function (CommandExists, vtable +0x28, decompiled in §4) to validate the string before treating it as runnable — and that lookup walks the exact same linked list AddCommand populates (both read/write the same [this+8] head pointer, confirmed in each one's own decompiled body). Since these names are absent from that list under both of this track's independent enumeration methods (§2 direct-call-site scan, §3 self-registrar-list walk) and have no second code reference anywhere outside the DevGUI table (§4b), they would fail that very validation — they are DevGUI label text for commands that were apparently planned but never wired to a real AddCommand call in this retail build, not functioning commands with a cheat flag. timescale is real but is a cvar, not a command (§5) — timescale .1 works as <cvar> <value>, the same syntax DevGUI's own "Slow Time" row uses.

1. The registration call, read out of its own decompiled body

String search (direct bytes.find, not adjacency) locates "idCmdSystemLocal::AddCommand: %s already defined\n" at RVA 0x1053d20. tools/tnc_runtime_code.py's Image.xrefs() (a RIP-relative-lea byte scanner over the whole .text, independent of Ghidra) finds exactly one reference to it anywhere in the binary: RVA 0x9ee014, inside the function (0x9edf30, 0x9ee025). Decompiled (tools/decomp.py 0x9edf30):

void FUN_7ff74ad7df30(longlong param_1 /*this*/, undefined8 param_2 /*name*/,
                       longlong param_3 /*callback*/, undefined8 param_4 /*description*/,
                       undefined8 param_5 /*argCompletion*/)
{
  puVar1 = *(undefined8 **)(param_1 + 8);      // walk the command list head
  while (true) {
    if (puVar1 == 0) {                          // not found -> allocate + link new node
      ... puVar1 = Heap::Alloc(0x28);            // 5 x 8-byte fields = 40 bytes
      puVar1[1] = param_2;  puVar1[3] = param_5;  puVar1[2] = param_3;  puVar1[4] = param_4;
      *puVar1 = *(undefined8*)(param_1+8);        // node->next = old head
      *(undefined8**)(param_1+8) = puVar1;        // head = node
      return;
    }
    if (0 == func_0x7ff74ad559d0(param_2, puVar1[1])) break;  // name match (idStr::Cmp)
    puVar1 = (undefined8*)*puVar1;
  }
  if (param_3 == puVar1[2]) return;               // same callback already registered -> no-op
  FUN_7ff74ad5a710(s_idCmdSystemLocal__AddCommand___s_already_defined, param_2);  // warn
}

Node layout, read straight from the storage order above: {next, name, callback, argCompletion, description} — four data fields, not five. There is no slot for flags anywhere in this struct. This one function is called through vtable slot +0x18 on the idCmdSystemLocal singleton (global pointer at RVA 0x15ba108, which this capture shows pointing at 0x7ff74b94a120, RVA 0x15ba120 — a static object in .data, vtable RVA 0x104fa68). Cross-checked against docs/ghidra/rtti_tno.json (adjusting for its static image base 0x140000000 vs. this capture's runtime base): 0x14104fa68 → "idCmdSystemLocal" — an independent, RTTI-sourced confirmation this is the right object, not just the right-shaped one.

idCmdSystemLocal's lookup method (vtable +0x28, RVA 0x9edc20) walks the same [this+8] head:

undefined4 FUN_7ff74ad7dc20(longlong this, undefined8 text, char tokenize)
{
  puVar1 = *(undefined8**)(this + 8);
  while (puVar1) {
    if (tokenize == 0) { if (0 == idStr_Cmp(text, puVar1[1])) return 1; }     // exact match
    else               { if (-1 != idStr_Icmpn_or_similar(text, puVar1[1],0,0,0xffffffff)) return 1; } // prefix match
    puVar1 = (undefined8*)*puVar1;
  }
  return 0;
}

(idCVarSystemLocal's own equivalent, RVA 0x9dd630, is the same two-mode shape over its own hash table — confirmed by decompiling it too, not assumed by symmetry.)

2. 147 commands from 147 direct call sites across 12 functions

Image.xrefs()-independent, tools/decomp.py 0x9edf30 --xrefs lists every xref TO the registration function: 152 COMPUTED_CALLs across 12 distinct caller functions (Ghidra resolved these because the vtable pointer chain is concrete data in this live capture, not a relocation it has to guess). 11 of the 12 are large, flat Init()-style functions that just call AddCommand once per command in a row (e.g. FUN_7ff74abddb00, RVA 0x84db00, 67 calls — engine/AI/debug commands: kill, teleport (argCompletion 0x852d90, entity-name completion), setviewpos, getviewpos, centerview, where, killMonsters, killAI, healAI, testWeapon, DebugUnlockPerkByAbility, ...; FUN_7ff74a4c7950, RVA 0x137950, 45 calls — map/cmap/devmap/checkmap/slowmap (shared argCompletion 0x9ef070, a map-name completer), quit/exit, writeConfig, saveGame/loadGame, vid_restart, demorecord*, ...). The 12th caller is the one call inside a for loop over a second mechanism (§3) — Ghidra's computed-call analysis found it as one call site (correct: it's one instruction, executed N times at runtime), but resolving what it registers needs the linked-list walk below, not decompiled text.

re_probes/tnocommands/mine_commands.py parses every one of these direct call sites' decompiled C: resolves name/description by re-reading the full, untruncated string straight from module.bin at the VA Ghidra's own label encodes (Ghidra's auto-labels truncate — e.g. its label says exportDuplicateCollisionGeometry, the real, in-game name is exportDuplicateCollisionGeometryModel, recovered correctly by this script precisely because it never trusts the label text, only the VA suffix it contains), and takes callback/argCompletion RVAs directly from Ghidra's FUN_<va>/SUB_<va> naming (which already is the VA). 147 unique names resolved (151 individual call instructions minus 4 incidental name collisions); one call (the loop) correctly flagged UNRESOLVED by the script and handled separately.

3. +45 more from a self-registering linked list Ghidra's xrefs missed entirely

idCmdSystemLocal::Init itself (RVA 0x9efa70, found the same way as §1 — by locating the six always-present built-ins listCmds/exec/vstr/echo/ parse/wait via Image.xrefs() and decompiling their containing function) registers those six, then:

for (puVar3 = func_0x7ff74ad95fd0(); puVar3 != 0; puVar3 = *puVar3)
    AddCommand(this, puVar3[1], puVar3[2], puVar3[3], puVar3[4]);

func_0x7ff74ad95fd0 (RVA 0xa05fd0) is a one-line mov rax,[rip+disp]; ret reading a global at RVA 0x1f01640 — the head of a static, self-registering command list (same shape as TNC's own, see re_probes/agent_reports/ cmdtable.md §2: C++ global objects that link themselves into a list at load time; the matching node-constructor is at RVA 0xa05fe0). This is exactly the registration path the task brief warned about ("Ghidra's static xrefs are incomplete... find references yourself"): idCmdSystemLocal::AddCommand's own xrefs TO list (§2) does not include this loop's callees individually — only the one loop-call instruction — because the five arguments it passes come from runtime-walked heap data, not compile-time constants Ghidra's constant propagation can fold.

Walked directly from the capture (re_probes/tnocommands/mine_commands.py walk_registrar_list(), live pointer values, not guessed): head 0x1f01640 → 0x7ff74c294f20, 45 nodes, 0 cycles, terminates cleanly at null. This is where toggle ("toggles a cvar"), bind/unbind/unbindAll/ listBinds, reset ("resets a cvar to its default value"), cvar_restart, listCvars, connect/startServer, messagemode, print/clear/history/ con_watch/con_unwatch/activateConsole, idStudio ("design studio for the game"), makeDeclTree, three ps3_test* leftovers, and more come from — none of these were in §2's direct-call-site set, and all of them are commands TNC has too (per cmdtable.md), which is why their total absence from §2 alone would have been a red flag, not a clean result.

147 + 45 = 192 distinct commands, zero overlap in name between the two sources (re_probes/tnocommands/commands.json, full table with callback_rva/ arg_completion_rva/source per entry). flags is kept as a JSON field for parity with TNC's table shape and is null on every single entry — not a placeholder, a fact (§1).

4. Where god/noclip/notarget/give/spawn actually live

Direct string search in module.bin for god\0, noclip\0, notarget\0, give throwable/player/grenade, killPlayer %d: each exists exactly once in the whole 36 MB capture, all clustered at RVA 0x103a0a4–0x103b600 — the DevGUI label/action table region r6 already found by string adjacency. This track's addition: Image.xrefs() shows each of those five strings has exactly one code reference (a RIP-relative lea) anywhere in .text, and all five land inside the same function, FUN_7ff74ad1a100 (RVA 0x98a100) — the DevGUI page builder. Decompiled excerpt (full page-builder function is ~230 lines; this is the "God Mode" row, byte-identical pattern for every checkbox row on the page):

uVar10 = FUN_7ff74ad1fee0(&list);
uVar10 = FUN_7ff74ad200c0(uVar10, s_God_Mode);        // set row label "God Mode"
uVar10 = FUN_7ff74ad20380(uVar10, &DAT_..."god", bVar15); // set row's command text = "god"
FUN_7ff74ad20690(uVar10, uVar6);                       // set row's current-checked bool

FUN_7ff74ad20380 (RVA 0x990380) is the actual widget constructor, and this is where the lookup from §1 gets used:

longlong FUN_7ff74ad20380(longlong this, undefined8 commandText, char doCheck) {
  ... allocate a &vtbl_cellCmd_t node, store commandText in it ...
  if (doCheck != '\0') {
    bool ok = idCVarSystemLocal->Exists(commandText, 1);        // vtable+0x28 on DAT_..a110
    if (!ok) ok = idCmdSystemLocal->Exists(commandText, 1);      // vtable+0x28 on DAT_..a108 (§1)
    if (!ok) FUN_7ff74ad5a7b0(s_idGuiListBox__Command___Command___not_found, commandText);
  }
  ...
}

DAT_7ff74b94a110 and DAT_7ff74b94a108 are two adjacent globals; reading their live pointee vtables from the capture and matching against docs/ghidra/rtti_tno.json identifies them unambiguously: 0x14104fa68 → idCmdSystemLocal, 0x14104f968 → idCVarSystemLocal. So this widget validates its command text against both real systems, using the tokenize/prefix mode (doCheck's 3rd arg 1) — meaning a multi-word action like "toggle g_showHud 0 1" is checked by its first token (toggle, a real command, §3) and a bare word like "god" is checked as a whole — and "god" is in neither system's list (§2/§3 exhaustively enumerate both). Per-string verdict, all re-derived the same way:

DevGUI label action text first-token check target found in §2/§3?
God Mode god idCmdSystemLocal (cmd) no
No Clip noclip idCmdSystemLocal (cmd) no
No Target notarget idCmdSystemLocal (cmd) no
Give Grenades give throwable/player/grenade give (cmd) no
Spawn Imp spawn zion/ai/imp/demon_imp spawn (cmd) no
Suicide killPlayer %d killPlayer (cmd) no
No Player Death NoPlayerDeath NoPlayerDeath (cmd) no
Set Team Red/Blue changeTeam 1/2 changeTeam (cmd) no
Remove AI killMonsters killMonsters (cmd) yes (§2)
Show Hud toggle g_showHud 0 1 toggle (cmd) yes (§3)
Show Hands toggle hands_show toggle (cmd) yes (§3)
Slow Time timescale .1 timescale (cvar, §5) yes (cvar list)

This both confirms and corrects r6. r6 correctly found notarget/give.../ spawn.../killMonsters/NoPlayerDeath/changeTeam as DevGUI-row strings and called them (hedged, but still) "clean, wired Label→Action pairs." This track shows killMonsters is the only one of that list that is actually a real, reachable command; the rest are row text for a validation check (shown above, decompiled) that they would fail. Whether that check actually runs at runtime in retail (doCheck/bVar15, computed once per DevGUI page from *(char*)(pageObject+0x58), meaning untested — purpose of that one byte is not identified) doesn't change the practical answer: even if the check is skipped, clicking the row still has to eventually dispatch "god" through idCmdSystemLocal's executor, which — per §2/§3's exhaustive enumeration of every node that executor can find — doesn't have an entry for it either.

5. timescale is a cvar, not a command

Raw string search: timescale\0\0\01\0\0\0puts the game in slowmo\0 — name, then a bare numeric-literal token (1, the cvar's default), then the description, in that exact order. This is the standard cvar-registration string-adjacency shape (docs/cvars_tnc.json's own method, and r6 §4's for TNO) — a command's registration (§1/§2) never has a literal token between name and description, only a cvar's does. Consistent with swf_timescale existing right next to it (a second, UI-animation-speed cvar with the same naming pattern). Not in commands.json by design — it is a real, working cvar, just not a command, so timescale .1 at the console works as "set this cvar to .1", not as a command invocation with an argument.

PROVEN (this track — decompiled code and/or live .data values, not string adjacency)

  • idCmdSystemLocal singleton RVA 0x15ba120 (pointer at 0x15ba108), vtable RVA 0x104fa68, RTTI-confirmed (docs/ghidra/rtti_tno.json, 0x14104fa68 → "idCmdSystemLocal").
  • AddCommand (vtable +0x18, RVA 0x9edf30) takes exactly (name, callback, description, argCompletion) — no flags field exists in the node or the call, read from the function's own decompiled body, not inferred from a missing string.
  • CommandExists-equivalent (vtable +0x28, RVA 0x9edc20) walks the exact same [this+8] linked list AddCommand writes to, in two modes (exact / tokenize-prefix).
  • idCVarSystemLocal singleton identified the same RTTI-confirmed way (0x14104f968), its own +0x28 lookup (RVA 0x9dd630) decompiled and confirmed to be the same two-mode shape over its own hash table.
  • 192 distinct, real, registered commands recovered by two independent methods (147 via 12 direct AddCommand call-site functions, §2; 45 via walking the self-registering linked list at RVA 0x1f01640, §3) — re_probes/tnocommands/commands.json. Zero name overlap between the two sources.
  • god, noclip, notarget, give, spawn, killPlayer (bare), NoPlayerDeath, changeTeam are absent from both sources, and have zero code references anywhere outside the single DevGUI-table-builder function that stores them as display/validation text (Image.xrefs(), independent of Ghidra, one hit each).
  • timescale is a cvar (default 1, description "puts the game in slowmo"), not a command.
  • map's real description is "loads a combo map" (§2/commands.json) — corrects r6 §4's adjacency-mined guess ("shows collision model info", which r6 itself flagged as a likely-wrong neighbour grab).

INFERRED (plausible, not fully nailed down)

  • Whether the DevGUI's doCheck/bVar15 validation (§4) actually executes in the shipped retail build, or whether *(char*)(pageObject+0x58) is always the value that skips it — not identified; doesn't change the practical conclusion (§4, last paragraph) either way.
  • r6's standing conclusion that TNO's command dispatch is architecturally ungated (no per-command restriction level the way TNC has) is now proven at one more remove: not just "no flag enum found by string search" but "the registration call has no parameter for one." Whether the console itself (com_allowConsole) is reachable in retail remains exactly as open as r6 left it — this track is about the command table, not the console-open gate, and found nothing new on that front.

Failed hypotheses / dead ends (this track)

  • A second, flagged AddCommand overload for "cheat" commands (the TNC pattern, 0x200000-flagged God/InfiniteHealth/NoPlayerDeath/ Notarget, per cmdtable.md §6): searched for by checking every one of §2/§3's 192 call sites for an extra integer argument distinct from 0 or a function pointer — none found; also checked whether idCmdSystemLocal has a second vtable slot with an AddCommand-shaped signature (5 args) — vtable slots +0x18 (AddCommand) and +0x28 (Exists) are the only two this track needed and found; no evidence of a third. Concluded: this engine version genuinely predates that TNC-only mechanism, not just "didn't look hard enough" (same conclusion r6 reached from the negative string search, now from the call-site shape itself).
  • A naive full-.text linear capstone disassembly scanning for direct call 0xa05fe0 (the registrar-node constructor), to cross-check the linked-list walk's node count independently: 0 hits, almost certainly because linear disassembly of a 12 MB section desyncs after the first embedded-data byte run (jump tables, padding) — this is exactly why every other tool in this repo disassembles per-.pdata-function-range instead of linearly; dead end, abandoned in favor of the (already-working, cross-validated) linked-list walk.
  • Treating the DevGUI label/action table (r6 §4b) as itself a command registry: it isn't one — it is the consumer of idCmdSystemLocal's table (§4), one level downstream, which is exactly why 8 of its entries reference commands that were never actually registered.

Recipe

# find a command/cvar's registration site from scratch, same method as this track:
python3 - <<'EOF'
data = open("re_probes/runtime_tno_186352/module.bin","rb").read()
i = data.find(b"YOUR_NAME_HERE\x00")   # NUL-bounded, exact
print(hex(i))
EOF

PYTHONPATH=re_probes/python_deps python3 -c "
import sys; sys.path.insert(0,'tools')
from tnc_runtime_code import Image
im = Image('re_probes/runtime_tno_186352')
print(im.xrefs('YOUR_NAME_HERE'))"   # -> containing function's RVA range

python tools/decomp.py <that RVA> --gzf D:/wolf-decomp/ghidra/tno_runtime.gzf

# regenerate the full table (12 direct-call functions + the self-registrar walk):
python re_probes/tnocommands/mine_commands.py --text <decomp.py dump of all 12> \
    --out re_probes/tnocommands/commands.json

Open questions

  • Is com_allowConsole reachable in retail (r6's own open question — this track adds nothing new here, since it studied the command table, not the console-open gate).
  • What is *(char*)(devguiPage+0x58) ("doCheck"/bVar15 in §4) actually wired to — a build config, an edit-mode flag, something else? Static-only answer wasn't findable without walking that object's constructor(s), which this track judged not worth the budget given the practical conclusion doesn't depend on it.
  • Were god/noclip/notarget/give/spawn/etc. commands in an earlier build (pre-release, debug) that got stripped, leaving only their DevGUI label text behind? Plausible given the naming (DebugUnlockPerkByAbility etc. did survive) but unverifiable from one retail binary alone.

Smallest in-game test

(Translated from German.)

Without a mod, only start arguments:

WolfNewOrder_x64.exe +bind F5 god +bind F6 noclip +bind F7 notarget +bind F8 kill +bind F9 teleport +bind F10 "map test"

Start the game (console not needed — according to docs/limits.md/r6, +bind is processed even without console access), load a save, then press F5, F6, F7 in order and search qconsole.log (%USERPROFILE%\Saved Games\MachineGames\Wolfenstein The New Order\base\qconsole.log) afterwards:

  • If Unknown command 'god' or 'noclip'/ 'notarget' appears after F5/F6/F7 → confirms this report directly: these three are not real, callable commands in retail, regardless of whether the console is open or not (section 4 — they exist only as text in the DevGUI table, never as an AddCommand call).
  • F8 (kill) and F9 (teleport), by contrast, should go through without Unknown command (kill kills the player immediately, teleport without a target probably does nothing visible except producing no error message) — both are documented in re_probes/tnocommands/commands.json with a real callback RVA.
  • F10 (map test) should not show Unknown command, but either load or abort with a different, map-specific error message (map/devmap are registered, §2) — that is the difference from r6's so far unanswered question of whether the dispatcher is reached at all: an Unknown command 'map' line, on the other hand, would mean that even registered commands do not arrive via +bind, which would put this whole report into perspective (negative control for the central claim).

Back up saves first (as already recommended in r6) — unclear whether TNO marks saves when entering a cheat state.

Related: Research Report: R6 Tno Console, Research Report: Cmdtable, Research Report: R7 Tno Cheat Gate, Modding Limits, TNO CVar Catalog.