VBM Specification by Heiko Herrmann

From Red Faction Wiki

Introduction

The VBM file format, used in Summoner and Red Faction is a very simple non-compressed bitmap animation format with mipmap support (mipmaps are used for lower detail levels). So it is a lot easier to read/generate than the ANI file format, which Volition Inc. used in Conflict/Descent: FreeSpace and its successor FreeSpace 2. VBM supports 16-bit color depth, with an optional alpha (=transparency) channel (see color formats below for details).

These specs were hacked out and written by Heiko Herrmann. They are by no means "official" and so I give no guarantee for the correctness of the information you find here. Of course I would love to get feedback when you find errors or missing information in these specs :).

File format

The file begins with a 32-byte header, directly followed by the first frame first mipmap data. If the file has more than one mipmap the second mipmap level of the first frame with half the width and half the height follows next. The second frame (with all mipmaps) starts after all mipmaps of the first frame. And so on. There is no file footer, so the file ends directly after the last mipmap of the last frame. Here are the specs:

#define COLORFORMAT_1555   0
#define COLORFORMAT_4444   1
#define COLORFORMAT_565    2

char signature[4]; //".vbm"
int unknown; //sometimes 1, sometimes 2 - not sure what it means
int width;
int height;
int color_format; //see COLORFORMAT_* constants
int fps;
int num_frames;
int num_mipmaps; //excluding the primary mipmap

for(int frame=0;frame<num_frames;frame++)
{
    for(int mipmap=0;mipmap<num_mipmaps+1;mipmap++)
    {
        unsigned char bitmapdata[width*height*2/pow(4,mipmap)]; //(*)
    }
}

(*) Note: The first mipmap always has the full width*height pixels. The second has half width * half height, so we need to divide it by 4 (=pow(4,1)). Each following has pow(4,x) pixels, since both the width and the height are always divided by 2.

The multiplication with 2 is needed because every pixel needs two bytes (see below).

Color format Each pixel needs two bytes, since they are always stored with 16-bit color depth. The format of the color depth can be one of the following (as specified in color_format):

COLORFORMAT_1555 (=0)

5 bits of color for the RG and B channels, 1 bit for alpha. Use this when you have alpha, but it's only the "on/off" variety. Pixels are either totally opaque or totally transparent. Useful largely for interface art.

 byte 0   byte 1
01234567 01234567
RRRRRGGG GGBBBBBA 

COLORFORMAT_4444 (=1)

4 bits for each RGB channel, 4 bits for alpha. Use this format when you want a full, varied alpha channel with semi-transparency.

 byte 0   byte 1
01234567 01234567
RRRRGGGG BBBBAAAA 

COLORFORMAT_565 (=2)

5 bits of alpha for the R and B channels, 6 bits for Green, and zero for alpha. Use this when the image needs no alpha transparency at all.

 byte 0   byte 1
01234567 01234567
BBBBBGGG GGGRRRRR