DARKER Research archive

Model components, landing structures and pointer sharing

Update: animated geometry and linked model states now implements gate/fountain transforms, exports 27 additional linked definitions, and adds state/animation controls. Earlier references below to those models being unresolved describe the previous extraction pass.

2026-09-18. Reproduce with python3 tools/inspect_model_components.py. The machine-readable inventory is components.json. Addresses below refer to the unrelocated executable image or explicitly to a bank's geometry pool.

Screen-space discs

The command is 22 colour:u8 radius_numerator:u16le. In the ordinary projection path, FC22 dispatches to 314D: it subtracts four from the projected-vertex cursor, takes that vertex's screen coordinates, resolves the colour via 3383, and calls A5C0 with the numerator in AX and projected depth in CX. Thus it consumes the last vertex slot, which subsequent vertices may reuse. The native A,B,C coordinates below use the model export's convention (A,-C,B) for Y-up coordinates.

At A5C0, unsigned integer division gives radius_numerator / projected_depth. The result is capped at 256 screen units; zero takes the single-pixel path. The following routine constructs clipped horizontal circle spans. There is no bitmap, UV map or spherical polygon mesh in this command. The near/clipped handler 3161 rejects depths below 32 before projection. Colours go through the same distance/runtime shade machinery as flat faces, then the display lookup. These are internal units, not established metres or an independent world radius.

Bank / entry Centre A,B,C Colour byte Numerator
30 / city 1, energy beacon (0,0,-2400) 0D 30720 (7800)
30 / city 11 (0,0,-720) 1C 6144 (1800)
30 / city 101 (198,-198,-160), (198,-198,-608) 93, 1B 19712 each (4D00)
30 / city 102 (198,198,-160), (198,198,-608) 93, 1B 19712 each
30 / city 103 (-198,198,-160), (-198,198,-608) 93, 1B 19712 each
30 / city 104 (-198,-198,-160), (-198,-198,-608) 93, 1B 19712 each
30 and 32 / special 0 (64,0,0) 1C 2176 (0880)

The tower disc therefore sits at Y=2400 in the exported coordinate system. For illustration, projected depths 1024 and 2048 yield integer screen radii 30 and 15. 1C is a dynamic shade token, not simply a fixed palette index 28. The two discs of types 101–104 are real separate drawing commands.

This inventory covers the statically traversed base definitions, not every alternate/damage model or unresolved animation branch. No discs were encountered in bank 31's traversed definitions. Discs are now shown as camera-facing circles in the model preview (and city viewer), but remain omitted from OBJ surfaces. Their exact definitions and pool offsets are retained in the JSON; see preview scaling.

Other non-polygon components encountered are opcode 1E coloured lines: city types 65 and 67 in bank 30, type 41 in bank 31, and 111 and 112 in bank 32. There are also model-header distant-point representations and conditional visibility branches; these are not additional mesh faces. The static inventory is deliberately not a claim to have exhausted runtime effects or particles.

Fountain reflections: authored geometry, not transparent water

Open the assembled animated fountain. Its twelve components are placed from map 68: two instances each of types 101–104 and one each of 120–123. The authored face/disc order reproduces the tinted reflection over the opaque water; switching off Authored drawing order shows why ordinary polygon depth sorting breaks this effect. Animation starts automatically and the clock can be paused/scrubbed. The view remains orthographic, with approximate between-component sorting and disc sizing.

The facing-test sign was checked against 256 controlled executions of native 2F65: it skips when the screen-space cross product is negative, as used by the viewer. The earlier reflection failure was caused by inspection depth sorting, not an inverted conditional branch. This check covers the sign for supplied projected vertices, not equivalence of every perspective camera pose.

Visual inspection identified the lower discs and pedestal shapes as reflections. The bank-30 type-101 data confirms reflection about the water plane at exported Y=384: the upper light is at Y=608, the lower copy at Y=160, exactly 224 units on either side. Types 102–104 repeat the arrangement in the other quadrants. Both discs use radius numerator 19712, but the upper colour is 1B and the reflected colour is 93, giving the reflection its authored tint.

The lower pedestal includes exact mirrored polygon counterparts: replacing native C with -768-C maps upper faces to lower ones, with different face colours (for example 47 becomes 86, and 70 becomes 8F). These are stored vertices and palette choices, not a runtime reflection transform.

There is no transparent-water material in this model. The ordinary opaque water faces (colour 8B, Y=384) are issued first, followed by the reflected disc and tinted pedestal geometry, then the remaining fountain structure. For type 101, water commands start at pool 9D19, the reflection disc is at 9D45, and reflected pedestal faces follow at 9D49 onward. Stored command order matters more than increasing byte offsets because the model calls shared subroutines. The software renderer has no depth buffer to reject those later reflection pixels for lying below the water plane.

