# Resource extraction and binary formats

Open the [offline resource browser](resources/index.html) to inspect the results.
It works directly from the filesystem: no server, downloads or build are needed.
The source installations are never modified by the extraction tools.

## Current extraction

Ten retained game filesystems are scanned, including the original installation
and played 2.00 floppy, with identical source files sharing one decoded asset. The browser records every contributing source path and SHA-256.
Embedded models are extracted from all seven distinct flight binaries. The two
reference editions have traced runtime animation; byte-identical installations
reuse those profiles.

| Resource | Decoded result |
| --- | --- |
| Artwork | 40 distinct VGA images decoded to indexed PNG; 14 original distribution JPEGs displayed in place |
| Cockpit and help screens | Two cockpit-mask variants and 25 distinct help images; each reference install has one cockpit and ten help pages |
| Worlds | 25 distributed definitions, 22 saved campaigns, three native-generated training examples and the source-only slalom layout |
| Embedded models | All seven flight binaries; 61 templates each, plus sun geometry, early sun-face variants and radar wrecks; animated effects in the reference editions |
| Palettes | Six distinct 256-colour palettes across editions |
| Medals | Sixteen custom 8×16 glyphs |
| Music | Six ROL sequences, three banks, one decoded driver; seven full sequence/bank FLAC renders |
| Effects | Three ADL files, 35 patch auditions and two examples executing native sound routines |
| Presentations | 55 distinct image/layout combinations; 17 panels in the normal reference, plus original animated title playback |
| Runtime state | Three recorded demos; four distinct pilot files; four distinct high-score files with three top-ten tables each |
| Programs | DOS executable headers and printable strings for 33 distinct executable contents |
| Text | 93 distinct manuals, help files, briefings, scripts and distribution documents |
| Promotional screens | Three executable text-mode screens, rendered with searchable transcriptions |
| Sky and instruments | Generated native star positions and plots, plus existing original cockpit/HUD and SRATS captures |
| Configuration | Four distinct configuration/PIF files, with original bytes, words and strings retained |

These are counts of distinct resources, not counts of missions, songs per edition
or independently flyable craft. Source JPEGs and converted VGA images remain
separate representations; they are not claimed to be byte-identical.

## Reproducing the extraction

With Pillow, Unicorn and DOSBox installed (DOSBox supplies the external BIOS text font for presentation composites):

```sh
python3 tools/extract_resources.py
```

The source tools are [extract_resources.py](../tools/extract_resources.py),
[corncob_models.py](../tools/corncob_models.py),
[corncob_colours.py](../tools/corncob_colours.py),
[corncob_music.py](../tools/corncob_music.py),
[resource_viewer.html](../tools/resource_viewer.html) and
[model_viewer.js](../tools/model_viewer.js).

Additional verification uses Pillow and Unicorn:

```sh
python3 tools/validate_resources.py
```

The [verification report](resources/verification.json) records byte-for-byte
agreement with the original `RIMG.EXE` decompression loop for all 27 masks, and
agreement with the original `3.EXE` record-expansion routine for all 898 objects
in the four normal-game reference theatres and two saved campaigns. Fourteen illustrated VGA images also
match the dimensions and closely match the colours of their original JPEGs.
The latter is an image comparison, not an assertion that different JPEG decoder
and quantiser implementations produce identical pixels.

[disassemble_engine.py](../tools/disassemble_engine.py) uses Capstone to regenerate
[selected, identified original routines](engine-disassembly.txt). Its addresses
are executable **file offsets**, and the fixed ranges refer to retail 3.42 only.

## VGA images

The first four bytes are two little-endian words: maximum X and maximum Y.
Dimensions are those values plus one. A file contains:

1. Four-byte dimensions.
2. `width × height` consecutive, row-major palette indices.
3. Padding bringing the pixel allocation up to `align_up(width, 8) × height`.
4. Two extra bytes.
5. Optionally, a 768-byte palette.

The padding is **all at the end**, not at the end of each row. Treating the
allocation stride as the row stride produces conspicuous diagonal shearing.
The JPEG converter's output routines establish the ordering directly; the two
extra bytes are zero in its output but need not be zero in hand-authored images.

