Development leftovers and embedded records
This survey follows strings to code or relocated records in the September 1994 TFX 2.05 executable. Addresses are file offsets unless labelled as data-object offsets. Function names are research annotations, not recovered source symbols. See the executable notes for the image layout and compiler evidence.
A developer joke in the terrain loader
“Jamie has bodged it again” is a real fatal diagnostic at file 0xf2410, rather than an unused joke string. The check at 0xb0358 subtracts the terrain-tag buffer's start pointer from its current cursor and rejects an extent greater than 16 KiB. Its callers append/read strings and 16-bit words in that buffer. Native checks at extents 0, 16,384 and 16,385 confirm the boundary and exact message; fatal termination is intercepted in the capture.
The original manual credits Jamie Cansdale with World Generator, Flight Model, making the name consistent with this subsystem. That connection does not establish who wrote every surrounding routine.
The same code retains two terrain-tag paths. 0xb0144 reads an ASCII source list containing a count, then a path and ten numeric authoring values per 73-byte runtime record. 0xb0604 can assemble tag names by enumerating *.sss, or consume a precompiled .dat tag buffer. Ordinary flight launch at 0x727f2 selects the latter through data-object 0xaad4. Both flight setup and UN Commander reach the world loader, so the alternative path should not be declared wholly unreachable without tracing the editor session. Here .asc means this terrain authoring list, not a presumed standard 3D-model interchange format.
Default high scores: names rather than secret passwords
The executable's table at 0xf7fbc contains ten 16-byte records: three string pointers and a 32-bit score. The initialiser copies them into ten 67-byte runtime records, each holding three 21-byte strings and the score at offset 63.
| First name | Surname | Callsign | Score |
|---|---|---|---|
| PAUL | HOLLYWOOD | ICE BUN | 100 |
| ANDY | BATE | B8C | 90 |
| DONNA | CHIPPENDALE | LURVE WARRIOR | 80 |
| LYNDA | WHITBY | ULTRA VIXEN | 70 |
| JIM | JENNETT | FUNKY | 60 |
| CHARLIE | CHUCK | 2 COOL | 50 |
| TIM | JOHNSON | BEER | 40 |
| ANDY | GAHAN | PURE | 30 |
| JAMIE | CANSDALE | THE LIZARD | 20 |
| N | PLURA | EVIL | 10 |
Several names match the original credits, including Tim Johnson, Andrew Gahan, Jamie Cansdale and Nevil Plura. The records themselves do not identify every person's role or relationship. Their traced consumer is the high-score initialiser, so these callsigns are not evidence of hidden enrolment passwords.
The loader at 0xa6aec reads tfx.hs under the directory selected by the DID environment variable. The disk payload is 670 encoded bytes followed by a 32-bit checksum. 0xa69b0 XORs each byte with the low byte of a reproducibly reset game random sequence; a second draw contributes to an additive checksum of the encoded bytes. 0xa6a10 reverses the encoding and calculates the same checksum. Missing files or checksum mismatches restore the embedded defaults. This is obfuscation and an integrity check, not strong protection. Native initialisation and encode/decode roundtrip checks pass without opening or writing a score file.
Retained interactive branch debugger
The presentation condition handler at 0xb22d8 contains an interactive diagnostic path. It draws the condition, its destination and the variable's current value, then waits for:
IF RANK == 7 THEN GOTO MISSION
SPACE - YES ENTER - NO
VARIABLE IS CURRENTLY 8
This is an example produced by the original native formatter from synthetic parser records in the capture, not a recovered campaign screen. Space takes the branch; Enter rejects it, independently of the condition's actual truth. A GOSUB branch also saves the return node on the graph's return stack.
Normal parser initialisation at 0xb2a68 calls 0x70d6c, a stub that returns AL = 1, and stores it in data-object byte 0xab41. For the ordinary equality condition tested here, that value sends execution directly to 0xb21cc, which compares the variable normally. The diagnostic path remains compiled in. Six native cases confirm normal true/false handling, forced yes/no handling, and GOSUB stack updates. Drawing is intercepted and the gate is changed only in emulated memory.
No keyboard shortcut or documented command-line switch enabling this debugger has been identified. It is evidence of retained development machinery, not a newly established gameplay cheat. The original manual credits David Dixon with Game Flow Editor, Instruments, Missions. A complete authoring editor cannot be inferred just from this runtime debugger: code described as “writing parser file” also serves pilot-save serialisation.
Personal names and animation fixes
Parser variable initialisation allocates 21-byte strings and initialises string-valued variables to DAVE; numeric variables start at zero. Game flow can replace those values subsequently. This is a default in working code, not a player-name check.
The generic animation initialiser also compares argument strings against DAVE_FADE, SLOW_FADE, MEDIA_BREAK_FIX and INTROGEN_FIX. These select palette/fade or presentation handling; they are internal arguments, not environment variables or newly recovered DOS configuration keys. The normal presentation-animation handler passes DAVE_FADE, as does another player at 0x7b2f4. These names show individual fixes surviving in the shared playback API. Associating “DAVE” with David Dixon is plausible given his credited work, but the string alone cannot prove it.
“Found an Ultra box!” resolved
This is a fatal sub-flow loading diagnostic, not an intentionally revealed player easter egg. The string at 0xf27b8 is referenced by 0xb388f, the type-14 entry in the sub-flow loader's switch table at 0xb3594. It calls the fatal error routine, which formats the message, records fatal state and exits. The sub-flow loader accepts ordinary return/quit/reset nodes but rejects type 14 before reading its payload. Four native synthetic loads confirm that distinction. “Box” here refers to a node in the graphical game-flow system, not a physical object in the world.
The top-level loader does support this node. 0xb3451 loads a 42-byte payload comprising three numeric conditions and pointers to up to three 17-byte choice-list records. The runtime handler tests conditions in priority order, then uses 0xb2620 to select a destination from the corresponding list. It records previously selected indices and avoids repeats until the entire list has been used, then resets that history. 0xb25e0 converts the selected index and list stride into a destination node. Native cases check first/second/third condition priority, no matching condition, and a complete four-choice cycle; the random-candidate routine is intercepted to exercise retry and sequential fallback reproducibly.
Thus “Ultra box” is an internal name for a compound conditional-choice node, with varied non-repeating branch selection. The meaning or origin of “Ultra” itself is not recovered. It could support variation in dialogue or presentation sequences, but that use is an inference from the mechanism. None of the nine decoded shipped parser graphs contains a type-14 node, so there is currently no concrete TFX scene that demonstrates it in ordinary play. The restriction against using it in a sub-flow is confirmed; whether this was a deliberate authoring constraint or an unfinished sub-flow implementation remains unknown.
The extractor previously labelled type 14 menu from its multi-buffer layout. Native execution shows that there is no menu input in this handler; the research label is corrected to ultra_choice. This does not alter any decoded shipped scene because those graphs contain no type-14 nodes.
Other data held in the executable
The executable supplies meaningful data beyond resources loaded from DID.DAT:
- Player aerodynamics and initial state: three different native initialisers write 95 captured floating-field locations for the Eurofighter, F-117 and F-22. The preset comparison retains values; the flight notes separate these from the external non-player entity profiles. Physical units and every field's meaning remain to be traced.
- Sample playback records: 26-byte descriptors supply original sample names, rates and cooldowns. These established the correct PCM interpretation for the sound exports; the sample bytes alone do not contain all those settings.
- Interpreter dispatch: embedded handler tables define model conversion/drawing, scenery events, part animation and presentation loading. These map opcode numbers to actual native functions and expose the boundary between authored data and engine behaviour in the code browser.
- Weapon labels and resource names: the string block around
0xef90c–0xefbf4pairs display labels such asAAAM,AA-ARM,CSWandAGM 109 Hwith model names. These are useful leads for matching weapon artwork and armament logic; their presence alone does not establish that a weapon was cut, playable, or implemented in every mode.
No additional secret mission, aircraft or gameplay easter egg is confirmed by this survey. WAYEDITOR belongs to a documented player-facing editor, and the video-recording strings belong to flight recording. The “Found an Ultra box!” diagnostic is now traced to the sub-flow restriction above; it provides no evidence of an “Ultra” difficulty or secret game mode. False positives are especially easy when a raw string scan includes padding around the actual referenced NUL-terminated strings.
Sine tables: the same one-unit asymmetry, at opposite peaks
TFX and Darker both use 1,024 signed sine samples per turn, with cosine taken a
quarter-turn further along the same cycle. Their samples follow
trunc(32767 × sin(2πi / 1024)), with one exception in each game:
| Game | Index | Angle | Stored value | Mathematical reference |
|---|---|---|---|---|
| Darker | 256 | 90° | +32766 | +32767 |
| TFX | 768 | 270° | −32766 | −32767 |
All other entries match that truncated formula. Comparing the complete recovered tables gives exactly two differing entries. Shifting Darker's table by half a turn and negating it reproduces all 1,024 TFX values, including the exceptional negative peak. This is a numerical relationship, not evidence of a particular shared implementation.
A published table or common generation routine circulating among developers is one possible explanation. Slight differences in floating-point sine generation, angle accumulation or conversion near an extremum could also produce a one-unit shortfall when a result just below an integer is truncated. The origin is unknown: no specific publication, shared source file or generation program has been identified. The matching pattern alone cannot distinguish those possibilities.
The anomaly is tiny: one integer unit is about 0.00305% of unit amplitude on the 32,767 scale. Native Q15 multiplication uses 32,768 as its divisor, so TFX's largest sample error against ideal unit sine is 2/32,768, or about 0.00610%, at 270°. The much more visible limitation at modern resolutions is the angular spacing: each table step is 0.3515625°. Near the centre of a 3,840-pixel-wide, 56° horizontal view, that is roughly a 22-pixel displacement.
The faithful reconstructions retain the respective exceptional samples. Redux's continuous display transforms evaluate sine and cosine without the original 1,024-phase rounding; simulation/reference arithmetic remains separately checked. See the Redux precision notes for the rendering changes and benchmarks.
Sources: Darker's exported table, Darker's findings, and TFX's reconstructed native table. This comparison uses those recovered tables and mathematical sine; it is not a new claim about the historical toolchain that generated them.
Evidence and reproduction
check_development.py executes the original routines in an isolated relocated LE image, with flat segment selectors. It checks all ten default records, their encode/decode roundtrip, six branch-handler cases, three terrain-buffer boundaries, four synthetic sub-flow loads and five Ultra-choice cases. development-checks.json retains the exact results and executable hash. Keyboard events, drawing, fatal termination and synthetic sub-flow I/O/allocation are intercepted; Ultra random candidates are fixed for the no-repeat checks; no installation or save file is changed. The terrain source path and animation argument uses above are static code traces, not claims that their complete authoring tools were executed.
python3 tools/check_development.py
The credit assignments come from page 98 of the original manual scan, rather than guesses based on names embedded in the executable.