# Environment palette bindings and colour remaps

The [palette-environment viewer](lighting/index.html) displays the results of executing TFX 2.05's original environment parser at [0x747fc](code/index.html#747fc). **33 of the 39 retained grid names** have usable configurations. For each, the capture records palette filenames, destination banks, mode flags, schematic binding, and seven numerical distance fields. Archive reads, allocation, the resource-root prefix and a fixed time input are supplied by the harness; these are configuration captures rather than rendered flight scenes.

The other six names are `clouds`, `columbia`, `libya`, `seaworld`, `somalia` and `yugoslav`. Five have no matching configuration text, while `columbia` is rejected as an invalid game type. These include authoring/base grids; they are not presented as six broken playable missions. Exact native errors and partial loads remain in [environments.json](lighting/environments.json).

Normal palette banks occupy data offsets `0x21000`, `0xf688`, `0xf388`, `0xf088` and `0xed88`. Darkside configurations load additional banks at `0x10888`, `0x10588`, `0x10288`, `0xff88` and `0xfc88`. All 33 successfully parsed TFX configurations also provide an infrared palette at `0xea88`; the parser’s `inferno` token appears in normal TFX regional configurations too. Multiple banks can deliberately use the same file. Night and darkside flags are retained separately; a fixed-time capture does not reproduce time-varying transitions.

The native **night-light flag** lives in the code object's shape status word at offset `0x47c82`, bit `0x0080`; it is not a field at that offset in the C data object. Captures retain both `shape_status` and `night_flag`. All 33 decoded configurations match their explicit `night` token, including twilight environments. City and runway shape programs test this bit to draw their authored amber/pale-yellow dots; the [map viewer and mechanism notes](terrain-and-scenery.md#night-city-and-runway-lights) now expose them.

The fields at `0x10bc8`, `0x10bd0`, `0x10bcc`, `0x10b9c` and `0x10b98` are now confirmed as **altitude palette boundaries** by the native consumer `0x73214`, which compares them with negated camera-anchor Y at `0x134f8`. It blends the five banks in integer 50-stage steps, with a retained cached blend value and a target-view exclusion. The C++ reconstruction compares every resulting palette byte and retained state across 4,224 supplied-state updates in all 33 environments. The remaining `0x10b8c` / `0x10b90` fields belong to the separate darkside traversal path; that path is outside the TFX altitude-palette comparison.

Native startup `0x73f5c` prepares a magenta sentinel palette, then `0x73964` fills its protected colour entries from the executable table. `0x73a0c` overlays those entries using the player pitch/roll phase and applies supplied flash/redout/blackout state. `HUDCOL` is written directly to the **green component of palette index 6**, not used as a palette-index selector; see [the corrected configuration notes](configuration.md#hud-intensity-hudcol). The VGA upload retains raw bytes, including the default HUD value 125, until the six-bit DAC masks them.

## Colour-index mapping

The native loader at [0xd7954](code/index.html#d7954) initialises identity mappings and loads root **`coltab.dat`**, identifier `7764422a`: **16 rows of 256 byte indices**. The viewer shows every row under a selectable palette and reports the exact source-to-output index under the pointer. Rows are not labelled brightness or distance steps without a verified caller association.

This is separate from **`dat/coltab.dat`**, a 27-byte identity selector sequence `0..26`. Similar basenames do not imply the same layout or role.

The [texture investigation](textures.md) independently verifies that textured rasterisation applies its selected index remap **before** deciding whether to skip transparent colour zero. The existing model/scenery viewers use identity remapping and a selected base palette. This page exposes the native tables and environment bindings without claiming to reproduce all live lighting, fog or time-of-day selection. Recovered Gouraud attributes and controlled raster paths are described below.

Seven `.sta` tables contain 250 tag-word / 5×5-tag-pattern records, using the same vocabulary as ASC authoring metadata. The likely terrain-editor stamp role, diagnostic previews and remaining native-reader questions are documented in [the investigation](unidentified-data.md#terrain-editor-stamp-candidates).

## Native special raster modes

The viewer now includes **27 controlled native quad/circle captures**, generated by [capture_raster_modes.py](../tools/capture_raster_modes.py) through the original scan converters and a planar VGA harness. [raster-modes.json](lighting/raster-modes.json) preserves pixel hashes, coverage, callback addresses, logical operations, pattern phases and procedural seeds. The captures can be recoloured with any extracted palette.

| Mode | Operation |
| --- | --- |
| 0 | Alternating checkerboard pixels |
| 1 | Quarter-density staggered dots |
| 2 / 3 | Sparse dots with span-dependent phase |
| 4 | Procedural stipple with persistent 16-bit seed |
| 7 | Horizontal stripes |
| 10 / 11 / 12 | XOR / AND / OR of source and destination **palette indices** |

Modes 2/3 count VGA bytes rather than clipping every individual plane at a circle edge; a last dot can lie slightly outside the nominal span. Mode 4 has its own self-modifying seed at `0xe3a3f`, independent of model vertex jitter. Its `ADD CH,CL` / `ADC CL,CH` sequence advances once per VGA span byte, including edge groups. Original integer circle tables, not a real-valued square root, define the small-radius spans. The model and actor viewers retain a separate procedural seed across draws; disabling Animate effects in the model viewer supplies a fixed inspection seed.

The software model and assembled-object previews support these modes. The model raster matches complete controlled circle rasters for all nine modes, including procedural seed transitions. Across circles and two quad placements it also matches **43,200 interior pixels**. This check deliberately distinguishes native callback behaviour from the browser's general half-open polygon edges and clipping. The WebGL scenery preview does not yet implement all these special modes.

## Gouraud palette indices

Model opcodes 76/78 contain three/four packed colour bytes; 77/79 draw the shaded triangle/quad. The load conversion preserves those bytes. The native setup handlers at `0xbc498` and `0xbc4b8` store them as 8.8 palette values. The previous viewer ignored these attributes and painted the current flat colour.

The model, cockpit and scenery viewers now carry vertex shade indices. Interpolation selects discrete palette entries; it never blends two RGB colours. The software path retains the tested integer reciprocal and half-step behaviour, while the WebGL scenery path interpolates the palette index and samples a discrete palette texture. Native lighting/remap selection is still separate from this per-polygon interpolation.

[capture_shading.py](../tools/capture_shading.py) checks **46 packed-attribute cases** and eight original Gouraud quads under identity and reversed remaps. [check_gouraud.js](../tools/check_gouraud.js) compares 1,280 native ramp samples. Source pixels and hashes remain in [gouraud-checks.json](lighting/gouraud-checks.json).