Embedded and separate palettes contain 256 RGB triples with six-bit components.
PNG export preserves the original indices and expands each component with
`(value << 2) | (value >> 4)`.

Images without an embedded palette inherit palette state during title playback.
Their static previews use `HC6.PAL` and explicitly identify that choice; it is not
a claim that every frame of the title uses that palette unchanged. Original
colour cycling, fades and sprite transparency still need their playback traced.

Evidence: `JVCC.EXE` file ranges `0x491–0x59b`, `0x59b–0x63a` and
`0x6f5–0x7e2` in the selected disassembly.

## IMG cockpit and help graphics

These are compressed one-bit graphics, not disk images. `RIMG.EXE` skips the
first four bytes and alternates:

- A little-endian repeat count, masked with `0x3fff`, followed by one repeated byte.
- A little-endian literal count, masked with `0x3fff`, followed by those bytes.

The expanded screen is 640×350, eight pixels per byte, most-significant bit first.
Runs are clipped to the destination capacity. The final repeat can fill the
remaining screen without another literal payload; blindly reading complete
repeat/literal pairs until end-of-file is incorrect.

The browser shows raw monochrome masks. The helper normally applies them to two
EGA video pages and depends on existing video state. A nonzero view argument
changes its draw capacity from 28,000 to 15,920 bytes, i.e. 199 scanlines. The numbered files are help screens, rather than different craft/view masks. [Checked transcriptions](help-screens.md) preserve all 25 distinct help images, including earlier wording and the 1.20 welcome page. The browser labels their subjects and searches their text. The diagonal line in both cockpit variants is part of the original data; its purpose is unresolved.

Evidence: `RIMG.EXE` file range `0x292–0x2de`, independently executed in Unicorn;
also the [native DOSBox helper capture](install-file-previews/rimg.png).

## World files: CCT and DEF

All decoded editions use 64 tiles in row-major order, eight columns by eight rows.
Each tile starts with a 16-byte header:

| Offset | Size | Meaning |
| --- | --- | --- |
| `+0` | 4 | `Pie` followed by NUL |
| `+4` | 2 | Tile X, 0–7 |
| `+6` | 2 | Tile Y, 0–7 |
| `+8` | 2 | Object count |
| `+10` | 1 | Tile storage/state flags |
| `+11` | 5 | Packed six-bit sky/ground RGB values |

The header is followed by `count` 23-byte object records:

| Offset | Size | Meaning |
| --- | --- | --- |
| `+0` | 2 | Packed high coordinate bits: X in bits 0–4, Y in 5–9, Z in 10–14 |
| `+2` | 2 | X low word |
| `+4` | 2 | Y low word |
| `+6` | 2 | Z low word |
| `+8` | 3 | Heading, pitch, roll high bytes, in that order; expanded to 16-bit angles with low byte zero |
| `+11` | 2 | Object flags |
| `+13` | 8 | Four object-specific words; raw values retained pending per-type interpretation |
| `+21` | 2 | Object type, encoded in CCT and plain in DEF |

For CCT, the type is `stored_type XOR x_low XOR y_low`. This is a small
obfuscation, not compression. DEF files in the expansion retain the plain type.
The decoder checks every type against the 61-entry definition table.

Coordinates are centimetres. With `tile_size = 32 × 65536` and
`origin = -128 × 65536`, the position is:

```text
X = origin + tile_X × tile_size + packed_X × 65536 + X_low
Y = origin + tile_Y × tile_size + packed_Y × 65536 + Y_low
Z = packed_Z × 65536 + Z_low
```

Each tile covers approximately 20.97 km; the complete coordinate grid spans
approximately 167.77 km on each horizontal axis. This is the storage grid, not
an assertion that scenery fills every tile or that the player has unrestricted
travel across all of it.

After all 64 tiles are twelve bytes: the player start position as three signed
32-bit centimetre coordinates. This is confirmed by READUNIV in the preserved
original source, which copies them directly into the player position.

READCOLORS interprets header bytes 11–15 as a big-endian 40-bit value. Its six-bit
channels are sky R/G/B at shifts 32/26/20 and ground R/G/B at shifts 14/8/2; the
lowest two bits are unused. For example White Sands stores sky `(15, 8, 61)` and
ground `(59, 62, 52)`. These replace EGA palette slots 11 and 2. The native C++
reconstruction and the 3D research world viewer use these values.

