PIC — Palettized Image (.PIC)¶
Custom image format used for aircraft skins, HUD overlays, instruments, and
backgrounds. Three sub-formats share the same 64-byte header, identified by the
format field. Stored throughout the .LIB archives — FA_2.LIB carries the
in-game art, FA_3.LIB the encyclopedia photographs.
Tools¶
fx¶
fx pic info <file.PIC> # header and sub-format summary
fx pic unpack <file.PIC> [-o out.png] # decode to PNG
fx pic pack <file.png> [-o out.PIC] # re-encode (see Round-Trip Notes)
Other Tools¶
- GIMP — free, cross-platform; handles indexed-color and palette-aware editing well
- Paint.NET — free, Windows; simple and fast for texture touch-ups
- Photoshop
$— industry standard; use 8-bit indexed mode to stay within palette - Affinity Photo
$— one-time purchase alternative to Photoshop
File Layout¶
All multi-byte integers are little-endian.
Header (64 bytes)¶
| Offset | Size | Type | Description |
|---|---|---|---|
0x00 |
2 | u16 | format: 0=dense, 1=sparse, 0xD8FF=JPEG |
0x02 |
4 | u32 | width in pixels |
0x06 |
4 | u32 | height in pixels |
0x0A |
4 | u32 | pixels_offset (absolute file offset of pixel data) |
0x0E |
4 | u32 | pixels_size |
0x12 |
4 | u32 | palette_offset (absolute file offset of inline palette, 0 if none) |
0x16 |
4 | u32 | palette_size (0 if using system PALETTE.PAL) |
0x1A |
4 | u32 | spans_offset (format=1 only) |
0x1E |
4 | u32 | spans_size (format=1 only) |
0x22 |
4 | u32 | rowheads_offset (format=0 only) |
0x26 |
4 | u32 | rowheads_size (format=0 only; must equal 4 × height) |
0x2A |
4 | u32 | font_data_offset — offset of a trailing 1,536-byte glyph-metrics block (256 × 6-byte records); nonzero only in the *FNT/video-title PICs. Not read by FA.EXE's PIC path (offline/FNT-DLL metadata) — see Round-Trip Notes |
0x2E |
18 | u8[18] | Padding, zeroed |
Pixel Data¶
One byte per pixel — each byte is a palette index (0–255). Index 0xFF = transparent.
Palette¶
The inline palette at palette_offset (if palette_size > 0) is raw VGA 6-bit
data: palette_size / 3 RGB triplets, each channel in range 0–63.
Scale to 8-bit: actual = (stored << 2) | (stored >> 6) (rotate-left-2).
- If
palette_size == 0: the PIC uses the systemPALETTE.PAL. - A partial palette (
palette_size < 768) overrides only the firstpalette_size/3entries.
Format 0 — Dense / Texture¶
Pixel data is sequential, row-major (top to bottom, left to right):
width × height bytes.
A row-head table at rowheads_offset contains height u32 values, each the
absolute file offset of the start of that row. Must be reconstructed correctly
when encoding:
rowheads[y] = pixels_offset + y * width;
Used for aircraft skins, terrain tiles, full-screen images.
Format 1 — Sparse / Image¶
Used for HUD overlays and UI elements where most pixels are transparent.
spans_offset points to an array of 10-byte span records, terminated by
row = 0xFFFF:
| Offset | Size | Type | Description |
|---|---|---|---|
+0x00 |
2 | u16 | row index |
+0x02 |
2 | u16 | start column (inclusive) |
+0x04 |
2 | u16 | end column (inclusive) |
+0x06 |
4 | u32 | byte offset into pixels_data for this span's pixels |
Pixels per span: end - start + 1.
Format 0xD8FF — JPEG¶
The entire .PIC file content is a standard JPEG — pass it directly to a JPEG
decoder. All PIC files in FA_3.LIB are this format. These are encyclopedia
reference images (photographs, diagrams), not the 3D aircraft skin textures
(which use format 0 and carry the _ prefix in FA_2.LIB).
File Inventory¶
Filename Conventions¶
The filename prefix identifies the role of the image within the engine:
| Prefix | Role | Example |
|---|---|---|
$ |
2D weapon / ordnance cockpit icon | $AIM9M.PIC, $AGM65A.PIC |
_ |
Aircraft skin / texture (referenced by .SH TextureFile instruction) |
_A10.PIC, _KIN.PIC |
| (none) | All other images: UI, medals, backgrounds, terrain tiles | PALETTE.PIC, ATFSPLAS.PIC |
The $ and _ prefixes are engine conventions embedded in the filenames stored
in the .LIB archives. They have no effect on the file format itself.
FA_3.LIB Naming Convention (Encyclopedia Reference Images)¶
FA_3.LIB (Disc 2) contains 700+ JPEG-format PIC files used by the in-game
aircraft encyclopedia viewer. All are 512×384 pixels except the five bare-name
thumbnail files (640×480). They are never referenced by the 3D engine.
Numeric suffix <AC>_<N>.PIC (N = 0–9) — exterior photographs and action
shots of the aircraft, one image per slot. Most aircraft have 4–10 numeric
variants. The game cycles through them in the encyclopedia photo gallery.
Simple or uncommon aircraft may have only _0. Count: 678 files.
Letter suffixes:
| Suffix | Role | Count | Example |
|---|---|---|---|
_C |
Cockpit interior photograph | 48 | F14_C.PIC, F22_C.PIC |
_E |
Engine photograph or cutaway | 38 | F14_E.PIC, F22_E.PIC |
_P |
Profile diagram with callout labels | 37 | F14_P.PIC, F22_P.PIC |
_F |
Internal structure / systems cutaway (CAD/exploded view) | 16 | F22_F.PIC, F16C_F.PIC |
_F is present only on higher-profile or more technically complex aircraft:
AF1, ASTOVL, AV8, B747, CMCHE, E2000, E3, F117, F16C, F22, F260, F29, F31,
GRIPEN, RAFALE, V22.
Bare name <AC>.PIC (no suffix) — five files (A6, F15, F15J, F18C, TU160)
at 640×480 pixels. These are aircraft selection screen / hangar thumbnails. The
aircraft image is composited against a white background. All other aircraft use
the _0 exterior photo in contexts where a thumbnail is needed.
Round-Trip Notes¶
fx pic repackre-emits any PIC byte-identically from its parsed structure: the header fields are re-serialized (proving them), the 22-byte header tail at0x2A–0x3Fis carried verbatim, and every region is copied through at its recorded offset under full-coverage verification — an unaccounted or overlapping byte fails the repack rather than being silently copied. Validated against every PIC in the full install (census in tests/test_pic.cpp; 2,693 dense + 493 sparse, no JPEG PICs ship inside the LIBs).- Layout facts established by the whole-install census (inferred):
dense = header · pixels (
width×heightat 64) · row-heads (4×height) · optional 768-byte palette, withspans_offset = 0and a vestigialspans_sizethe engine never reads (commonly10×(height+1); the font PICs carry another image's stale value). Sparse = header · pixel runs · span table · optional palette, the span table 16-byte aligned over short all-zero padding. Font PICs end with a trailing 1,536-byte block (256 × 6-byte glyph records) named by header field0x2A(below), also 16-aligned. font_data_offset(0x2A) is not consumed by FA.EXE's PIC path. The.PICname-resolution and list paths (?FindPic@@YGXPAD0JJ@Z0x467C30,_MakePicList@160x4679C0) and every.PICstring consumer were traced; none dereference header offset0x2A. Consistent with runtime fonts being served by the FNT overlay DLLs, the field is offline glyph-metrics metadata (nonzero only in the 25*FNT/title PICs per the #175 census), carried verbatim through repack but never read by the base executable.fx pic pack(PNG import) always encodes as format=0 (dense) with a full inline palette. The game accepts format=0 in place of any sub-format, including JPEG originals; userepackwhen byte identity matters.- Keep image dimensions unchanged — the engine does not resize at load time.
- Pixels are quantized to the nearest palette color on re-encode; alpha < 128 maps to 0xFF.
Related¶
Formats: PAL — the system palette and the 6-bit color encoding;
LIB — container for every PIC; SH — 3D shapes reference _
textures via their TextureFile instruction.