# Dynamic cockpit inspection and HUD consumers

[Interactive cockpit](../analysis/interface/dynamic/index.html) · [Data](../analysis/interface/dynamic/dynamic-hud.json) · [Native checks](../analysis/interface/dynamic/verification.json)

The preview combines the recovered instruments with controllable display state for Caero, Skimma and upgraded Skimma. The windscreen is deliberately a plain inspection background; it is not a rendered world. It includes cumulative gauge strips, Caero compass and coordinates, primary/secondary icons, movable radar contacts, Skimma bearing/weapon-state sprites, three native vector-marker outlines and demonstration indicator timing.

The controls supply display states directly. They do not yet run flight, targeting, damage, charging or mission simulation. This distinction is particularly important for reserve values, shield startup and receiver behaviour.

## Strip updates and engine dimming

`457B–45A6` compares old/new seven-bit counts:

- Increase: apply on-source strips starting at the old count, for the difference.
- Decrease: restore base-source strips starting at the new count, for the difference.
- Equal nonzero count: redraw the last active strip. This permits a colour/source change without a count change.
- For an on/redraw operation with the new state's high bit set, use the packed source word **two bytes before the descriptor**, not the usual on source. This must not be generalised to a simple hidden/off flag.

All 13 descriptors pass five native transition cases each. Caero engine field `4552` additionally passes the 1→129 transition: alternate packed source 2000h, strip zero, count one. The physical Caero source is (64,8), after the viewport row-table offset, instead of the normal (40,22). Its new `alternate` PNG is exported beside on/base, bringing that directory to 365 PNGs. The dynamic preview's engine-dimming toggle uses that patch while preserving the strip mask.

The preview redraws from the static cockpit then applies the first N strips; this reproduces final ordinary count states without requiring a history of previous slider positions. The optional receiver example uses the observed 0/1 blink field; it is not a complete implementation of Nayas message/hangar conditions.

## Skimma 454E: selected weapon reserve/reload counter

`C90A–C94E` clears field `454E`, scans the craft's weapon slots, and copies `5E13 + selected_index` when that weapon is selected and enabled. Other weapons' counters do not populate this field. Thirty-six synthetic native cases cover all three indices, counter values 0–5, and enabled/disabled states.

`5E1F–5E31` decrements this reserve counter when the working counter at `5E10 + index` is empty, then reloads the working counter through `5E50`. `5E44–5E58` refill the counters. Native reserve-capacity bytes at `5E1C` are 5, 3 and 4 in weapon-index order (corrected from the earlier reordered description). This supports the label **selected weapon reserve / reload count**, superseding “unidentified Skimma indicator.” It does not establish a manual terminology or complete firing/rearming model.

## Caero aircraft threat lights

The four red squares above the damage instrument indicate **up to four nearby
aircraft aiming at the player**, rather than compass sectors or incoming missiles.
The strongest threat is on the left. A pursuing fighter is a common cause, but
an aircraft ahead of the player and aiming towards them can also illuminate a light.

Each simulation update resets four angular-error bytes at `576A–576D` to 64
(`3DF9`). After an aircraft steers and moves, `8A58–8AA0` contributes a value only
if its selected target is the player (`D986`) and the high byte of its previously
calculated horizontal distance is below 11 (distance below `0B00h`, 11 map cells).
There is no additional missile-launch, weapon-readiness or line-of-sight test here.

The score adds the folded high bytes of heading and pitch errors between the
aircraft's updated orientation and its earlier target bearing. Negative high bytes
are complemented, not negated. The four smallest scores below 64 are retained,
stored worst first. `574F–5767` converts each score to a brightness level:
`14 - floor(error × 56 / 256)`; an unused score of 64 becomes zero. Thus better aim
means brighter red, not greater proximity once inside the range limit.

Fields `4547–454A` dispatch to `45DD`. They draw compact-font glyph `81h` at Y=180,
with X=232, 224, 216, 208 respectively. Levels 1–14 use ink indices `E5h + level`;
the edge is black for level 1 and `DFh + level` otherwise. Zero restores the
underlying cockpit rectangle. These are shaded glyphs, not four flat-colour fills.
The surface-aircraft path supplies the readings; the underground HUD producer
skips this update. Isolated native checks cover 128 ranking/brightness cases and
the glyph/restore calls at representative levels.

## Normal Caero radar contacts

`5AC9` reads player position and heading; `5AE9–5B55` walks an object list. The two normal display calls use lists at `6FD8` and `6FC8`, with callback offsets BC and B9. The UI names them Group A/B without assigning an unverified allegiance.

Each contact:

1. Must lie in the 42×42-cell candidate window, from −21 inclusive to +21 exclusive on each axis for integer-cell offsets.
2. Is rejected when object flag bit 08h is set.
3. Must pass the `59A3` radio-coverage predicate.
4. Is rotated with the original signed sine/cosine table and signed high-word products, preserving truncation.
5. Is clipped to squared radius 441 around screen (54,215).
6. Produces one pixel. Base palette indices are F9h/F2h for the two callbacks, reduced by `floor(radius_squared/32)`.

