.VPX Documented

The Caesar .VPX picture format

Every full-screen picture in Caesar — the title, the Forum, the battle, the map of the Empire — is a .VPX file: four blocks of run-length-coded bytes that interleave into a 320 × 200 image of palette indices. The file carries no colours. The game loads a palette from a separate file before it shows each picture, and which palette goes with which picture is the part that has to be looked up.

Used by Caesar

Layout

A .VPX file is exactly four blocks back to back, with nothing before, between or after them. Each block is an 8-byte header followed by its compressed payload, and each decodes to exactly 16,000 bytes: a quarter of the picture. A file whose blocks do not end exactly where the file ends is malformed, and the decoder here rejects it rather than guessing.

There are twenty in the US build. All decode to 320 × 200, one byte per pixel.

Block header, 8 bytes, once per block

OffsetSizeTypeFieldDescription
02u16packed_sizeSize of the whole block in bytes, this header included. The next block starts that far on.
22u16decoded_sizeAlways 16000 (0x3E80) in every shipped file.
41u8fill AThe low byte of the header's third word: the byte a "fill A" command repeats.
51u8fill BThe high byte: the byte a "fill B" command repeats.
62u16field3Read by the engine, not needed to decode. Purpose not established.
8packed_size − 8bytespayloadThe command stream, read until the block has produced 16,000 bytes.

Commands

n is the low six bits of the command byte, so every run is 1 to 64 bytes long.

00nnnnnn + 1 byte
Explicit run: repeat the byte that follows, n + 1 times.
01nnnnnn
Fill A run: repeat the header's fill A byte n + 1 times.
10nnnnnn
Fill B run: repeat the header's fill B byte n + 1 times.
11nnnnnn + n + 1 bytes
Literal run: copy the next n + 1 bytes unchanged.

Putting the planes together

The four decoded blocks are not bit planes. They interleave one byte at a time: byte i of plane p (p from 0 to 3) is pixel 4i + p of the picture, read row by row. That is the memory layout of VGA's unchained 256-colour mode, where each plane holds every fourth column; the engine copies a block to the screen one plane at a time. The explanation is an inference from the sprite sheets, where the executable's blitter was read directly; the interleave itself is not.

The same layout is used by the .PL8 sprite sheets and the .VAS animations.

Which palette goes with which picture

Twenty pictures. "Definitive" means the engine's own load was read or a capture of the real screen matches; the rest are matched by eye.

EMAP2.VPX
EMAP2.P32. Definitive: matches a capture of the map screen on 63,144 of 64,000 pixels, every difference being the province markers and status text the game draws on top.
NEWFORUM.VPX
NEWFORUM.256. Definitive: the Forum capture's palette equals it in all 256 entries.
TEMPLE.VPX
TEMPLE.256. Definitive: loaded with it by the ratings screen.
WAR2.VPX, WARMESS.VPX
WAR2.256. Definitive: the battle screen, and the offer to hand a battle to the separate Cohort 2 program.
C_VITAE.VPX
SHADE.256, the interface palette. Definitive: the governor's page.
PANEL1.VPX
PANEL1.256, or PANEL1.P32: the two agree on every index the picture uses.
TITLE3.VPX
TITLE3.256. Renders the title screen correctly.
LOSEPIC.VPX, WINPIC.VPX
LOSEPIC.P32 and WINPIC.P32 respectively. By name.
IMPRLOGO.VPX, IMPRSEN.VPX
IMPRLOGO.256. By name for the first; inference for the second, the same intro sequence.
LOGO.VPX
IMPRLOGO.256. Inference: the picture uses only the 16 standard VGA colours and one grey, which that palette holds.
ROME1.VPX, ROME2.VPX
ROME1.256. The natural-looking match; an inference for ROME2, which shows the same scene.
ROME.VPX
SHADE.256. Inference: the picture uses only colours 0 to 15, which SHADE, PANEL1 and TEMPLE share.
PANEL1A.VPX to PANEL1D.VPX
Unresolved. They use high palette indices that PANEL1.256 does not hold, and no palette has been matched to them.

Sources