Help
Using the viewer
- Tour in the header walks through loading a file, playback and register inputs; it also starts on the first visit. Skip, Escape or a click outside the highlight leaves it.
- Hover over labels, buttons, table headers, instruction names and step names for a short explanation of each. The Tips toggle in the header turns these off.
- Open a
.PAN file with the button or by dropping it on the page. Load demo opens a small animation that ships with the viewer, made for it rather than taken from the game.
- Play / pause with the button or Space. ← and → step one frame, Home rewinds.
- Scrub with the slider. Every frame is recomputed from frame 0, so seeking backwards is exact.
- Frames sets how many frames the slider covers. Animations that end with
End keep animating sprites forever, so this is a viewing limit, not a property of the file. EndImmediate stops the animation early and shortens the slider.
- Speed scales the file's frame delay. 1x is the speed the game plays it at (18.2 timer ticks per second).
- Input registers write a value into a VM register at the start of a frame. The game sets registers before playing an animation to choose which sprites appear; frame 0 does the same here. Use the now button to apply a value at the current frame while paused.
- Colour 0 transparent shows colour index 0 as a checkerboard instead of black, which makes the background page visible through unpainted areas.
- In the Sprites tab, click a row to outline that sprite on the screen.
- Export WebM records a frame range as a video at the file's own frame rate, using the current input registers. Recording happens in real time, so it takes as long as playing the range. The file downloads when it finishes.
What a PAN file is
A PAN file is a self-contained animation from Sid Meier's Covert Action: a set of embedded images plus a small program that draws, moves and sequences them. Cutscenes, building interiors and character actions all use this format.
Instructions and the VM
The top-level program runs on a stack-based virtual machine with a 16-bit value stack, 51 registers (0 to 50) and one instruction pointer. Values are pushed with Push and consumed by the next instruction. The VM runs until it hits WaitForFrames, then pauses for that many frames while sprites animate. End stops the VM but sprites keep running; EndImmediate stops everything.
- SetupSprite pops step pointer, sprite index, follow index, X, Y, rate and flags, and starts a sprite in that slot.
- RemoveSprite deactivates a slot. StampSprite draws the sprite permanently into the background page at the end of the frame.
- TriggerAudio queues a sound from the game's audio table; this viewer only lists the index.
- Push Rn reads a register, PopToRegister writes one. Registers outside 0 to 50 (retail files use -1) discard the value.
- Compare*, Add, Subtract, Multiply, Divide pop two values and push a result. Arithmetic is 16-bit and wraps.
- JumpIf pops a value and jumps when it is non-zero. Jump, Call and Return control flow by absolute byte offset within the data section.
Sprites and steps
There are 50 sprite slots. Each sprite runs its own step sequence: a linear list with counter-based loops but no stack or registers. A sprite only steps on frames its speed allows: the speed is added to a credit each frame and steps run when the credit passes 255. A rate of 255 steps every frame, 128 roughly every other frame.
- DrawFrame picks the image to show from now on (255 hides the sprite). It is the only step that ends the sprite's turn for the frame.
- MoveAbsolute and MoveRelative change the position. SetSpeed and AddSpeed change the speed.
- PushCounter and JumpIfCounter form loops: the counter is decremented and the jump taken while it is non-zero.
- Restart returns to the first step with the original position and speed; Loop returns to the first step but keeps position and speed.
- Pause freezes the sprite while still drawing it; Stop deactivates it.
A sprite can follow another slot: it is drawn at the followed sprite's position plus its own setup position plus its own movement. Following is a single level deep.
Frames and pages
The engine keeps a background page and a draw page. Each frame: the VM runs until a wait, every active sprite steps, stamped sprites are copied into the background, the background is restored over the areas sprites covered last frame, then all visible sprites are drawn in slot order (higher slots on top). Colour 0 in an image is transparent. A sprite set up with non-zero flags is never erased, which retail files use for static background pieces.
The background type chooses the initial background page: the previous animation's page (this viewer starts from black), the first image in the file, or a solid colour.
Images and colours
Images are 16-colour, LZW and run-length compressed, and indexed through a 250-entry table of image IDs. The file's colour block maps each colour index to one of the 16 standard VGA colours; entry 0 is always black. Retail files map colour 5 to black as well, so magenta never shows.
Debug tabs
- Info: header fields, colour block, image table.
- Images: every embedded image, shown through the file's colour mapping.
- Instructions: the reachable instruction listing. The highlighted row is the instruction pointer; rows that ran this frame are marked.
- Steps: the reachable step listing. Sprite indices are shown next to their current step; the selected sprite's steps from this frame are marked.
- Sprites: every slot that has been set up, with its live state.
- VM state: instruction pointer, wait counter, stack, registers and audio triggered this frame.
- Warnings: anything unusual the parser or simulation encountered.