# ANIM and Q3 movies

Both extensions use the same `ANIM` container. The reference disc has two introductions and 24 campaign movies, eight for each operational warzone. Their images are 320 pixels wide, with heights of 160, 184 or 200 pixels.

The twelve-byte header is `ANIM`, then four little-endian 16-bit values: frame count, width, height and palette size. All retained files have 256 colours. Each frame starts with an eight-bit flags field and a 32-bit payload length. Flag `0x20` adds a 32-bit palette payload length before the payload itself.

The first frame supplies 768 six-bit RGB values and a complete width × height image. Later frames have flags `0x30`: palette runs and compressed image blocks. A palette update starts with a run count. Each run contains an eight-bit starting index, an eight-bit colour count, and that many RGB triplets. The original Windows renderer converts the colour components to eight bits by shifting them left twice.

The image is split into 8 × 8 blocks, traversed left to right and then downwards. Each block has a one-byte instruction:

| Opcode | Payload |
| --- | --- |
| 0 | One colour fills all 64 pixels. |
| 1 to 4 | A palette of 2, 4, 8 or 16 colours, followed by 64 indices packed into 1, 2, 3 or 4 bits each, least significant bits first. |
| 5 | Keep the previous frame's block. |
| 6 | One row mask, one pixel mask for each selected row, then the replacement pixels. |
| 7 | Eight pixel masks, then the replacement pixels. |

Row and pixel mask bits run from top to bottom and left to right, starting with the low bit. The masks precede the replacement pixels. Keeping those two streams separate is essential for decoding opcode 6 and 7.

The original `PlotWholeAnimScreen_` and `AnimUnblock_` routines provide an independent check of every indexed output frame. The palette check runs `internal_quick_set_windows_palette_registers_` and its run-list counterpart, intercepting only the final DirectDraw upload. The [verification report](native-animation-check.json) records frame counts and a SHA-256 over all decoded pixels and palettes.

## Timing

`FlipAnimScreens_` waits for 16 `fast_clock_` ticks between frames. In the Windows build, `initialise_windows_timer_` schedules a 10 ms periodic callback. That callback increments the shared tick counter; `fast_clock_` returns twice that counter, with a PIT half-tick adjustment. The intended interval is therefore 80 ms, or 12.5 frames per second. Late frames delay playback rather than being discarded. The browser uses 12.5 fps for the original speed setting.

The container carries no audio. Speech and music are started separately by the surrounding menu and campaign routines.
