TFX Research archive

Images, sprites, animations and presentations

Use the media browser for individual resources and the presentation browser for consecutive scenes. Both work from local files. Image downloads are PNGs; animated resources have one frame atlas each, avoiding a second set of individual-frame copies.

Full-screen images and palettes

116 resources use the war signature. Each is exactly 64,772 bytes:

4 bytes:    "war "
768 bytes:  256 RGB triples, VGA DAC values 0–63
64000 bytes: 320×200 indexed pixels, ordinary row-major layout

The native loader at file offset 0xc6c84 recognises the signature. Its row conversion at 0xc6d0c reads every fourth source pixel to prepare the four VGA planes: this is a runtime conversion, not evidence that the stored bitmap is planar. Treating the source as already planar would scramble the image.

Full-screen images, ILBM artwork and animations carry their own palettes; the palette selector is hidden for these resources. The standalone palette family has 101 resources of 768 bytes. The media browser shows their 256 colours as swatches. The model viewer currently exposes the 79 palettes already named in the colours/ extraction directory. Palette association with sprite banks remains an inspection choice where the runtime binding has not been traced.

Sprite banks

39 banks have a one-byte frame count, followed by that many little-endian 16-bit absolute offsets. At each offset are one-byte half-width and height fields, then width × height indexed pixels. All offsets, dimensions and frame ends are bounds-checked against the resource. The pixel payload consists of four contiguous VGA planes, each containing every fourth column. Extraction interleaves these into row-major pixels before generating atlases or browser data. Every stored frame has a width divisible by four. Treating the payload as ordinary rows caused the repeated, horizontally compressed schematic and also misdecoded other sprite previews. All 242 frames match the original sprite blitter at 0xc0ef8, recorded in native-checks.json.

Banks include 200×200 schematic maps, HUD strips, fonts, lamps and explosion sequences. Preview palettes can be selected without changing the stored indices. Both the gallery and main preview apply the selected palette and preserve sprite proportions, with whole-pixel enlargement for small fonts and HUD strips. Downloaded sprite atlases retain greyscale index values and are labelled accordingly. Index 0 is shown transparent for inspection. This does not imply that every native sprite-drawing path uses exactly the same transparency rule.

The twelve 49,152-byte texture pages are 256×192 indexed images, established from the native sampler and isolated polygon captures. Their global/named bindings and model UVs are exposed in the texture browser and texture notes. The separate palette-bearing global_1.tmt remains an authoring-image candidate whose conversion to the raw .tm page has not been established. See cockpits.md for compiled drawing overlays, their companion bitmap and instrument artwork.

Native animation streams

40 resources have the .256 family layout:

Position Content
0 Little-endian word 256
2 Declared frame count
4 768-byte VGA DAC palette
772 Initial full-frame flag, 0 or 1
774 onward Repeated 32-bit compressed lengths and compressed frame data

The compression uses interleaved little-endian bit words and literal bytes, with bits consumed from the high end. Literal runs, backward references, a marker and an end symbol are handled by decode_media.py, translated from the native decoder at executable file offset 0xde8cc.

The first frame is either 64,000 bytes of four contiguous VGA planes, or a delta stream. Each later frame is a delta. A delta has one run count per plane; each run stores a relative skip, a word count and two bytes per copied word. Decoding preserves the previous plane contents, then interleaves the four planes into ordinary screen pixels.

The native animation setup clears its frame buffer at 0xca144/0xca632. A standalone delta-starting clip therefore starts on a black base. Atlas alpha preserves which pixels have actually been written, useful for research; it is not a claim that consecutive native clips inherit the preceding image. Presentation playback clears the canvas to black before drawing each decoded animation frame.

Declared and stored frame counts are kept separately. A few resources contain an additional record beyond the declared traversal. The media browser exposes every stored frame; presentation playback follows the declared count. The native repeat pointer starts at frame 2, rather than repeating the first frame as well.

Every one of the 1,606 stored blocks matches native x86 decompression byte for byte. Native validation records output lengths and hashes. Delta runs and plane bounds are independently checked during atlas generation.

Saved parser graphs

cdintro.par, cdfwsint.par, tfx.par and six additional CD programs are saved linked parser graphs, not plain scripts or a simple list of movie names. Their serialised structures retain unused bytes from the compiler's buffers. A generic strings scan consequently finds fragments that are not executed text.

The loader at file offset 0xb3168 establishes the following disk layout:

  1. A 16-bit variable count, then 30 bytes per variable.
  2. A 16-bit function count, then a 25-byte function record and its statements for each function.
  3. Each statement has a 13-byte node header, followed by a payload whose size depends on its type.
  4. Text-bearing statements append a 16-byte text descriptor and its length-delimited text buffer. Type-14 Ultra-choice nodes have additional choice-list descriptors; their condition and non-repeating selection behaviour is traced in the development notes. None of the nine shipped graphs uses that node type.

All nine files decode to exactly their end: 41 functions and 1,173 nodes, with no leftover data. The complete decoded graph retains node offsets, header/payload bytes, text settings and functions. Readable transcripts are available for the CD intro, Fighter Weapons School introduction and main game flow.

Animations, static images and text-only scenes are extracted as 116 contiguous visual groups, separated by control-flow/gameplay nodes. The opening CD intro and training introduction each form cohesive sequences. The campaign browser does not flatten all branches into a claim about a single playthrough: each group preserves its source function and offsets.

