DARKER Research archive

The STAR THREE hidden command prompt

2026-09-18. Addresses below are offsets in the unpacked 64 KiB image, excluding the reconstructed EXE header. This report follows executable references; it does not decode the DARKER.00–.04 archives.

Activation and relation to save names

The four strings are commands, not displayed menu choices or ordinary save names. The recovered activation sequence is:

  1. On the “Select a game: 1,2,3,4 or N” screen, use Shift+8, release Shift, then press 3 on the number row. Playtesting found that numpad input did not work. The automated DOSBox/X11 capture accepted a synthetic keypad-multiply event, so that result is environment-specific and should not be treated as reliable player instructions.
  2. A separate input state uses the title “STAR THREE” and prompt “What do you want?”.
  3. Enter one of the exact phrases below and press Enter. Case, spaces, apostrophe and question mark matter. Re-enter *3 for another command.

Confirmed in the original packed executable running in DOSBox, using actual keyboard events: hidden prompt screenshot, typed command screenshot. After submitting Who gives true life?, a debugger memory dump confirms its patch is installed. All four phrases are additionally checked by executing their original machine code in an isolated Unicorn harness.

The hidden input and normal new-game name input share their editor at 05D3 and buffer at DS:01E0. They are distinguished by the menu-state byte at 4540: 4 means a normal new-game name; 5 means a hidden command. A control run entered Who gives true life? as a normal name: it was stored in the synthetic save slot, and the cheat handler was not called. Hidden-command tests did not modify the synthetic save-slot memory.

Corrected string boundaries

The string-table reader at 060D–0637 resolves the original ambiguity:

record := byte(text_length + 1), text[text_length], little_endian_handler_word
terminator := 01
Record Exact phrase Handler
04E1 The Jason Brooke special 0537
04FC Lyndon's little snooze 053E
0515 Who gives true life? 0543
052C Level X 0549

“Level XI” was an ASCII-string extraction artefact. The last record contains seven text bytes, Level X, then pointer bytes 49 05. Byte 49 also displays as I; it is not part of the phrase. The following 01 at 0536 terminates the table. Level XI is explicitly rejected by the actual matcher.

Reference and control-flow trace

These are instruction/table references checked against execution, rather than every occurrence of the same two bytes anywhere in the binary.

Address Role
0439, 0499 Menu drawing dispatch table; it includes the name/prompt renderer at 0645
0444–0449 Gets the current menu record and calls its handler at record offset +0A
07D5–07E0 Menu record = 0451 + 12 * byte[4540]
045B State 0 handler pointer: 0751, game selection
048B, 0497 State 4 and 5 handler pointers: both 05D3, text editor/submission
0751–078D Processes selection input and recognizes the secret preceding-key state
0747–074F Selects menu state 5 via 079F, then marks the input for redrawing
0645–0653 Alternate prompt renderer chooses SI=04BC for the hidden state
04BC–04E0 Formatting controls plus STAR THREE and What do you want?
05E3 Tests byte[4540] == 5; branches to hidden submission at 0608
060D Actual command-table reference: mov si,04E1
0615–0627 Exact byte comparison against ES:01E0, followed by zero-terminator check
0629–0637 Pushes matched handler address, copies accepted text, then RET dispatches to handler

The four individual text addresses do not need separate immediate references: the matcher walks records sequentially from 04E1.

Why the sequence is asterisk, then three

0800 obtains a character through the game's scan-code translation at 1534, then searches the selection keys N4321 at 0553. The reverse ordering means 3 produces result index 2. Unmatched input records character + 1 in the immediate operand at 0786 (0764–0768). No-key result FF wraps to zero and does not overwrite this remembered value, so idle frames are allowed.

When a recognized choice arrives, 0785 loads that remembered value into AH. At 078A the program compares AX with 2B02. Therefore:

AH = '*' (2A) + 1 = 2B
AL = selection index for '3' = 02
AX = 2B02 -> jump to 0747 -> hidden state 5

There is no elapsed-time test in this path. Another unrecognized printable character can overwrite the remembered character. The harness confirms *3 and * + idle polls + 3; it rejects 3, +3, *2, and *x3 as hidden-mode entry sequences. This explains the title “STAR THREE” directly.

Submission details

The editor accepts Enter through its control-character dispatch. State 5 submission returns to state 0 via 0608–060C, then scans the command table. The comparisons use REPE CMPSB, without case folding. The following byte of the input buffer must be zero, preventing prefix-plus-extra-text matches.

On a match, the text including its null terminator is copied to the address held at E3F4—initially the English game-selection prompt at E553. This is an in-memory UI text change, not a savegame-name write. PUSH AX at 0629 and RET at 0637 implement an indirect handler call through the stack.

What the handlers do

The Jason Brooke special

0537 writes word CA89 at 7F7B, replacing:

; Before
mul cx           ; F7 E1: DX:AX = AX * CX
; After
mov dx,cx        ; 89 CA

Playtest: infinite energy-boost recharges. The effect survived dying, loading other saved games, and entering additional commands during the same running session. This gives the arithmetic patch a concrete gameplay meaning.

The following shr dx,1 and xchg ax,dx remain. For the branch where DI > 250, the intermediate result changes from floor(((DI - 250) * CX) / 131072) to floor(CX / 2), before subsequent rounding/adjustment. The precise variable names and replenishment timing still need mapping; the infinite-recharge interpretation is based on the playtest rather than merely inferred from these instructions.

Lyndon's little snooze

053E shifts byte B949 right once: its initial 01 becomes 00. This changes mov ax,1 at B948 into mov ax,0, opening the handler at B938.