Evidence: `3.EXE` loader `0x1b84–0x1c1c`, compact-record expansion
`0x7f85–0x8056`, and inverse packing `0x8056–0x80f8`. The expansion table lookup
is found by its instruction sequence and checked against template self-IDs.

The `angles_u8` and `angles_u16` arrays retain the original heading, pitch, roll
order. `MAT.ASM` documents the same order for GETANG; NCALCMAT transforms
model coordinates with `Rz(heading) × Ry(pitch) × Rx(roll)`. Atkinsville’s
second parked aircraft stores `[224, 250, 0]`: a −45° heading and −8.4375°
pitch, not a 45° pitch. Early extraction variable names reversed heading and
pitch, although the exported arrays always retained the correct byte order.

The resource browser opens worlds in 3D, including all edition variants and
saved campaigns. It shares the showcase's scenery renderer, recovered world
colours and per-instance colour cycling. Object selection exposes the complete
record and links to that edition's model; mission starts, landmarks, type
filters and airfield/world framing are available. The 2D atlas remains an
alternative and a fallback when WebGL is unavailable. It shows +X to the right
and +Y upward without assuming those axes mean East/North. Both views support
shareable world/object links. See [viewer maintenance](../tools/viewers/README.md)
for the feature list, source provenance and browser checks.

## Briefing and environment files

Mission headings occur as both `Mission Code Name:` and `Mission:`. Each stored
`Sxyth` start is paired with its own title, direction, distance, difficulty and
briefing text. A fresh `Direction:` without a mission heading begins an untitled
briefing; Ice World's second Dulles start must not inherit **Hornet's Nest** from
the preceding mission. Missions without `Sxyth` still appear in the complete raw
text, but have no stored starting position to offer in the viewer.

Selecting a start shows a reading copy with hard-wrapped lines joined and divider
lines removed. Original wording is retained, and the full verbatim section remains
under **Briefings and environment**. A `start` URL parameter links directly to the
chosen briefing. In 3D, the stored heading helps frame nearby objective scenery
from the approach direction. The orbit centre stays on the ground beneath it;
the camera pulls back to include elevated structures. This is an inspection
heuristic, not a stored mission-to-object link. The **2D objectives & starts**
switch controls atlas markers and
is disabled in the 3D scenery view.

TWR files are CP437 text with form-feed-separated sections. Each `Sxyth` line
provides a mission start: X, Y, Z and yaw. A section can contain several missions;
one form-feed block is not necessarily one mission.

The optional leading `X` line describes sun angle, sun size, sun colour, gravity,
air density, star visibility and atmosphere height. These meanings come directly
from the expansion's [mission-builder manual](../installs/other_worlds_download/MBUILDER.DOC).
Its documented ranges should not be assumed to match every engine's actual clamps.

The same manual reproduces original assembly symbol names and object tables.
Those supply the browser's names, including generator orbs, KLA sites, vehicles,
forcefields, portals and the rescue van. Record parameters can have different
meanings for different types; the JSON deliberately preserves them as raw words.

## Embedded model data

Models are stored inside the flight executable, not in the cockpit IMG files.
Both reference engines have a 61-entry template-pointer table. Each template is
74 bytes and ends with its own type ID, which the extractor validates.
Three data pointers at template offsets `+40`, `+42` and `+44` select model detail
variants. They are **not executable callbacks**.

A model starts with three position/cache words, then a command count. Eight
command lists follow, one per viewing octant. Every command is two words:
primitive opcode and data-segment address. The original renderer selects the
list by signs of the camera-relative position in model coordinates.

| Opcode | Payload |
| --- | --- |
| 0 | No drawing |
| 2 | Counted list of polyline pointers; each polyline has segment count, colour and `count + 1` connected XYZ vertices |
| 4 | Counted XYZ points with individual colour words |
| 6 | Counted XYZ centres, diameters and colour words; projected as circular discs |
| 8 | Polygon vertex count, colour word and XYZ vertices |