Thus the appearance of seeing through water is an authored reflection illusion: opaque colours and drawing order, not alpha blending. No semitransparent model material has been identified in the decoded retail model command set. Collision overlay translucency belongs solely to the inspection UI. This does not claim that every other screen effect or sprite in the game uses the same mechanism.

Landing gates and animated geometry

HQ gates were proposed for 17,19,21,23 and approach stripes for 18,20,22,24. The executable strongly supports the landing gate/approach identification:

This is stronger evidence than spatial proximity alone. It does not establish that every occurrence belongs to one of the four specifically named HQs on the paper map. The main-city resource contains nine type-17 and eight type-21 cells, with the corresponding stripe immediately in front of each. Types 19/20 and 23/24 do not occur in that resource. Other mission state may alter the map.

Types 14 and 16 are empty base drawing definitions, not currently undisplayed HQ meshes: both point at pool 0FC9, whose body 5A 52 61 0D emits an origin vertex and returns without polygons. Types 78 and 125 share it. Neither 14 nor 16 occurs in the supplied main-city map. An additional role elsewhere is not excluded.

Types 120–123 use another dynamic transform, 3B 09, at pool offsets BDBB, C037, C197, C2F7. Handler 334A reads the same parameter table and scales projection coefficients. DB1A–DB69 updates six parameters beginning at SS:7947 (index 9), driven by the clock and a sine lookup. This identifies a procedural animation dependency. Subsequent visual inspection identified these as probable fountain effects: their four map cells form the central 2×2 of the fountain, surrounded by pool types 101–104. See the assembled scene and coordinates. The eight animated definitions still need correct transform emulation before claiming complete exports.

Shared pointers versus copies

Within a bank, the repeated entries overwhelmingly are aliases to the exact same drawing stream, not duplicated meshes. The 33 special records use only 23 distinct pointers in bank 30, 9 in bank 31, and 19 in bank 32.

Bank Special slots Shared pool offset
30 19,24,26,27 — Skimma geometry D25F
30 25,28,29 — Caero geometry C9E0
30 11,13,16 C819
30 12,17 C8C0
31 19,24,25,26,27,28,29,30,31,32 — Skimma geometry 4E53
31 0–10,15 4C37
31 11,13,16,18 4C8C
32 19,22,23,24,26,27 C1AF
32 25,28 — Caero geometry B930
32 29,30,31,32 C5A4

Every group, including the remaining pairs and singletons, is in components.json. The early special objects were identified as ammunition through gameplay; individual weapon names have not yet been assigned from their behaviour records. The apparent repeated tanks can be checked by their numeric slots in this table/inventory without assuming a tank name from silhouette alone.

The executable retains separate 24-byte object definitions at 1926+24*i; the bank loader fills their model pointers. Equal geometry therefore does not imply equal behaviour, weapons, damage or player controls.

Across banks, data lives in separate resource pools: there is no cross-bank pointer sharing in this directory format. Shape comparison, ignoring colour and shade attributes, finds bank-30/31 Skimma geometry identical, bank-30/32 Caero geometry identical, and specials 20 and 21 geometrically identical across all three banks. Their complete colour-bearing exports are not all identical. The underground Skimma has 97 polygon commands versus 99 in banks 30/31. Drawing streams also use relative subroutine calls; their actual targets are listed, rather than treating each directory slot as a self-contained mesh blob.

Follow-up audit: empty Delphi types 14, 16, 78 and 125

These four IDs have identical eight-byte directory records, c9 0f 80 80 00 00 00 00, not merely similar-looking previews. All select pool offset 0FC9 (resource offset 1457). None occurs in the supplied Delphi map, resource 00/68.

The 11-byte header is 00 00 00 00 f0 86 ff 00 00 00 00: both damage and alternate links are zero. The complete drawing body is 5A 52 61 0D, which produces one origin vertex and returns. There are no polygon faces, lines, light discs, transforms or subroutine calls. All 256 possible state-byte values retain that same empty result.

An audit of all 154 unique city headers reachable through the bank's type directory and state links found no incoming damage/alternate links to this definition. None of the 33 special-object pointers aliases it. Decoding city/state and special drawing streams found no calls into it; a broader raw scan also found no relative call/jump candidates into its 15-byte header/body range.

The evidence therefore supports unused empty directory slots in the shipped Delphi base assets, plausibly placeholders left by content development. Their position next to particular building IDs does not establish a hangar, collision trigger or other identity. There is no concealed model or non-polygon visual component to recover from these bytes.

This is not proof that the IDs can never be introduced dynamically: the audit does not yet cover every executable path and mission-script operation. No specific gameplay purpose has been established for them. Likewise, this finding applies to bank 30; the same numeric IDs in other banks are different definitions.

Reproduce with python3 tools/inspect_empty_models.py; results are in empty-model-audit.json.