16 KiB
Crusader Command-Line Parameters
Scope
This note consolidates the currently recovered startup/debug argument set across the retail Crusader executables.
The current strongest parser/control-flow evidence now comes from both live targets:
REGRET.EXECRUSADER.EXE
Two conclusions matter most for the recent startup-map work:
- the executable patch was still required to change the stock fresh-game start map
- the built-in manual/debug warp lane is real, and its direct-coordinate form is
-warp <mission> [x y z]
That direct-coordinate syntax is now confirmed in both retail games, not just Regret.
Short Answer
If the question is could the normal first-mission executable hack have been replaced by parameters all along?, the answer is still no.
The stock new-game path hardcodes map 1, egg 0x1e in code. The parameterized warp path is a separate startup/debug branch that only runs when -warp is present.
If the question is can the executable already warp into another map without patching files?, the answer is yes.
The current best-proven forms are:
-warp <mission>-warp <mission> <x> <y> <z>- optional
-mapoff <delta>and-egg <id>modifiers
The important restriction is that -egg beats X/Y/Z. If you supply a nonnegative egg override, the game routes through the teleporter-egg path and does not use the direct-coordinate teleport.
That precedence rule is also now confirmed in both retail games:
REGRET.EXEroutes throughGame_RunNewGameFlowCRUSADER.EXEroutes throughGame_Start
For the specific -u question, the current live No Remorse answer is now yes.
The regular non-Japanese CRUSADER.EXE still contains a real -u lane, and the current best read is no longer unresolved leftover token. In this build it is a live startup override for the usecode/EUSECODE load source.
Parameter Table
| Argument | Current best syntax | Confidence | Current best effect |
|---|---|---|---|
-? |
-? |
Medium | Help/usage-style startup path. The option is present in the parser table, and the nearby startup strings include You DO need help!. The exact REGRET-side case-to-string tie was not re-closed in this pass. |
-u |
-u <arg> |
High | Live in retail CRUSADER.EXE. The parser copies the following token into 1478:065a, and startup_apply_u_override_if_present later uses that buffer as a startup usecode/EUSECODE load-source override. The JP build matches the same interpretation. |
-debug |
-debug |
High | Live parser branch. Raises the debug-print threshold, prints Debugging mode ON., and enables the known movie-player timing overlay / debug-print lane. |
-setver |
-setver <text> |
Medium | Still present in the broader Crusader parser-family tables, but the earlier CRUSADER-side assignment of the string-copy branch now belongs to -u. Treat the exact retail CRUSADER.EXE -setver behavior as still unresolved here; the older version/banner read is now best treated as REGRET-weighted rather than closed for both games. |
-asylum |
-asylum |
High | Joke/no-op style switch. Current best recovered effect is printing Enabling ENHANCED mode. (NOT!) with no stronger gameplay-side state change recovered in this pass. |
-warp |
-warp <mission> |
High | Enables the manual/debug warp lane by setting g_warpToLevelNoArg. The runtime then computes target_map = mission_table[mission] + mapoff. |
-warp with coordinates |
-warp <mission> <x> <y> <z> |
High | Direct coordinate warp. After parsing the mission number, the parser checks the next argv token. If it is present and does not begin with -, the next three argv tokens are parsed as X, Y, and Z. |
-skill |
-skill <n> |
High | Parses a difficulty override into 1480:0ace. The parser clamps 0 up to 1, then Game_RunNewGameFlow copies the value into the difficulty level before the mission-start hop. |
-mapoff |
-mapoff <delta> |
High | Adds an offset to the mission-table result inside the manual/debug warp path. It does not affect the stock fresh-game selector when -warp is absent. |
-egg |
-egg <id> |
High | Sets the destination egg override used by the warp path. When the value is nonnegative, it takes precedence over the direct-coordinate teleport branch. |
-demo |
-demo |
High | Sets 1480:0ad4, prints Demo mode., and changes the ORIGIN/ANIM01 startup-video behavior in Game_RunNewGameFlow. |
-laurie |
-laurie |
High | Separate from the main HandleCommandlineArgs switch table. This is the broader cheat/debug-enablement argument already documented in the live No Remorse notes. |
Warp Syntax And Precedence
The current best evidence-backed parser behavior is now confirmed in both REGRET.EXE and CRUSADER.EXE.
In the No Remorse live database, the exact matching parser case is HandleCommandlineArgs at 1048:0adc, and the matching consumer branch is in Game_Start at 1020:029e / 1020:02d0.
In the Regret live database, the matching parser case is HandleCommandlineArgs at 1058:0cd2, and the matching consumer branch is in Game_RunNewGameFlow at 1030:0628 / 1030:069a.
The shared behavior is:
-warpalways consumes one numeric mission argument.- The parser then peeks at the next argv token.
- If that token is missing or begins with
-, the game takes the mission-only path and printsWarping to mission %d.. - Otherwise the parser consumes the next three argv tokens as X, Y, and Z, stores them in
1480:0ac8,1480:0aca, and1480:0acc, and printsWarping to mission %d @ x:%d y:%d z:%d..
For No Remorse the corresponding X/Y/Z globals are the earlier siblings:
1478:084c= X override1478:084e= Y override1478:0850= Z override
That means the recovered syntax is positional:
-warp <mission>-warp <mission> <x> <y> <z>
This pass did not recover any separate literal -x, -y, or -z switches in the startup parser.
At runtime, both games apply the same precedence:
- Compute the target map from the embedded mission-to-map table plus
-mapoff. - If X is unset (
0xffff/-1), use the egg teleporter path. - If X is set but
-eggis also nonnegative, still use the egg teleporter path. - Only when X/Y/Z are present and the egg override is still negative does the game bypass egg lookup and call
NPC_Teleportdirectly.
No Remorse’s direct consumer branch is especially clear:
1020:029echecks whether X is still-11020:02a5/1020:02d0check whether-eggis nonnegative1020:02d7..02ebcallNPC_Teleportonly when X/Y/Z are present and egg override is still negative
Eggless Maps And The Non-Patching Workaround
This directly answers the recent map-254 style question.
There is a parameter-only route into maps with no usable destination egg, but it is not -egg.
The working shape is:
-warp <mission> <x> <y> <z> -mapoff <delta>
with -egg omitted.
Why that matters:
-eggkeeps the code on the teleporter/egg path- the direct-coordinate form falls into
NPC_Teleport - the inspected
NPC_Teleportlane writes the exact map/X/Y/Z values and moves the camera there - the currently inspected teleport path does not show any automatic
snap-to-groundorfind a safe spawnrescue
So the non-patching workaround for an eggless map is known-good coordinates, not some hidden eggless-map flag.
If the supplied X/Y/Z values are bad, the game can still strand the avatar in empty space even though the warp itself succeeded.
What -u Does In Retail CRUSADER.EXE
The live non-Japanese No Remorse database now closes -u much more tightly than the older note.
In HandleCommandlineArgs, the retail parser case at 1048:0a46 consumes the next argv token and copies it into the fixed startup buffer at 1478:065a.
The only recovered consumer of that buffer in the same retail executable is startup_apply_u_override_if_present at 1420:0cdf.
Recovered behavior in that helper:
- check whether
1478:065ais non-empty - if empty, leave the default startup path alone and return
- if non-empty, route startup through an alternate load/resolve path using the copied string
- store the resulting far pointer in
1478:6611/6613 - set the loaded-state byte at
1478:6615 - rebuild the cumulative slot-base words at
1478:8c7c..8c82
That is strong retail No Remorse evidence for this meaning:
-u <arg>is a live startup override for the usecode/EUSECODE load source.
What is still not fully closed from this static pass is the exact Filespec path syntax for the copied token.
What is now materially tighter:
- the helper does not treat the argv token as the final archive filename
- it uses the token as the
pathcomponent toFilespec_GetFullPath - it uses the mutable filename template at
1478:07a0, which iseusecode.flx, as the fixedfilenamecomponent - it forces that template's first byte to
'e'before the existence probe and final load call - the path builder uses DOS-style backslashes via the literal
"\\"string fromFILE\\FILESPEC.C - the existence probe goes through the DOS file-search path in
File_Exists, so the override must resolve inside the game's DOS-visible filesystem - the parser copies the token into the
0x1e-byte buffer at1478:065a, so the practical maximum is29visible characters plus the terminator
So the safest current retail read is:
-u <arg>expects a directory/resource-root style path argument for the standardeusecode.flxarchive family- it does not currently look like a free-form arbitrary filename override
- the safest token spelling uses DOS-style backslashes, not forward slashes
That gives a direct explanation for failed attempts like:
-u USECODE/FLICTEST.FLX-u FLICTEST.FLX-u C:\MADDOCODEwhen that path only exists on the Windows host and not inside the guest DOS drive mapping
Those forms fit the recovered helper badly because the token is used as the Filespec_GetFullPath path component while the filename remains the fixed template eusecode.flx. Current safest interpretation is therefore:
- pass a directory or resource-root to
-u - put the replacement archive at
<that root>/EUSECODE.FLX - do not expect
-uto openFLICTEST.FLXdirectly as the final archive name
The current safest syntax examples are:
-u MADDOCODE-u .\MADDOCODE-u \MADDOCODE-u C:\MADDOCODE
But for real DOS-facing installs, the safer practical examples are the 8.3-safe variants:
-u MADDOC~1-u .\MADDOC~1
with these current best path interpretations:
MADDOCODE= relative to the game's current DOS working directory.\MADDOCODE= explicit relative DOS path\MADDOCODE= root-relative path on the current DOS driveC:\MADDOCODE= absolute DOS path on driveC:as seen by the DOS game, not automatically the Windows host path
In the current GOG install used for this investigation, Windows reports the short alias:
MADDOCODE->MADDOC~1
That makes MADDOC~1 the highest-probability next token for this specific setup.
Current safest negative guidance:
- avoid forward slashes for
-u - avoid long path tokens because silent truncation at
1478:065acan change the real lookup target - do not use the archive filename itself as the
-uargument - prefer
8.3-safe directory names or explicit DOS short aliases when testing under DOSBox-like environments
But the important uncertainty is now only exact naming rules, not whether the switch is real. In the regular non-Japanese CRUSADER.EXE, the switch is clearly still live.
Expected Console Output For -u
Current best answer: probably none.
The recovered -u parser case does not print a banner, and the startup helper that probes and swaps the override path also has no recovered ConsolePrintf call. So unlike -debug, -warp, -skill, -mapoff, -egg, or -demo, -u does not currently appear to advertise itself on the console before the game loads.
The safest current expectation is:
- success: no dedicated
-uconsole message - missing path/file: no dedicated
-uconsole message, likely silent fallback to stock usecode - malformed but existing replacement: no dedicated
-ustatus line from the parser/helper path; later behavior depends on the deeper loader/runtime path
This also sharpens the practical diagnosis for the current MADDOCODE setup. In the tested GOG install, only EUSECODE.FLX differs between USECODE and MADDOCODE; the sidecar files are byte-identical. So if replacing USECODE\EUSECODE.FLX with the hacked file produces the expected obvious no-usecode-style breakage, but -u MADDOCODE behaves like stock gameplay instead, the strongest current read is that the override path was probably not accepted and startup silently fell back to the stock usecode root.
This also aligns with the already-stronger JP Win32 result, where the matching -u lane was recovered as the same kind of usecode override.
For the deeper runtime-side investigation of whether -u replaces or augments the stock usecode root, and what game systems that replacement feeds, see docs/usecode-startup-override.md.
Current best answer from that follow-up is:
-ubehaves like a replacement of the live usecode runtime root, not an additive overlay- the replaced root is then used by normal item-event dispatch, usecode process creation, interpreter bytecode stepping, and gameplay-side scripted capability checks
The current best replacement-vs-addition answer is also now stronger:
- there is one live root at
1478:6611/6613 startup_apply_u_override_if_presentoverwrites that root directly when-uis present- later event/process/interpreter consumers read the replacement root through the same global pair
So the safest current retail read is full runtime root replacement for the session, not load one extra add-on script beside stock usecode.
What -setver Most Likely Does
-setver should now be treated more cautiously in this consolidated note.
For retail CRUSADER.EXE, the string-copy branch that had previously been grouped under -setver is now better closed as the live -u handler described above.
That means the older displayed version/build string override reading is no longer closed for the non-Japanese No Remorse executable itself.
Current evidence bundle:
- the option name is still present in the broader Crusader parser-family tables
- older REGRET-side evidence still points toward a startup/UI presentation role rather than gameplay control
- but this pass did not directly re-close the exact retail No Remorse
-setverconsumer after reassigning the resolved string-copy branch to-u
Current best read:
-setver <text>still looks more like a presentation/version banner switch than a gameplay/startup-map selector- but that statement is now provisional for consolidated retail notes until the retail
CRUSADER.EXEhandler is isolated directly
The exact retail No Remorse -setver branch is therefore an open cleanup item again, while -u is now the closed string-consuming retail startup override.
No Remorse Cross-Check Summary
The main recent uncertainty was whether Regret had gained an extra direct-coordinate warp feature that No Remorse lacked. The live CRUSADER.EXE pass now closes that question.
Current best answer:
- No Remorse supports the same positional
-warp <mission> [x y z]syntax. - No Remorse uses the same
-eggprecedence rule over X/Y/Z. - No Remorse reaches the same direct
NPC_Teleportstyle fallback when coordinates are present and the egg override is still negative.
So the parameter-only workaround for eggless maps is not Regret-specific. The same approach should work in No Remorse too, as long as the supplied coordinates are valid for the chosen target map.