DARKER Research archive

Flight controls: executable versus manual

2026-09-18. Canonical unpacked image offsets. Compared with the supplied manual, printed English pages 17–19 and 22 (PDF pages 10, 11 and 13).

The event dispatcher at B780–B7B6 indexes an 83-entry table at B7FA with (scan - 1) * 2. 32 entries have a nontrivial handler. Continuous controls also read the key bitmap at 15A7; they need not appear in this table. The following covers these flight input paths, not every menu or configuration screen. Availability depends on craft, equipment, mission and cutscene state.

Main controls and manual coverage

Key Flight action Code evidence Manual coverage
Left / right arrows Bank left / right Held-key steering, 7AD6 onward p.17.
Up / down arrows Nose down / up Same p.17.
Ctrl + arrows Increase control force Modifier read from 15AA; manual p.17 p.17.
Opposing arrows together Reduce force in first direction Manual p.17; steering consumes both bits p.17.
A Toggle automatic altitude adjustment, Caero fighter B97A, flag 7ED2 p.17.
E Engine toggle; craft-dependent behavior B8CE, flag 4552 p.17: Caero explicit; other-craft function only hinted.
Enter Boost; craft-dependent behavior B956; energy deduction and message p.17: Caero explicit; other-craft function only hinted.
Number-row − / = (manual says − / +) Other-craft speed settings B913/B918, values 248/500 to 7F20, gated by craft p.17: keys hinted; speed settings unspecified.
Backspace Brake Input mask at 7F59, used 7F55, 7FE0, 81D4 p.17.
Caps Lock Clear/reacquire target lock 797B calls CFCB p.17.
Space Primary fire Held-action mask; configurable p.19.
Alt Secondary fire Held-action mask; configurable p.19.
1, 2, 3 Select available primary weapon C8A0; mode-dependent p.19: keys listed; later weapon names left blank.
5, 6 Select available secondary ground weapon C885 p.19: keys listed; names left blank.
8, 9, 0 Select available secondary air weapon C885 p.19: keys listed; names left blank.
Insert / keypad 0 Hold enlarged radar overlay 55A5, default mask 1000 p.18 explicitly documents keypad 0 and magnification; p.22 identifies Insert equivalence.
Tab Hold third-person look-around mode; steering device controls view 7872, default mask 0180 includes joystick button; third-person transition confirmed during playtesting p.18: look-around documented; third-person transition not explicit.
F1 Cockpit; missile-follow view in missile mode B8AC, view index 0 p.18.
F2 Behind craft/missile Same, index 1 p.18.
F3 Level behind craft/missile Same, index 2 p.18.
F4 Full-screen inside / missile-eye view Same, index 3 p.18.
F5 Drop camera, follow craft/missile B8A0, index 4 p.18.
F6 Drop camera, fixed view B8A0, index 5 p.18.
F7 Drop camera on object pointed at 257D p.18.
M Toggle missile-view mode B8C1, XOR 54CA with 7; disabled for mode 2 p.18.
Comma / period (manual labels < / >) Move following camera closer / farther B8B2/B8B5, six-position index B8B8, consumed 2554 p.18.
Pause / Num Lock Pause until another key Scan 45, B7BB p.19.
Escape Quit/confirmation UI B7CE p.19.
Q after Escape Confirm quit B7DA; requires nonzero 3EA5 Not listed in the reviewed control section.

These are scan codes, not character comparisons. Shift is not necessary for comma/period zoom or the = event. Dedicated versus keypad equivalents depend on the keyboard/emulator's extended scan-code delivery. The supplied batch file runs X Lang=0 Mus=1 without control remappings.

The manual documents mouse/joystick steering and firing as well. It lists command-line options for changing action masks, but this executable differs from the manual's fire-option names and has an apparent mask-inversion defect. See the complete command-line reference and native parser checks before using remapping recipes. The mask's keyboard half is: Tab 0100, Backspace 0200, equals 0400, minus 0800, Insert 1000, Caps Lock 2000, Space 4000, Alt 8000. Lower bits represent mouse/joystick buttons. The bitmap aggregation is B9F3–BA20.