The size word in opcode 6 is a **diameter**, not a radius. The original projection
routine scales it by focal length / depth, then the rasterizer halves that result
to position the left and right edges (`3.EXE` file offsets `0x6be4–0x6bfc`).
For example, the ground crew's head has diameter 40, and the ground vehicle's
wheels have diameter 428 with centres at Z=214, placing their bottoms at ground
level. The extractor records `diameter`; browser framing uses half that value
and both the main view and thumbnails use the full width for point size.
The [verification report](resources/verification.json) includes execution of the
original projection and rasterizer setup for head and wheel sizes.

The **experimental stealth aircraft at White Sands** is not a separate object
number. The parked instance is type 2 (Aircraft), with flags `0x20f9`: flag
`0x2000` makes the game replace its near and middle model pointers at runtime.
The original extractor followed only template pointers and therefore missed it.
It is now extracted as a separate browser entry, **Experimental stealth aircraft
(White Sands)**, while retaining type 2 and recording the selection condition.
Its model contains five polygons, at data-segment address `0x6838` in retail
3.42 (`0x6a6a` in Other Worlds). The far-detail pointer is left unchanged by the
original code, so selecting Far shows the ordinary aircraft's distant silhouette.
Retail selection blocks are at file offsets `0x8fc1–0x8fd1` (internal/player
object) and `0x97ac–0x97bc` (parked aircraft). Both blocks in both reference
engines are checked by executing the original instructions with the flag clear
and set. The White Sands briefing explicitly describes the parked craft as an
experimental aircraft for a high-altitude test.

### Model states and the ground crew's gesture

The browser's **Pose / state** selector now exposes the following original
arrangements. Thumbnails follow the selected state too, and the framing stays
fixed across a model's states so changes of pose do not look like zooming.

| Object | States exposed |
| --- | --- |
| Runway piece | Standard and alternate quality-flag geometry |
| Ground crew (7) | Standing; raised middle finger; shot and lying flat |
| Radar (3) and wreck type 33 | Active/inactive dish; distinct burning radar wreck |
| Aircraft (2 and internal 28) | Intact; damaged/bent geometry with the fire-particle primitive |
| Explosion (19) | White flash; yellow flash; red flash |
| Generator orb (0) | Intact; destroyed (becomes type 43) |
| Fuel dump (27) | Intact; destroyed (becomes type 33) |

The crew gesture is **one discrete pose change**, not a cycling animation. In
retail 3.42, `0x8d2b–0x8dbb` resets the uniform colours, checks damage, and tests
proximity. With the player **on foot**, a standing crew member within **2,000 cm
(20 metres)** switches all three model pointers from the standing model to
`0x6f71`. That pose persists when the player moves away. The model adds a bent
arm, hand and extended finger; there are no intermediate frames to interpolate.
Flag `0x1000` instead selects the bloodied `0x7099` model and sets pitch to
`0x4000` (a quarter turn), laying it flat. Flag `0x0800` makes the uniform black;
this colour variant is not a separate pose. Equivalent models in Other Worlds
are `0x71a3` and `0x72cb`.

