- Extension: RL2
- Samples: http://samples.mplayerhq.hu/game-formats/voyeur-rl2/
The PC version of the FMV-based adult game "Voyeur", developed by Entertainment Software Partners, heavily uses this custom format for its videos. This article only describes the format version found on the PC version of the game; no CD-i version details is known so far. In general, video is compressed using a simple RLE scheme and audio is carried as uncompressed, unsigned, 8-bit PCM data.
Trivia: According to Wikipedia, this game caused ESRB rating system to be invented.
+ 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 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.
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, the algorithm is slightly altered (you need to decode BackFrame using the above scheme first):
copy pixels from background-frame until videobase is reached 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) copy pixels from background-frame until the output frame is complete