# No Regret Game_Start Flow ## Scope This note documents the currently opened live `REGRET.EXE` startup lane around `Game_Start` and the later helper that performs the actual new-game mission hop. The immediate goals of this pass were: - name the directly involved startup helpers in Ghidra - annotate the startup-state globals that feed the new-game path - explain why No Regret appears to set the start map twice ## Named Functions The following previously-unnamed functions are now promoted in the live `REGRET.EXE` database. | Address | New name | Why the name is justified | |------|------|------| | `1058:0bbe` | `HandleCommandlineArgs` | Matches the already-recovered Remorse-side parser role. It compares argv entries against a startup-option table and writes `g_warpToLevelNoArg`, the difficulty override, map offset, egg override, and the extra startup-video flag. | | `1030:032d` | `Game_RunNewGameFlow` | This is the full No Regret new-game helper. It plays the ORIGIN/ANIM01 intro lane, opens the difficulty modal when not warping, rebuilds the world/avatar state, and then performs the actual mission-start teleporter hop or the debug `-warp` path. | | `1030:022e` | `Game_DrawCenteredStartupSplash` | Called immediately before the teleporter hop in both the normal and `-warp` startup lanes. It fades black, clears the active gameplay state, centers one startup screen object, and redraws the viewport. | | `11c8:0d96` | `Game_EnterFrontendMenuViewport` | Used before modal-gump dispatch. It clears the gameplay-style viewport flag, expands the mouse Y range to the taller menu height, and refreshes the screen object. | | `11c8:0d39` | `Game_RestoreGameplayViewport` | Used after the modal/front-end phase. It restores the gameplay-style viewport state, notifies NPC update lanes, restores the shorter mouse Y range, and refreshes the screen object again. | ## Game_Start Structure `Game_Start` in No Regret still looks like the top-level frontend entry point. High-level shape: 1. Freeze the current gameplay/process state enough to enter a frontend/modal lane. 2. Enter the taller frontend viewport mode and dispatch the startup modal gump. 3. Handle non-new-game modal results such as exit/other menu actions. 4. For the new-game path, clear world/gameplay state, rebuild the avatar and starter items, and do an early teleporter hop to map `1`, egg `0x1e`. 5. Fade/reset again and hand back into the wider startup framework. The key early selector is still: - `1008:1446 PUSH 0x1` - `1008:1448 PUSH 0x1e0001` - `1008:144e CALLF 0x1030:0000` That early site is real, but it is not the only startup teleporter call that matters. ## Actual New-Game Mission Start The function now named `Game_RunNewGameFlow` is the important second lane. It is called from at least two concrete places: - `CreditsProcess_Run` at `1008:0056` - another startup/control lane at `1058:0a2a` That already shows it is not dead duplicate code. It is a standalone startup helper reused by the frontend. Its normal no-warp branch does all of the following in one place: 1. Play the ORIGIN/ANIM01 intro-video lane. 2. Open the difficulty-selection modal. 3. Reinitialize NPC/world/tracker state. 4. Apply any command-line difficulty override. 5. Recreate starter inventory items. 6. Draw the centered startup splash. 7. Perform the actual mission-start teleporter hop. The effective mission-start selector is: - `1030:05c3 PUSH 0x1` - `1030:05c5 PUSH 0x1e0001` - `1030:05cb PUSH CS` - `1030:05cc CALL 0x1030:0000` This is the selector that redirected real new games only after the script was updated to patch it together with the earlier `Game_Start` site. ## Startup Globals These data roles are now annotated in the live Ghidra session. | Address | Current best role | |------|------| | `1480:1453` | Startup-world transition flag. `Game_Start` clears it before the early menu-start teleporter hop. `Game_RunNewGameFlow` sets it during world/NPC rebuild and clears it again immediately before the actual mission-start teleporter hop. | | `1480:0ac8` | Optional command-line warp X override. `0xffff` means no direct coordinate warp is requested. | | `1480:0aca` | Optional command-line warp Y override. | | `1480:0acc` | Optional command-line warp Z override. | | `1480:0ace` | Command-line difficulty override parsed by `HandleCommandlineArgs`. If greater than zero, the new-game flow copies it into `g_difficultyLevel` before the teleporter hop. | | `1480:0ad0` | Command-line `-mapoff` additive map offset used by the debug `-warp` path. | | `1480:0ad2` | Command-line egg override used by the `-warp` path. When negative or `0x001e`, the code falls back to the default startup egg. | | `1480:0ad4` | Extra startup-video behavior flag parsed by `HandleCommandlineArgs`. Clear means the ORIGIN/ANIM01 lane is played once; set means the same lane is repeated until `1480:95f0` becomes nonzero. | | `1480:95f0` | Startup-video loop exit latch used by `Game_RunNewGameFlow` and `CreditsProcess_Run`. | ## Command-Line Warp Controls The startup parser exposes more real gameplay-side command-line controls than just `-warp`. Currently proven from the recovered parser strings and control flow: - `-warp` - `-skill` - `-mapoff` - `-egg` - `-debug` - `-demo` - `-setver` - `-asylum` The same executables also contain the runtime status strings: - `Warping to mission %d.` - `Warping to mission %d @ x:%d y:%d z:%d.` - `Defaulting to skill level %d` - `Destination Egg = %d` That parser behavior is now tight enough to promote the actual syntax: - `-warp ` = mission-only manual warp - `-warp ` = direct coordinate warp The key parser detail is that there are no separately recovered `-x`, `-y`, or `-z` switches in this lane. After `HandleCommandlineArgs` parses the mission number, it checks the next argv token. If the next token is missing or begins with `-`, the parser takes the mission-only path and prints `Warping to mission %d.`. Otherwise it consumes the next three argv tokens as X, Y, and Z and prints `Warping to mission %d @ x:%d y:%d z:%d.`. There is one important precedence rule in `Game_RunNewGameFlow`: `-egg` wins over the coordinate override path. When X is present but the egg override is nonnegative, the code still routes back into the egg-based teleporter lane. The direct `NPC_Teleport` path only runs when X/Y/Z are present and the egg override is still negative. The live `REGRET.EXE` table backing that `-warp mission` branch is now closed directly too. In `Game_RunNewGameFlow`, the target map comes from: ```c mapno = *(int *)(g_warpToLevelNoArg * 2 + 0x75c) + DAT_1480_0ad0; ``` So the current retail No Regret mission-table base is `1480:075c`. Static bytes at that address: ```text 1480:075c: 00 00 01 00 03 00 05 00 07 00 09 00 0b 00 0d 00 1480:076c: 0f 00 11 00 13 00 15 00 17 00 19 00 1b 00 1d 00 1480:077c: 28 00 ``` Interpreted as little-endian words, the current recovered base-map table is: - `0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 40` That is the same 17-word sequence already recovered from No Remorse at `1478:0488`, so the two games currently match on the embedded mission-to-base-map table even though the surrounding startup control flow differs. ## Could Parameters Replace The Executable Hack? For a normal fresh game, no. The executable patch was needed because the stock new-game path still hardcodes the startup selector payload `(map = 1, egg = 0x1e)` in code. No Regret does that twice, once in `Game_Start` and once again in `Game_RunNewGameFlow`. The command-line warp lane is different: - it only runs when `g_warpToLevelNoArg != -1` - it uses a debug/manual warp flow rather than the ordinary fresh-game path - it computes the target map from an embedded mission-to-map table plus `-mapoff` - it can also change the destination egg - it can apply explicit X/Y/Z destination overrides through `-warp ` So a command line could likely have reproduced the practical destination change for a manual debug warp session, but not the ordinary fresh-game mission-1 behavior that the patch script changed. For maps with no usable teleport egg, the parameter-only workaround is now clearer too: use `-warp ` together with `-mapoff`, and do not pass `-egg`. That path bypasses the egg lookup and calls `NPC_Teleport` directly. The current inspected teleport lane does not show any automatic `snap-to-ground` rescue, so this only works if the supplied coordinate triple is already valid for the target map. Current best distinction: - executable patch = changes the stock fresh-game startup behavior - command-line warp args = invoke a separate manual/debug startup path that can land on a different mission/map/egg and likely a different coordinate triple ## Likely Reason Map 1 Is Set Twice The most likely explanation is that No Regret preserved two valid entry paths into an in-engine gameplay state instead of refactoring them into one shared startup selector. Evidence for that read: - `Game_Start` contains an early teleporter hop immediately after rebuilding the avatar and starter items. - `Game_RunNewGameFlow` is a separate, live helper called from `CreditsProcess_Run` and another startup/control lane. - `Game_RunNewGameFlow` owns the full intro-video, difficulty-modal, world-reset, and real mission-start sequence. - Both paths call the same local teleporter wrapper with the same literal `(1, 0x1e, 1)` payload. Current best model: - the early `Game_Start` hop is a frontend/bootstrap entry into a playable engine state - the later `Game_RunNewGameFlow` hop is the authoritative mission-start step for a real new game after the intro/difficulty flow - both kept their own literal selector instead of sharing one startup-map global or helper constant So the duplication looks more like split control-flow ownership and startup code reuse than a deliberate “set it twice just in case” pattern. ## Practical Patch Implication For No Regret, changing the fresh-game destination map must update both hardcoded selectors: - early `Game_Start` selector at `1008:1448` - actual mission-start selector at `1030:05c5` Patching only the early site is insufficient because the later new-game helper can silently overwrite that choice during the real mission-start sequence.