The aircraft damage flag `0x0100` selects model `0x47a1` for near/middle detail
(`0x4879` in Other Worlds). Its bent parts are authored geometry. The model
gallery previews its fire discs using captured native particle updates, as
described under [continuous effects](#continuous-model-effects);
it does not run the complete aircraft-damage simulation. The experimental-aircraft flag overrides that ordinary damage-model
selection, so the stealth preview does not inherit this state selector.

Explosion updates (`0xae0b–0xae28`) select the white model while the lifetime
word is above 3, yellow at 3 and red at 0–2. The stored diameters are 2,500,
4,000 and 6,000 respectively. The viewer defaults to an **Animated stages**
inspection loop for this object, showing white → yellow → red at four stages
per second. This deliberately readable preview cadence is not a claim about
the original lifetime countdown timing. **Animate geometry** pauses the loop;
each stage remains individually selectable. The main view and thumbnails share
the same stage and fixed framing, preserving the visible expansion.

The verification tool runs the original crew routine for near/far, on-foot/in-
aircraft, shot and already-raised cases in both reference engines. It also
executes the aircraft-damage and explosion-stage selection instructions.
The results are in [verification.json](resources/verification.json).

Stored model swaps are distinct from continuous effects. The reference viewers
now include traced dish/propeller rotation, forcefield geometry and captured
particle updates; their timing and preview limits are described below. This
does not simulate whole-object flight or gameplay-driven damage progression.

A colour word with a nonzero high byte points to a runtime colour variable;
otherwise its low byte supplies the stored value. Some values also involve
renderer conventions that are not yet reproduced. Animation and object quality
can alter colours, geometry and model selection during play. The state selector
applies the explicitly traced model swaps and crew pitch change described above.

All original command lists and addresses are retained. The model gallery follows the
original **painter order**, selecting one of the eight lists for the viewing
direction. It preserves interleaved polygons, polylines and discs, repeated
commands, and surfaces omitted from particular directions. Depth testing is
disabled: coplanar details rely on later drawing replacing earlier pixels,
including the crew's eyes and mouth, runway markings and rescue-van windows.
Some van lists draw the windscreen twice around other surfaces; deduplicating
commands or sorting by primitive type loses that authored layering.

The list index packs signs of the model-relative **object-minus-viewer** vector:
negative X contributes 4, negative Y 2 and negative Z 1. Preview camera and pose
rotations are inverted before selecting the list, including the shot crew's
quarter-turn pose. Exact-axis views choose the nonnegative side. Verification
executes the original selector and observes the van's command traversal for all
26 nonzero combinations of negative/zero/positive axis components, in both
reference engines. Thus the checks include omitted and repeated commands as
well as all eight octants.

The model gallery uses an orthographic inspection projection and optional neutral
shading so that uninitialised runtime colours do not hide the geometry. It is not
a pixel-faithful reproduction of the DOS rasterizer or a full simulation of live
object behaviour.
Game-colour rendering remains approximate where special stipple/rasterizer conventions have not yet been reproduced. A clickable thumbnail gallery follows the main preview’s rotation, detail level and colour selection. Paging defaults to thirty models at a time and can be disabled to show all models. Line strokes scale against a 320-pixel reference viewport, with a one-CSS-pixel minimum for thumbnails; their thickness stays constant while zooming. They are drawn as screen-space quads to avoid WebGL drivers that limit native line width to one pixel. Thumbnail badges identify available colour variants and multiple poses/states; the corresponding dropdown is greyed out when the current preview has only one meaningful choice.

Evidence: distance/detail selection `0x7270–0x73a8`, octant/command dispatch
`0x5e44–0x5fc2`, polygon transform `0x5b83–0x5c89` and disc transform
`0x5d45–0x5e0d` in the retail reference. Connected polylines advance one vertex
per segment; treating them as independent pairs reads into neighbouring data.

### Runtime model colours

**Game colours** is now the default in the model browser. **Animate colours**
can freeze the current frame for inspection; **Neutral geometry** remains
available. The main model and its thumbnails share the same colour phase.
**Colour variant** selects the original three-bit quality's paint-table row
(0–7) where applicable; it changes the preview's paint rather than simulating
that quality's wider gameplay rules. Radar dishes have active/inactive homing-
beacon states so their conditional flashing can be inspected explicitly.

These colours are pointers into mutable data, not black materials. The traced
rules include:

| Appearance | Original rule reproduced |
| --- | --- |
| Generator-orb core, Mindbender and other users of the shared random colour | One random colour from indices 0–14 per game frame |
| Active radar homing dish | Black/white flashing from timer bit `0x0400`; black when inactive |
| Projectile/debris colour pairs | Swap their original two colours each game frame |
| Generator-orb base, forcefields, balloons and vehicles | Original eight-row quality/paint tables |
| Orb ring and ground-vehicle antenna | Timer-bit `0x0200` flashing when object flag `0x0800` enables it |
| Saucer paint and mission-objective saucer panels | Two quality-dependent paint colours; objective panels use the shared random colour |

The random generator is the original 32-bit multiplicative recurrence,
`state = state * 0x278dde6d mod 2^32`, with the high word reduced modulo 15
for the shared colour. The viewer uses a fixed seed and advances it independently
of which thumbnails happen to be visible. The game consumes random numbers for
many other effects, so this is not a claim to reproduce a particular play
session's exact random sequence.

Random and alternating colours advance once per DOS **game frame**, so their
speed originally depended on frame rate. The inspection preview uses **30 colour
updates per second**. Timer-driven flashing uses the original PIT input
1,193,182 Hz divided by 1,024, approximately 1,165.2 ticks/second; it is not
arbitrarily tied to the browser's refresh rate. Pausing freezes both clocks.

The extraction records rule sources and tables for both reference engines.
Verification executes the original routines for 64 consecutive random colours,
all eight rows of seven table selections, active/inactive flashes at timer
boundaries, the three alternating pairs and every possible shared colour in
the objective-saucer override. Original routine excerpts are retained in
[engine-disassembly.txt](engine-disassembly.txt); results are under
`model_colours` in [verification.json](resources/verification.json).

The 3D world viewer applies the traced placement flags, paint choices and
world-defined sky/ground colours. It cycles colours on static geometry; the
model gallery separately offers the recovered pose and particle previews.
Neither viewer reproduces every special EGA drawing mode or live gameplay
transition. Untraced colour pointers retain their stored values instead of
being assigned an invented animation.

## Music and effects

ROL streams have been decoded completely: tempo changes and eleven logical
voices, each with notes/rests, instrument changes, volume changes and pitch
changes. Durations below integrate the stored tempo values. They are **nominal
sequence durations**, not verified recordings or loop boundaries.

| Edition | File | Nominal duration |
| --- | --- | ---: |
| Normal game | `DESTINY3.ROL` | 84.46 s |
| Normal game | `RIDINGT.ROL` | 203.99 s |
| Normal game | `DREAMSO2.ROL` | 178.33 s |
| Other Worlds | `VOYAGE3.ROL` | 232.24 s |
| Other Worlds | `DAYBREAK.ROL` | 152.16 s |
| Other Worlds | `HEAVENS.ROL` | 229.65 s |

The normal-game manual credits Jim Collymore / James L. Collymore for its music.
It refers to an older `DREAMS0.ROL` filename; the inspected file is `DREAMSO2.ROL`.
Title playback references `DESTINY3`; `ROLFILES.TXT` lists the two menu pieces.
The normal-game audio exports now use the original driver; its native timings
and register sequence are documented in [audio-rendering.md](audio-rendering.md).

BNK extraction retains instrument names, active-slot information and the 30-byte
patch records. ROL instrument names are terminated at NUL; bytes after that can
contain editor leftovers and are not part of the name.

`MOAGDATA`, common to the later packages, decodes with XOR `0xA5`. The block
contains the AdLib sound-driver V1.51 signature. The decoded block is exported
without truncation. Object/linker-style filenames near its end, such as
`iscore.OBJ` and `readfont.obj`, are recorded with offsets; their reason for being
in the block has not been established.

ADL effect files contain comma-separated hexadecimal register/value pairs,
separated into blocks by `ff`. The normal reference has twelve blocks. They are
patch definitions rather than recordings. All three banks now have playable
auditions, and selected native routines supply engine and death-sound examples.

[Audio exports and reproduction](audio-rendering.md) document all seven complete
music renders, their matching banks, release tails and the distinction between
AdPlug sequence timing, native register-writing routines and chosen audition
settings. Audio exports use maximum FLAC compression and no normalisation.

## Original author's retrospective

Kevin Stokes's [2010 engine article, archived in 2020](https://web.archive.org/web/20201109033939/https://www.pieintheskysoftware.com/art-history-corncob-3d-engine.html)
is a useful primary source alongside the binaries. It describes signed fixed-point
rotation matrices, saturating arithmetic, aerodynamic lift and damage effects,
AdLib synthesis, and the separate C front end written by George Welch. The main
engine source was assembly. It also explains the artwork: photographs of plastic
aircraft models and the author in surplus flying clothing, retouched digitally.
These are author recollections; exact release-specific behaviour is still checked
against the retained programs.

## Continuous model effects

The reference model viewers now animate native forcefield shapes, saucer pulse
vertices, radar rotation, the propeller and a repeatable particle preview. The
geometry and colour controls pause independently. Static geometry remains cached;
only models using changing words are rebuilt, and visible thumbnails follow them.

The forcefield routine at `0x8ada–0x8bd6` increments a 16-bit phase each game frame.
It uses three cosine phases with multipliers 4096, 3111 and 5333. The original
quarter-wave table and integer interpolation are retained, including the sign
of each destination coordinate and the engine's clamps. Forty-two words affect
stored geometry. Thirteen phases, including wrap and quadrant boundaries, are
checked against native execution in each reference engine; browser checks compare
the resulting coordinate words too. This does not substitute a modern sine curve.

The particle update at `0x3ffa–0x4105` jitters position and diameter words in shared
fire/smoke/effect buffers. A 120-frame clip of original routine output supplies
76 words used by extracted models. The clip repeats for inspection; the original
PRNG does not have a 120-frame period. Preview cadence is 30 frames per second,
whereas these effects originally advanced with the game loop.

Radar heading is four angle units per PIT tick: approximately one revolution in
14.1 seconds. The player propeller's native roll is
`-timer * 2 * (speed_input - 10)`, modulo 65536. Its preview holds the input at 20;
this is a controlled display input, not a running flight model. Both rotations
retain view-dependent painter-list selection.

Run `python3 tools/extract_runtime.py` after the initial extraction, then regenerate
with `python3 tools/extract_resources.py`. Runtime extraction requires Unicorn.
The JSON files `models/*-runtime.json` retain recipes, native particle frames,
bindings, code ranges and comparison values.

## Earlier models

All seven engines use the same basic template/model structure. Earlier builds'
additional model-pointer assignments are followed separately; newer code offsets
and state triggers are not copied onto them. Their colour animation controls are
disabled where no older-build profile has been traced.

The [geometry comparison](model-comparison.md) ignores relocated addresses and
compares every detail level's eight ordered drawing lists. Relative to normal
3.42, 1.20 changes the saucer's far model and the portal's near/middle models;
2.00 changes the portal's near/middle models. Later template geometry is identical
under that comparison. Each normal-game engine now has 111 extracted models, including stored sun-face
and otherwise untraced geometry; Other Worlds has 112. These are model records,
not independently placeable object types.
The runway switch is verified natively with six flag combinations in both reference
engines. Shape matches identify earlier extra appearances without assigning
unverified gameplay triggers. The early sun-face assignment is traced explicitly. The comparison does not claim identical
gameplay or colours.

## Presentations

The browser composes the PICT/TPICT artwork with the stored text, colours and
positions, and provides previous/next panel controls. PICT entries store text
count, pixel X/Y, image filename, text colour, then row/column/text triples.
TPICT instead starts with pixel X/Y and filename, followed by text count/colour
and column/row/text triples; `-1` terminates it. These fields are layout data,
not per-caption timing values.

Normal retail has fifteen outcome panels and two story panels. Different scripts
and image variants across editions produce 55 distinct compositions. The flight
engine's outcome compositor at `0xdc8e–0xdd25` confirms the image and BIOS text
placement. Both reconstructed normal story panels match original CCTITLE output
**pixel for pixel**, including palette index zero's tinted background. See the
[composition comparison](resources/presentations/composition-check.json).

The animated title is also available as a lossless RGB VP9 recording of the
original CCTITLE executable in an isolated DOSBox/Xvfb session. Its drawing,
palette changes and fades are original program output; page holds follow the
recorded key schedule. The silent video avoids storing another copy of the
separately exported music. [Capture metadata](resources/presentations/title-native.json)
records the executable hash, DOSBox configuration and key timings.

`tools/capture_title.py` reproduces that capture with DOSBox, Xvfb, xdotool, ffmpeg
and Pillow. Presentation BIOS text uses DOSBox 0.74-3's built-in IBM-compatible
8×8 font, external to Corncob's assets and licensed GPL-2.0-or-later. The extractor
locates and checks that font; it does not claim the font was stored in Corncob.

## Saved state, demonstrations and training

[State-format notes](state-formats.md) describe the saved theatre header, its
embedded pilot record and world, the seeded pilot-file mask, full/delta demo
records and the native training generator. These now have usable browser views
rather than being omitted opaque files. The original demo reader matches all
4,580 decoded position/angle states; pilot masking matches every supplied byte.

## Coverage and fidelity limits

The identified resource backlog now has extraction and inspection output: audio,
continuous effects, presentations, earlier models, saved campaigns/pilots, demos
and generated training scenery. Extraction checks all 793 source files for changes and currently reports no
decoding warnings. The [coverage inventory](resources/coverage.json) accounts for
791 inspected/decoded source files and two retained duplicate distribution ZIPs;
no source file is unaccounted for. Executable coverage means identified embedded
resources and program metadata, not that every instruction or field is understood.
[Final extraction pass](remaining-assets.md) records the added material and limits. Reproduce the additional checks with
`tools/validate_extended.py` and, optionally with Playwright/Chromium,
`tools/validate_browser.py`.

This remains resource analysis rather than a reimplementation of the game.
Unlabelled campaign/statistics fields, some per-instance colour flags and special
EGA drawing modes are preserved honestly; generated-world examples and particle
clips do not enumerate every possible runtime state. Normal-game music now uses
unchanged bundled-driver captures; other-edition exports still use AdPlug. Effect
auditions explicitly state their selected pitch/hold inputs. Exact gameplay-driven sound scheduling, complete
flight dynamics, collision rules and AI require the subsequent game-logic work.


## Sun, promotional screens and final coverage

The [final-pass notes](remaining-assets.md) describe the renderer-owned sun and
earlier face variant, the distinct radar wreck, executable promotional screens,
older saved games, high-score layouts, native stars and configuration exports.
The original star generator can be rerun with `tools/extract_renderer.py` before
regenerating resources. `tools/validate_remaining.py` checks native score sums,
sun settings and geometry switches, and scans all seven flight binaries for
additional complete models referenced by immediate AX/SI loads.


## Models omitted by source build switches

The preserved assembly also contains source-only geometry in conditional data
branches. [Source variants](resources/models/source_variants.json) expose the
farm from FARM.INC, full/line-trunk/foliage-only tree helpers, the long-stem Tet,
and the slalom crater (160 metres across, fixed blue). The farm and tree replace
saucer and shell geometry in the slalom configuration. The foliage-only tree is
complete but not referenced by its selected object template. Other changed
slalom templates reuse existing aircraft and forcefield models.

`tools/extract_source_models.py` decodes only the original DW/DB/EQU/DUP data,
resolves its pointers into a reserved normalized address range and exports the
same primitive/model schema as the executable extractor. These 935 bytes are
bundled in corncob-cpp as generated resources; the original source is unchanged.
Each preview is marked source-only so it is not mistaken for an asset present
in a retained released executable. The usual extraction command also incorporates
these previews; `--cpp ../corncob-cpp` on the source extractor refreshes the
bundled generated header and its provenance.


The farm preview now includes **Intact** and **Destroyed** states. Slalom's
`bmrtim` calls `gmdest`: destruction replaces the farm with the shared fuel-dump
wreck (`gmobj2/gmobj3`, type 33), rather than a separate damaged-farm mesh. Each
edition preview uses its own wreck addresses; the standalone source catalogue
borrows the equivalent Deluxe geometry and records that provenance. The three
source traffic aircraft likewise reuse the normal aircraft middle/far models.

The **Worlds & missions** selector includes **Slalom — recovered source
experiment**, with 109 placements, six checkpoint boundaries and passing sides,
the runway start, and links to its source-specific models. It initially fits the
course and airfield; **Fit world** includes the distant survey pads. The five
survey objects occupy four corners of a 20.97152 km square, including two
coincident markers at the origin. They are not established world boundaries.

[Slalom JSON](resources/training/slalom.json) and
[SVG overview](resources/training/slalom.svg) are generated by
[extract_source_world.py](../tools/extract_source_world.py), called by the source
model publisher and the normal resource extraction. The shared airfield is
emulated from Deluxe's original training generator with all defence counts zero;
the alternate layout is reconstructed from `DEFOBJS.ASM`, with a matching random
stream. The JSON distinguishes source placements from native live records and
records the preserved-source/released-build forcefield flag difference. This is
a recovered source experiment, not evidence of a shipped slalom edition.