The enlarged radar is therefore documented, though easy to miss: printed p.18 explicitly calls it an overlaid, magnified display. The undocumented bindings in the extras table are distinguished from the merely hinted craft-specific functions above. The Skimma’s repeated 1–3 enable/disable behaviour is not explained in the reviewed control section.

Caero weapon number keys

The manual leaves the later weapon names blank. The following mapping is recovered from the executable's number-row bindings and mission-script weapon introductions. Selections work only when the mission has made that weapon available; these names apply to the Caero, not the Skimma's craft-dependent 1–3 controls.

Number-row key Weapon Fire action
1 Pinner Direct Primary
2 Pinner Mimic Primary
3 Brent Forbes Dual Launch Primary; automatically selects its follow-up homing unit after the capsule launches
4 No direct weapon binding —
5 Forbes Diffuser Secondary; automatically alternates gas capsule and trigger
6 Brent Ground Secondary
7 No direct weapon binding —
8 Caero Weapon Secondary
9 Pinner/Forbes Chargeable Secondary; hold to charge, release to launch at a valid target
0 Brent Hunter Secondary

Default keyboard fire actions are Space (primary) and Alt (secondary). The paired weapons use internal selection IDs 4 and 7, but pressing those number keys does not select the corresponding components. In particular, 3 selects both stages of Dual Launch through its automatic sequence; its follow-up remains on the primary-fire path.

Evidence: dispatch B793–B7B8, key table B7FA, selection handlers C8A0/C885, weapon indexing C9D1–C9D8, and mission availability handler C281. See weapon identities and behaviour for the slot mapping, mission evidence and special firing/impact rules.

Extras and hidden controls

Key Finding Evidence and limits Manual coverage
Z Toggle player-ship freeze after Lyndon's little snooze Playtesting confirms enemies continue, firing and external views work; callback swap at B938 Not listed in the reviewed manual control/configuration sections.
X Immediately start next-level transition after Level X Playtesting confirms cutscene then progression; B926 Not listed in the reviewed manual control/configuration sections.
Grave / backtick Alias for F7's object camera action Both table words point to 257D; not listed in English controls Not listed in the reviewed manual control/configuration sections.
F9 Switch Gouraud-shaded polygons to the flat-colour path and back 33B4 changes relative jump operands at FC13/FE13, selecting 30EB/30A1 versus 312A/30BD; extra bytes are vertex shades, not UVs; see model-colours.md Not listed in the reviewed manual control/configuration sections.
J Reset joystick sampling/calibration state B7F4 calls 171C and 1731; not a demonstrated mouse/joystick selector Not listed in the reviewed manual control/configuration sections.
Keypad minus Cycle paired-view camera separation through 8,16,24,32,40; no effect on the ordinary single-view path B7E5 changes immediate 2B69; 2B51 gates the paired camera offsets on display mode 3CFD >= 1. Stereo-separation interpretation follows from the two displaced scene draws; full alternate-display output not tested Not listed in the reviewed manual control/configuration sections.

Shift also participates in a camera-state latch (3E20, 257E); this has not been assigned a separate player-facing action. No active event-table bindings for F8, F10, number-row 4 or 7 were found. This does not make them unavailable in other screens or through a different input device.

Keypad minus has five states, with an initial parameter of 16: successive presses select 24, 32, 40, 8, 16. At 2B51, mode 3CFD < 1 jumps straight to the ordinary scene draw at 2BC1, bypassing this parameter entirely. Otherwise the renderer saves the camera position, applies a half-parameter offset (2B6E), draws one view, applies a negative full-parameter offset (2B7C), restores the saved camera values, switches drawing destination and draws the other view. 2B97 projects these offsets using camera-orientation coefficients. This strongly identifies a stereo/paired-view separation adjustment: look for changed relative parallax between the two views, not a detail or shading change. No visible change is expected in the standard single-view mode, consistent with the test. Hardware/display-mode activation and full output remain unverified.

Reproduction

python3 tools/inspect_flight_keys.py writes all 83 entries, including no-ops, and the relevant held-key bit locations to analysis/flight-keys/bindings.json. This is static extraction plus manual comparison, not a claim that every key has been exercised in a complete playthrough. The existing hidden-command harness separately executes the Z/X handlers and their gates.