Text blocks referring to ^briefNNN.txt load the selected language's recovered briefing text. Player-name, callsign and score substitutions use visible placeholders. Other embedded text remains exactly as decoded. Original line breaks remain visible below the preview. The 320×200 canvas now uses captured native glyph pixels, line heights, alignment, colour and shadow settings. Ten presentation styles supply 1,104 successful glyph captures; 26 unavailable title-font character mappings are marked explicitly. All 26 select null pointers in the original style-0 table, which has only 36 non-null glyph entries for a shared 51-character map. None occurs in the recovered style-0 presentation text; this is an original font-coverage limit, not an unresolved capture failure.

Palette fades are validated against the original routines: normal fades take 40 vertical retraces, slow fades 80, and each DAC channel is floor(source * factor / count). All 240 palette uploads / 184,320 DAC values match native execution. Fade-out ends with a palette clear. The viewer applies those discrete steps at a selectable inspection refresh rate (70 Hz initially).

The text descriptor stores signed Y/X words, alignment byte 4 (left/right/centred), shadow byte 6, reveal byte 7, font byte 8 and colour byte 9. Native centring is 160-trunc(width/2)+x; right alignment is 319-width+x. Text uses authored newlines, not browser wrapping. Styles 0/7 omit two trailing pixels from their line-width calculation and styles 8/9 omit one; glyph advances retain that spacing. Style 6 also draws an extra pixel of advance after an extended glyph that its width helper does not count; the viewer retains that original spacing/centring discrepancy. Extended glyph captures include negative bearings so raised accents are retained. Eleven complete native string captures, including accented text, also validate assembled glyphs and advances pixel for pixel; the browser reconstruction is checked against their native pixel/coverage hashes. The native reveal handler uses a fast elapsed counter clamped to 1–50, one character per two accumulated ticks. The minimum increment couples it to render frequency. The viewer's nominal 27.31 characters/second is an inspection approximation, not an exact simulation of every slow-frame case.

An animation's payload word at byte 11 gives its BIOS-tick frame delay (0x46c, nominally 18.2068 Hz). Byte 13 means play until the end of a traversal, not “loop forever”; the old loop JSON field is retained for compatibility alongside the clearer play_until_end field. When that flag is clear, the native player instead uses the wait budget and may repeat frames 2 onward until it expires. Image and text wait counts are display-retrace budgets, not 18.2 Hz BIOS ticks. Static-image revealed text holds its wait budget until reveal finishes; text-only scenes do not. Full skip/input handling and campaign/menu conditions are outside this inspection player.

Native font data, fade checks and scene-music associations retain the evidence. The presentation page links directly to the locally identifiable music for each group, leaving conditional or inherited audio unassigned.

Additional CD programs and original artwork

Structural parsing identified six additional graph resources whose extracted paths were initially unnamed. Their native resource references and filename hashes recover cddeath1, cdbusted, cdcolint, cdsomint, cdyugmid and cdyugint. They cover death/court-martial sequences and campaign introductions/interludes. All are included in the presentation browser, with source paths retained. Their animation names also resolve the three previously unnamed animation resources; all 40 animations now have recovered family names.

One resource retains its original IFF ILBM form: identifier 69a71912, 125×112 pixels, eight bitplanes, ByteRun1 compression and a 256-colour RGB palette. Its transparent colour is 0. GRAB, TINY and colour-cycle chunks survive alongside the image. The decoder checks every planar row, compressed run, chunk length and final BODY consumption. Its PNG is available in the media browser; its use in the native scene flow remains unassigned.

Parser editor source leftovers

Three resources contain original parser-editor source text rather than saved binary graphs. Two previously unclassified files begin with DOS box-drawing characters: V2.4 result-script example and V2.3 mission launcher, both credited in their headers to Dave, Digital Image Design, 1992/93. The third is a 1,628-line front-end/game-flow draft extracted under the candidate name waytxt/dpop.lst (66cebd1a). Their STRIP, MISS, STAT, TEXT, labels and variable declarations provide authoring-language evidence without implying that these example scripts are selected during normal play. CP437-decoded text and original bytes are available in the audit; the recovered-source inventory links all three text exports.

The long source has 31 STRIP declarations; 26 names survive among the retail tfx.par graph's 33 functions. Retail adds dedicated ejection, promotion and UN-defeat handling, while some draft-only screens disappear. This establishes substantial shared structure without making the draft the exact source of the shipped graph. The separate short result example also jumps to an undefined LABEL2.

Comparing source captions with the nine shipped graphs finds 31 matching texts after whitespace/case normalisation. Of those, 26 also match all seven decoded layout fields exactly: X, Y, font, colour, alignment, shadow and reveal. For example, the training-schedule caption at source line 99 matches cdfwsint node 0x2da: (40,39), style 6, colour 113, centred, without shadow or reveal. This is independent authoring-text corroboration of the binary descriptor interpretation, rather than another pixel-rendering comparison.

The mission wrapper at source line 1607 is especially useful: clear redo, launch MISS %mission, call the outcome subroutine when needed, retry when redo == 1, then return. Retail retains that structure, adds an explicit outcome reset and expands outcome handling. In both, a zero miss_val can request another attempt. Elsewhere OPTS mastopts uses miss_val for the main menu selection: its meaning depends on the current host action. These sources provide readable command vocabulary and control-flow intent, while runtime values and final rules still come from the shipped graph and executable.

Floppy counterparts

A complete floppy-resource sweep preserves the unprefixed presentation programs and the floppy main game-flow graph alongside their CD counterparts. No floppy image or animation payload is missing from the reference CD. The CD prefixes identify script variants, not higher-resolution graphics; some sequences are identical and others add scenes or revise text/timing. The comparison browser exposes both instruction streams, while this presentation player retains the reference CD sequences.