Her Interactive AVF File Format

Introduction

This page describes the AVF file format used in various Nancy Drew games by Her Interactive. In the first few titles, they were used for still and animated scenes (UI elements and overlays being the main exception, done with TGA files), while in later games were relegated to just particular still backdrops. This video format does not support audio; any relationships between video and audio are handled by the game itself.

All multi-byte numbers are in little-endian format, unless otherwise specified.

Games Examined

The following games have had their AVF files examined and figured out to the extent described below. Other games in the series are potentially different.

  1. Secrets Can Kill
  2. Stay Tuned for Danger
  3. Message in a Haunted Mansion
  4. Secret of Shadow Ranch
  5. Curse of Blackmoor Manor

Format

Header

This appears at the top of any AVF file. It identifies the file as an AVF file and defines some information about the video as a whole.

Byte Offset Size Description
0x00 15 Constant null-terminated string AVF WayneSikes (size field includes null), which can be used as a magic number.
0x0F 6 Unknown.
0x15 2 Number of entries in the frame index (see next section)
0x17 2 Width of each frame, in pixels.
0x19 2 Height of each frame in pixels.
0x1B 6 Unknown. Seems to always be 0x10 0x42 0x00 0x00 0x00 0x02

Frame Index

The frame index details offsets into this file for each frame of animation. This index starts immediately after the header. Each entry is 19 bytes long.

Layout of each index entry. Byte offsets are relative to the entry, not to the index or to the file.
Byte Offset Size Description
0x00 2 Frame number, zero-indexed.
0x02 4 Absolute offset to first byte of the frame.
0x06 4 Size of the frame data in bytes.
0x0A 3 Unknown, seems to be file-local padding. "File-local" means that this padding is (as far as has been investigated) the same for every entry in the index, but different between different AVF files.
0x0D 6 Unknown, seems to be game-local padding. "Game-local" means that this padding seems to be the same for every index entry of every AVF file in a particular game, but differs between different Nancy Drew titles.

Frame Format

An AVF's frames are "raw", in the sense that they come with no kind of header. These frames are "encrypted" (in a strenuous use of the term) and compressed in LZSS format. The following subsections go through these pieces in the order necessary to read the image data.

To summarize the below, in order to read the frame data you need to do the following:

  1. For each byte, subtract its offset modulo 256 from itself, and modulo that result by 256 (specifically the "floored division" kind of modulo1).
  2. Decompress the LZSS-compressed data.
  3. Convert the RGB555 color data to your format of choice.

Offset-based Encryption

The "encryption", for lack of a better term, involves adding offsets to each byte. Specifically, for each byte in the frame, you take its (zero-indexed!) offset from the start of the frame data, and add the least-significant byte of that offset to the byte. The stored byte is the least-significant byte of the sum. As an example, given non-encrypted frame data

00 00 00 00  00 00 00 00

The result after encryption would be

00 01 02 03  04 05 06 07

, and for original data

FF FF FF FF  FF FF FF FF

the result would be

FF 00 01 02  03 04 05 06

. Notice how the very first byte is unmodified by this operation (and in fact, every 256th byte, or every byte whose offset satisfies offset % 256 == 0).

To read the frame data, you simply invert this operation by subtracting the low-order byte of each byte's offset from that byte.

LZSS Compression

While this section won't describe LZSS compression in general, we will list the points that differ between implementations:

  • Flag bits for data chucks are stored in groups of eight bits before the next eight chunks.
    • The first chunk's flag bit is the least-significant in the group, with the next 7 chunks going in increasing significance.
    • The last group of flag bits will have "fake" flag bits if there aren't 8 data chunks left. These are safe to ignore.
  • Circular buffer is 4096 bytes, and starts filling at offset 0xFEE (not 0x000).
  • The circular buffer is initially filled with 0x20 values (ASCII spaces).

Color Format

The frame's image data after decompression is a series of 16-bit color values in RGB555 format. The most significant bit of the 16-bit value is the unused bit. as a binary representation:

0rrr rrgg gggb bbbb

Important! These 16-bit values are not little-endian, but rather big-endian. This means that the first byte of each pixel contains the unused most-significant bit.