Halon / Skimma differences

Playtesting confirms that after level 99 the player moves into the Halon city and flies a Skimma, and that E switches its shields on/off. Bank 31's role is therefore identified by gameplay, not merely guessed from its geometry.

Craft configuration is separate from city-bank selection. Loader BC50–BC66 reads 24-byte records at 1B66 + 24 * byte[F003]:

Configuration index Control discriminator B91F City bank Initial callback
1 19 30 7E7F (Caero)
2 1A 31 8108
3 1B 31 7E49
4 19 32 D510 (underground)

Playtesting confirms that the higher Enter speed is turbo on the upgraded Skimma. This identifies the 1B behavior as the upgraded configuration; the complete mission-to-configuration schedule remains to be mapped.

Control Caero (19) Halon configuration 1A Halon configuration 1B
E Engine toggle Shield toggle Same non-Caero shield branch
Number-row − No speed-setting write Set speed parameter 248 Set speed parameter 248
Number-row = No speed-setting write Set speed parameter 500 Set speed parameter 500
Enter Spend 32 boost reserve; activate boost No action in this handler Set speed parameter 640
A Altitude-hold toggle Normal 8108 flight path ignores this toggle Needs configuration-specific callback assessment
1–3, where available Select weapon Select/toggle weapon enable Select/toggle weapon enable

The speed keys select discrete parameters; they do not increment/decrement a throttle value. The numbers are internal parameters, not established mph. Holding the brake bypasses the selected parameter in the 81D1–81E0 path. The manual's printed p.14 mentions cruising/turbo speeds and upgrades, but does not supply these key assignments. Playtesting has now confirmed − / = as speed down/up, and Enter as the upgraded Skimma’s higher maximum speed (turbo).

For non-Caero weapons (C8B6–C8DB), a repeated press on an already selected available weapon toggles its low enable bit. Changing selection also clears other enable bits (C8DD). This differs from ordinary Caero selection. The isolated probe verifies key 1 twice yields 1,0 in the Halon configurations, versus 1,1 for Caero. Availability is still gated by the equipment mask.

Shields and landing

E sets a startup deadline at 57B8 = timer[0BF8] + 06FF when enabling shields. The display logic at 57B7–5828 uses that deadline and the resource at 810A. Thus the code distinguishes enabling shields from their later displayed state; no conversion of the timer interval into real seconds is claimed.

With the shield flag enabled, 84E7–84FC subtracts incoming damage from 810A and sets a different damage status when depleted. With shields off, it instead sets damage status 4. This identifies the earlier “incoming quantity” test more precisely for the Halon craft: it is shield-resource depletion, not a universal health field. A 21-point probe takes reserve 100 to 79 with shields enabled.

The supply-pad approach path (C6FB–C76E) requires shields off, object flag 10 clear, bank mode 1, and suitable movement/position conditions. It tests the cell's type for 3, then installs automatic landing callback 7D9A and sets object flag 10. E refuses to leave shields enabled while that flag is set. This matches the manual's p.15 requirement to disable shields before landing. It also identifies bank 31, type 3 as the supply-pad geometry used by this landing check.

tools/verify_flight_controls.py executes 16 original-handler probes covering speed/boost differences, E's landing-state restriction, shield damage and repeated weapon selection. Sound/UI notification and target-refresh helpers are stubbed; this is not a substitute for testing each late-game configuration in DOSBox.

Manual shield timing observation

We measured shield charge/startup as approximately 4 seconds with manual reaction-time uncertainty. The PIT setup subsequently traced to divisor 2,386 predicts about 500.075 ticks/second, putting the 06FFh deadline at 3.58146 seconds. The approximately 0.42-second difference is retained rather than declaring an exact confirmation or changing the clock rate to fit it. The display routine 57B7–5828 has several phases based on the remaining deadline and shield reserve; which visible transition was timed is not established. No extra fixed delay has been established by this inspection. Video timing of consistent start/end landmarks would resolve the comparison more tightly.

See recorded measurement.