RL2
Jump to navigation
Jump to search
PC version of the FMV-based adult game "Voyeur" developed by Entertainment Software Partners, heavily uses custom video format for the videos stored in files with exteension .rl2 This article describes only PC-version format details, no CD-i version details is known so far. In general, video is compressed using simple RLE scheme and audio is carried in raw 8-bit format.
Trivia: According to Wikipedia, this game caused ESRB rating system to be invented.
File Format
+ 0 dword Header -- "FORM" + 4 dword BackSize -- size of the background frame + 8 dword Signature -- "RLV2" or "RLV3" + C dword DataSize -- size of the data past this point *BIG-ENDIAN* + 10 dword NumFrames -- number of frames + 14 word Method -- encoding method. ignored, zero + 16 word SoundRate -- sound sample rate in some obscure format. zero means no sound + 18 word Rate -- sound sample rate in Hz + 1A word Channels -- number of sound channels + 1C word DefSoundSize -- size of the single sound chunk. see notes below + 1E word VideoBase -- initial drawing offset within 320x200 viewport + 20 dword ClrCount -- number of used colors + 24 RGB Palette[256] -- 256 RGB triplets. full 8-bit entries -- if Signature == "RLV3" AND BackSize <> 0 +324 byte BackFrame[BackSize] -- encoded background frame. ignore VideoBase during it's decoding -- +xxx dword ChunkSize[NumFrames] -- complete size of the chunk for each frame (audio+video) +yyy dword ChunkOffs[NumFrames] -- offset of the each frame chunk from the start of file +zzz dword SoundSize[NumFrames] -- size of the audio portion in the frame chunk
-- for each frame -- +xxx byte Audio[SoundSize[frame_nr] & 0xFFFF] -- raw 8-bit audio +yyy byte Video[...] -- compressed video stream
- All numbers are little-endian (except for the DataSize).
- If sound is present (SoundRate <> 0) then fps = Rate / DefSoundSize. Otherwise, fps = 11025 / 1103.
Video Decoding
The video is always encoded in 320x200 resolution. If no background frame is present, video decoding operates as follows:
repeat tag = next byte of input tag < 0x80 : paint pixel with (tag) tag = 0x80 : length = next byte of input if length is zero - finish fill next (length) bytes of output with (zero) tag > 0x80 : length = next byte of input fill next (length) bytes of output with (tag & 0x7F)
For background-frame based decoding, algorithm is slightly altered (you need to decode BackFrame using the above scheme first):
repeat tag = next byte of input tag = 0x00 : copy pixel from BackFrame tag < 0x80 : paint pixel with (tag | 0x80) tag = 0x80 : length = next byte of input if length is zero - finish copy (length) pixels from BackFrame tag > 0x80 : length = next byte of input fill next (length) bytes of output with (tag | 0x80)