BRP
- Extensions: brp
- Company: Argonaut Games
- Samples:
At least 2 games use an animation format with the extension .brp: FX Fighter and Alien Odyssey, both by Argonaut. The general container formats used in both games are similar, but differing fourccs inside may indicate that the games used different video coding algorithms (which are presently unknown). All multi-byte numbers are little endian.
File Format
BRP files consist of multi-stream chunks, where video and audio located in separate, but interleaved streams.
File begins with following 12-byte header:
dword signature - "BRPP" dword streams - number of streams in file dword unknown - unknown, but equal to 640*480
File header followed by stream headers:
dword signature - stream FOURCC dword index - logical index of the stream dword unknown1 - dword unknown2 - dword plsize - size of the following payload data byte payload[plsize] - stream-specific payload
Finally, actual data chunks follows, each one starts with chunk header:
dword index - logical index of the stream chunk belongs to dword unknown dword size - size of the chunk data byte data[size] - stream-specific chunk data
Streams
BVID Stream
The video stream. Stream header payload:
dword unknown1 dword width - width of the frame dword height - height of the frame dword unknown2
Each BVID's chunk data started with another FOURCC, indicates chunk format:
PAL8 Chunk
word start - first color to update word count - number of colors to update byte rgb[count * 3] - RGB triplets
AVCF Chunk
Intraframe 2x2 VQ, similar to one used in AVS.
ALCD Chunk
Interframe 2x2 VQ, similar to one used in AVS.
RLED, RLEF Chunks
Rle-compressed frame.
while not all output processed count = next byte of the input pixel = next byte of the input if count is zero skip (pixel) bytes of ouput else fill count of bytes of output with pixel
MAD1 Chunk
TODO
This chunk type is made up of several subchunks. Each subchunk is identified by a single byte after which the subchunk data follows. Note that the size of each subchunk is not stored, you need to correctly process each subchunk to get to the next one.
These subchunk types are currently known:
- 0x02: RLE-type algorithm
- 0x03: unknown, first two bytes are some size (of output?)
- 0x05: half-resolution frame, scaled to full resolution (e.g. for a 320x200 BRP this would be 160x100 pixels upscaled to 320x200)
- 0x06: full frame, read width*height bytes of data
- 0x07: block copy / motion vectors
- 0xFF: marks end of MAD1 chunk
0x02 algorithm
while input left get a byte from the input count = upper 2 bits of the byte skip = lower 6 bits of the byte if skip is 0x3F, skip 0x3E pixels in the output buffer else skip 'skip' pixels in the output buffer while count is greater than zero get a byte from the input as 'bitbuffer' repeat the following four times get next 2 bits from 'bitbuffer' ('bitbuffer' & 3) as 'code' do one of the following according to 'code' 0: skip the next pixel in the output buffer 1: repeat the last output pixel 2: copy the pixel from output[output_positon - width] to the output buffer 3: copy next pixel from the input buffer
BASF Stream
Audio Stream. Stream header payload:
TODO
Audio is compressed using one- or two-point DPCM. Samples chunk starts with the following header:
dword unknown1 dword unknown2 dword unknown3 dword unknown4 dword unknown5
Header continues with one or more encoded 64 samples blocks. Each 64 samples broken on two 32-sample groups, each group holds signed 4-bit delta nibbles of even and odd samples respectively (or left and right channel ones in case of stereo sound). Single 32-samples block occupy 17 bytes and have following layout:
bits 0..1 unused 2 flag - non-zero value indicates two-point DPCM 3 unused 4..7 scale - delta scale factor 8..135 nibbles[] - 32 4-bit nibbles, first nibble in bits 4..7 of the byte and second - bits 0..3, etc.
For one-point encoding each new sample calculated using this simple formula:
sample[n] = ((sample[n - 1] << 4) + (nibble << scale)) >> 4
Two-point scheme takes in to account two previous samples:
sample[n] = ((sample[n - 1] << 5) - (sample[n - 2] << 4) + (nibble << scale)) >> 4