The gameplay dispatch table at B7FA maps scan code 2C (Z) to B938. Its reader at B793–B79F indexes by (scan_code - 1) * 2; the word is at B850. The code's own keyboard map at 15B7 confirms the character.

With the gate open, Z swaps the current object's callback at SS:[BP+66] between its previous value and B925 (a bare RET), and zeroes SS:[BP+3E]. The normal gameplay caller sets BP to D986. An isolated test confirms the first Z installs the no-op callback and the second restores the old callback.

Playtest: Z freezes the player ship in space. Enemy ships continue moving, and the player can still fire and use external views. This is a player-update freeze, not a global pause or an enemy-AI freeze. Debugging or screenshot use is plausible, but developer intent is not established. The exact phrase is Lyndon's little snooze; Jason's phrase enables the boost cheat.

Who gives true life?

0543 changes byte 84DE from 3C to B0:

; Before: cmp al,0 (leaves AL unchanged)
; After:  mov al,0

This zeroes an incoming quantity in the routine beginning at 84D0, after another helper has already run. One following path subtracts AL from byte 810A, saturating at zero; the patch prevents that decrement. An execution probe with the resource initially 100 and incoming AL=21 produces 79 normally, 100 with the command enabled. Call sites at 6EB0, 6EE2 and 8BD1 place this in collision/impact-related processing. Damage prevention is a strong interpretation; universal invulnerability, including all other death paths, has not been demonstrated.

The later Skimma trace identifies 810A as shield reserve in the non-Caero branch: depletion is applied while shields are enabled; with them off, a separate damage status is set. See flight controls. This is not a universal health/invulnerability flag.

Playtesting confirmed that scenery crashes are still lethal; enemy-hit immunity was not established because they did not manage to get hit during testing.

Level X

0549 changes byte B92A from 72 to B0:

; Before: jb B925  (72 F9), early return when a counter is below four
; After:  mov al,F9 (B0 F9), then fall through

The gameplay dispatch table maps scan code 2D (X) to this handler at B926 (table word at B852). It then copies word C610 to C81E and sets byte 3E9A to 1. The latter participates in the end-of-game/level transition path around 3EEB; C81E is also used by the game's script machinery. This supports a progression/level-completion shortcut, rather than a literal request for level ten. The harness verifies that X performs those writes with the counter at zero only after the command has been enabled. The exact destination depends on the current game's/script's values.

Playtest: X immediately advances to the cutscene leading into the next level. This resolves the earlier uncertain impression about enemy speed.

The gameplay key dispatcher has additional normal-play/script-state gates (B7AB–B7B6). The probes reproduce the normal-play value FF written at 3D3C; they do not imply the keys work during every cutscene or other state.

Entry while flying and persistence

No direct in-flight route to the *3 prompt has been identified. The proven entry is in game-selection handler 0751; flight input uses a different dispatch path (B780). The Z/X actions are intended to run later through that flight dispatcher, after their phrases have enabled them. Returning to game selection without restarting the process allows further commands.

These handlers patch executable memory, rather than fields of a single save record. Playtesting confirmed Jason's patch persists across deaths, loaded games and additional commands. Persistence across exiting/relaunching DOS is not claimed, nor has every patch's lifetime been exhaustively traced.

Reproduction and validation

python3 tools/unpack_exe.py
# Optional analysis dependency, install in a suitable virtual environment:
python3 -m pip install unicorn==2.1.4
python3 tools/trace_hidden_commands.py

The harness accepts only the known extracted-image hash. It executes the original x86 keyboard translation, selection, editor, matcher, handlers and gameplay key dispatch. Assertions cover:

The machine-code probes use synthetic empty save slots and eight-pixel font widths. They bypass mouse routines 1731, 173C and floppy housekeeping 4217, and feed the keyboard latch instead of emulating the physical IRQ. They do not emulate the full renderer, DOS, or a complete gameplay session. Results and substitutions are recorded in verification.json.

Independent graphical DOSBox confirmation

tools/capture_hidden_prompt.py launches a temporary copy of the original packed X.EXE, dismisses the startup screens, presses keypad * then 3, types Who gives true life?, and presses Enter. It captures the screens and then enters the heavy debugger with Alt+Pause to dump memory. The loaded image is located by its unchanged handler bytes, rather than assuming a fixed DOS load segment. The captured code at 84DE is B0 00, versus original 3C 00, and the menu state is back to zero. No code patch was injected by the capture tool; the game performed the write in response to the typed command.

The evidence is in ui/, including a compressed 1 MiB memory snapshot and provenance.json. This confirms the real activation and submission path, but is not a full gameplay test of invulnerability or the other commands' effects.

# Requires Xvfb, xdotool, ImageMagick import, pexpect, and dosbox-debug.
xvfb-run -a -s '-screen 0 800x600x24 -extension GLX' \
  python3 tools/capture_hidden_prompt.py --dosbox-debug /path/to/dosbox-debug

Disabling GLX avoids an Xvfb/NVIDIA EGL crash observed in this environment. The capture uses SDL's X11 video backend; the earlier SDL dummy-backend experiments had not reached a usable graphical session. The startup timing and Escape sequence are tailored to this installation and may need adjusting for a different emulator configuration.

No original game file was changed. The unpacked image remains the canonical unmodified extraction; patches occur in running memory. DOSBox mounts only the temporary installation copy.

Follow-up: player collision and damage now verifies the streetlight-specific crash mutation, controlled native geometric sweeps, and the exact limits of the player damage cheat. Earlier open questions on that response path are superseded by these tests.