Visage Animation Format
The Visage Animation Format used in Bodyworks Voyager: Missions in Anatomy and The Lost Files of Sherlock Holmes: The Case of the Serrated Scalpel is an 8-bit 320×200 animation format used for full-screen cutscenes. The format consists of a pair of files with the same name but different extensions. The first, with .VDA extension, is the frame chunks file. It is a variant of the normal Visage Format with a slightly revised header that has its X-offset stored in two bytes, giving the format the ability to store locations anywhere on a 320×200 image. The second file, with extension .VDX, is the frame definitions file; it determines which chunks together form a whole frame.
Every frame after the first one contains only the differences between the two frames, with the rest of the data replaced by transparency (index 0xFF), to form a delta-frame. Delta-frames can be drawn over the previous frame to get the next step in the animation. However, the format does not just save these delta-frames; each delta-frame is cut up into small chunks using blob detection, and those chunks are saved as separate frames, together with their X and Y coordinates.
The video starts with one full image, and for each next frame, a bunch of these chunks are stacked together. The big advantage of the chunks system is that changes from previous frames can be reused for later ones, which is ideal for recycling small repeating loops playing in the background of an animation. The frame definitions format also has a way to paint existing chunks on new coordinates, which gives further reusability potential.
It must be noted that the RLE compression used for this format in Bodyworks Voyager makes the chunk compression somewhat obsolete; simply saving a file with RLE compression applied to the cropped delta-frames gives file sizes similar to the game's original chunked and RLE-compressed files. However, since Serrated Scalpel does not use RLE compression, the use of chunks considerably decreases the size of its cutscenes.
Frame chunks file
The frame chunks file, with extension .VDA, is a variant of the normal Visage format. The chunks inside it have the following format:
|0x00||UINT16LE||FrameWidthMinOne||Width of the current frame, minus one. Add one to get the actual frame width.|
|0x02||UINT16LE||FrameHeightMinOne||Height of the current frame, minus one. Add one to get the actual frame height.|
|0x04||UINT8||Compressed||0x00 if uncompressed, 0x02 if compressed. Compression is only used in Bodyworks Voyager, and is the Visage Format's Flag-based RLE.|
|0x05||UINT16LE||XOffset||X coordinate of the chunk on the image. Saved in two bytes to allow it to cover the full 320-pixel width.|
|0x07||UINT8||YOffset||Y coordinate of the chunk on the image. Only needs one byte to cover the 200 pixel height range.|
|0x08||BYTE||Data||The image data.|
The image data and compression handling are identical to the normal Visage format.
The file always starts with a colour palette, in normal Visage color palette format. The headers of VDA frames without compression and with both their X and Y offset set to zero are indistinguishable from those of normal Visage format frames, meaning the palette format is completely unchanged.
After the palette there should be a full 320×200 image, unless the animation is a continuation without initial frame. Note that while index 0xFF is used as transparency on the chunk images, it can appear as colour on the initial frame, and should not be treated as transparent in the final frame image.
Frame definitions file
The frame definitions file, with extension .VDX, will determine how to use the chunks to build up the frames. It is a collection of UINT16LE values that reference chunks to be painted on the current frame, with a 0xFFFF value indicating that the current frame is complete, and 0xFFFE indicating the end of the animation. If the highest bit in a chunk number value is enabled, the two values following that chunk number will be used as X and Y offsets instead of the values saved in the chunk.
Since the highest bit in the frame number UINT16LE can't be used, and 0xFFFF and 0xFFFE are restricted values and will never be interpreted as repositioned versions of frames 0x7FFF and 0x7FFE, the highest frame number that can safely be used is 0x7FFD, meaning the maximum length of a VDA cutscene is 32766 chunks.
The palette is not considered part of the chunks, and should not be counted in the indices. Index 0 should be the first actual image after the palette.
Example byte sequence:
00 00 FF FF 01 00 02 00 FF FF 03 00 04 00 FF FF 01 00 02 00 FF FF 01 80 8B 00 2F 00 05 00 FF FF FE FF
As UINT16LE values, separated per frame:
0000 FFFF 0001 0002 FFFF 0003 0004 FFFF 0001 0002 FFFF 8001 008B 002F 0005 FFFF FFFE
- Chunk 0 is the base image. Frame complete.
- Overlay chunks 1 and 2 at their normal positions. Frame complete.
- Overlay chunks 3 and 4 at their normal positions. Frame complete.
- Overlay chunks 1 and 2 again, at their normal positions. Frame complete.
- Overlay chunk 1 but at position X=139 Y=47, and chunk 5 at its normal position. Frame complete.
- End of animation.
Note that sometimes, animations are cut up into separate files. In that case, the files beyond the first one will not start with a single full 320×200 frame loaded from chunk 0, but will instead start with a collection of overlayed chunks just like any other frame. These cut-up animations should be overlayed on the final image of the previous animation to view them correctly.
Note that even the incomplete animation files will contain a palette file at the start. This is usually identical to the one in the file they are continuing from, though palette equality should not be used as test, since some continuing files do have small palette variations in their unused colour ranges.
The following tools are able to work with files in this format.
|Name||Platform||View images in this format?||Convert/export to another file/format?||Import from another file/format?||Access hidden data?||Edit metadata?||Notes|
|C&C64 File Converter||Windows||Yes||Yes||Yes||N/A||N/A||Can load the missing start frame from previous files in the folder. Contains its own chunk-saving algorithm.|