The JavaScript integer-cell projection matches **144 original-code cases** across eight headings, boundary/interior positions and both groups, plus an explicit hidden-contact rejection. The native coverage predicate is stubbed as covered in these tests; the preview's coverage checkbox simply suppresses its synthetic contacts. Full per-region radio coverage, interference, tower markers, fractional-cell positions and enlarged/Skimma radar remain separate from this display probe. Existing [radio-beacon investigation](small-beacon-radar.md) documents the coverage network.

Coordinate digits above the cockpit radar use **row on the left (4546, X=44)** and **column on the right (4545, X=56)**. This follows the producer's low/high-byte position mapping and callback-directory order.

## Vector target markers

These outlines are procedural assets, not bitmap crops. `5F39` supplies two halves to `E302/E305`; the byte stream controls the paired outlines. Native execution with captured plane-mask writes yields:

| Stream | Inspection label | Captured pixels |
| --- | --- | ---: |
| 5FCC | Target shape A | 32 |
| 5FDD | Target shape B | 24 |
| 5FEA | Skimma aiming shape | 60 |

The target path at `5F1F–5F39` selects the first shape for type values below 2 and the second otherwise. Native acquisition/type meanings and lock-strength colour changes are not fully translated here. The preview uses fixed explicit colour inputs (E9F3h for target shapes; 0E0Eh for the Skimma shape), stores the resulting colour indices, and allows moving the marker around the windscreen. There is no claim that those fixed colours represent every lock state.

Geometry is captured around (160,84) with a linear row table and stored relative to that anchor. The preview places it at the active viewport centre: (160,92) for Caero and (160,90) for Skimma. Follow-up: [procedural HUD graphics](procedural-hud.md) now captures the enlarged-radar contact shape and Skimma weapon ring. The latter has fixed angular positions and a changing radius; the earlier rotating-ring description was speculative.

## Timing and runtime patches

The missile-camera indicator at `54A3–54EE` uses a green 4×3 rectangle at (300,0), palette index BEh. In ordinary views it requires the missile-view flag and nonzero timer bits 0180h: 128 ticks off, then 384 ticks on, repeating every 512 ticks (roughly one second). In missile camera modes (7 and above) it stays lit regardless of those timer bits. Isolated execution confirms these branches and rectangle arguments. The preview reproduces that bit pattern with an optional approximately 500-tick/second inspection clock; stopped-clock mode keeps the selected indicator visible. Menu/view-mode branches and stereo placement are not simulated.

Original runtime code differs from the untouched unpacked image at several drawing call sites. Probes use the saved DOSBox memory capture `analysis/hidden-commands/ui/after-command-memory.bin.gz`, loaded image segment 01A2, for the radar/shape routines. This resolves the original patched pixel/outline drawing calls rather than treating misleading pre-initialisation relative targets as real consumers. The scene-state fixtures are synthetic. Count transitions and the weapon-counter producer use the unpacked image where their consumed paths do not require those drawing patches.

## Validation and reproduction

```
python3 tools/extract_hud.py
PYTHONPATH=/tmp/darker-python python3 tools/extract_dynamic_hud.py
```

Requires the prior sprite/procedural exports. The report contains 144 radar projection cases, one hidden-contact rejection, 36 selected-weapon-counter cases, 66 strip-transition cases and three native vector rasterisations (116 captured pixels). Browser checks cover all three craft selections, gauge limits, weapon/bearing states, marker choices and clock toggles. No original DOS files are changed.

Outstanding work: run the actual producer functions together over simulated flight/mission state; translate full lock acquisition and colour feedback, radio coverage/interference and all radar modes; connect shield startup/reload timing and receiver messages; complete the height-coded navigation-contact traversal and its live reference-height producer. The mono enlarged-radar surround, heading and coordinates, plus a height-colour glyph sample, are now recovered. Ring, Caero attitude pixels and enlarged contact projection are now available in the [procedural HUD follow-up](procedural-hud.md). The current browser is a display-state inspection rig, not a finished reimplementation of the HUD.

## Craft-specific preview limits

Gameplay corrections and existing native branches constrain the assembled preview:

- Caero primary icons permit IDs 0,1,2,3,7; secondary icons permit 0,4,5,6,8,9,10. The automatic Dual Launch follow-up (7) remains primary; Diffuser trigger (4) remains secondary. Zero is the empty slot.
- Ordinary Skimma speed/output stops at **16 strips**; upgraded Skimma reaches **20**. This matches `582B–5844`, which selects cap 10h for discriminator 1Ah and 14h otherwise. The underlying sheet/mask extraction remains intact for inspection.
- Ordinary Skimma exposes and draws **two** weapon-status slots; the upgraded craft exposes **three**. `C911–C94E` starts at index `(E7h + craft_discriminator) & FFh`, giving 1 or 2, then works down to zero. Switching back to ordinary Skimma clears and disables the hidden third control.
- The heading slider is **Caero-only** because its current consumers are the Caero compass and radar. Neither Skimma has an absolute-heading indication implemented in this preview. The separate Skimma bearing control selects an already-computed relative-bearing symbol; it is not linked to a world-space destination here.
