Archive for the ‘Game Video’ Category

Cinepak everywhere!

Sunday, March 2nd, 2025

First of all, I’m happy to announce that I’ve finally managed to reverse engineer a format for game called Wing Nuts which means I’ve finally collected formats for the whole alphabet. So I want to implement another format that I’ve REd and I can finally release na_game_tool 0.3.0 in a week.

But what I really want to talk about is the game format itself. There are no real game videos but rather game engine data files containing various kind of data, including video frames. I could also extract PCM audio but I don’t know how to synchronise it properly so I ended up with a video-only decoder. MIDI data was yet another option that I ignored.

What is curious is the video compression format. While REing it I had constant thoughts like “hmm, it stores chunk type in a byte followed by 24-bit big-endian number, just like Cinepak” or “hmm, it uses 2×2 vectors and either scales them or combines four of them in a single 4×4 block, just like Cinepak” or “wait a minute, this bitstream format—chunk markers, flags and vectors—are exactly like Cinepak”. There are some differences from the usual Cinepak we all know though: it is a paletted format (with palette stored in a similar form before actual image data) and it has some additional chunks with codes 0x60-0x62 which seem to contain some auxiliary information used by the engine.

So seeing this shortly after CinEApak and knowing that SEGA company used slightly modified Cinepak format on its consoles, it makes me wonder is the codecs was more widely licensed and tweaked than we are aware of. That would make it even more like Duck TrueMotion (which was also widely used in game videos, on consoles as well, and with a special flavours used at least in one game).

na_game_tool: penultimate letter

Friday, February 28th, 2025

So now there’s just one letter left, hopefully it won’t take that long to find a suitable format.

Meanwhile two formats for letter ‘o’ have been added, both formats are formally from Origin.

One is FLIC-in-IFF used to store intro and ending for Ultima VII (both parts). Actually there are also fonts and speech stored there but since you need external data (plus game engine) to combine them properly I ended up simply decoding animations from those archives.

Another one is equally flimsy—System Shock movies (which are predominantly just audio tracks used probably for audio logs; also the game reminds me of Paul for some reason). What’s remarkable is that it essentially combines two different coding methods for two sizes: VGA movies are RLE-coded, SVGA movies use 4×4 tile coding with additional Huffman coding of tokens. Essentially tiles are coded using tokens representing opcodes, which may refer to 4-16 colours from the global colour table or some other operation (e.g. “skip N blocks” or “repeat previous operation” or even “fill block with these two colours”); tokens are Huffman-coded, both colours and Huffman table may be transmitted at any time. Luckily I did not have to RE it from scratch as the engine code has been open-sourced some time ago.

Just a couple more formats and I’ll be able to make 0.3.0 release at last.

And I’ve thought for another fun goal for 0.4.0: get a number of supported formats to a hundred (it would be better to hit some round number like 128 but that’s more of a milestone for the improbable 0.5.0 release). Currently I have 70-something formats listed and that will number will increase to 80 for the upcoming release for sure. Finding about eight extra formats to support is easier than finding twelve formats to RE. And to put things into perspective, librempeg lists about 270 video decoders (excluding raw formats and hardware accelerated decoding), some of them being equally incomplete, simple, or being a small variation of another decoder. So having a third of that number for game-only video formats (most of those being unique too) is a respectable feat IMO.

na_game_tool: another letter

Tuesday, February 25th, 2025

Finally I’m closer to the goal of having formats for every letter of alphabet supported in na_game_tool. Finally I’ve managed to add a format(s) starting with ‘y’.

First, I was able to locate an obscure game ported to Windows from SEGA Saturn called Yumimi Mix. The best part of is the first letter in its name and that it has some animation formats. Two and a half of them actually: there’s a companion game Dinosaur Island with its own cutscene format starting with ACUT magic, and there’s a sprite collection and animation format starting with ABLK magic that has two distinct coding modes (plus raw).

All these formats are based on the rather standard approaches used by the console: a scene is composed of (possibly several) overlaid sprites, each sprite is split into 8×8 block that belong to a global tile atlas. Both tile data and tile indices are compressed by some variants of RLE plus there are multiple palettes and commands to compose sprites and backgrounds and do some other stuff.

Since I’m not inclined to re-implement half of the game engine for that I simply ended up with a guesswork that gives acceptable results in many cases. Of course it’s far from perfect but it still better than something.

And then dexvert added MXV format to its list of unsupported formats. Since it’s used in Yo Matías game series (as well as some other games by Caimán), it was a perfect backup candidate. Of course it’s proper to call it simply mxv but I know what I’ll call it.

The format is rather simple: PCM audio and 8- or 16-bit intra frames with no/deflate/LZW compression. There’s a later iteration of the format using Vorbis audio but you should expect librempeg to support such format, not na_game_tool. So it took me just a day to RE and implement it compared to about ten day for the Yumimix formats (which are still rather incomplete).

All in all, it’s moving fine. I have some prospects on filling two other missing letters and probably by then I can finally make 0.3.0 release. Despite Paul’s suggestion I’m not going to hunt and/or invent formats with names starting with every combination of two letters of alphabet, but I’m not going to abandon the project for good either. It’s just without a clear (even if artificial) goal it’ll take more time to get enough formats for the next release.

This fortnight in na_game_tool

Saturday, February 15th, 2025

Since last time I’ve added a couple more formats:

  • finally did Dragon’s Lair (PC port) videos—it turned not as bad as I expected after Space Ace;
  • Jazz Jackrabbit 2 videos (from the decompiled decoder in Jazz² Resurrection)
  • finally implemented Xilam DERF format support (audio and video);
  • ported FutureVision FCMP and FST decoders from main NihAV;
  • freshly implemented scene format for Psychic Detective;
  • and Cyclemania video support.

If you for some unfathomable reason wonder when it will be released, I can answer: not soon.

As I mentioned before, I intend to make a release with at least a dozen of new REd formats and I’m still far from that goal. Since version 0.2.5 I’ve added support for about fifteen formats but most of them don’t count: some formats were ported from NihAV, some were based on other sources (like game engines or—for some planned additions—entries in The Wiki not based on my research), some are of poor quality and don’t really count. This means only about half of those formats is eligible—and I don’t know where to find another half (and that’s not counting other things I’d like to work on).

And there’s another small but irritating detail: so far I’ve implemented decoders for all but three letters of alphabet. Formats with names starting at ‘o’, ‘w’ and ‘y’ are still missing. Of course I can easily fill the gaps by supporting Origin Xan, Westwood VQA (or CPS) and Psygnosis YOP but I’d prefer to have something original instead of well-known formats supported elsewhere.

CinEApak

Tuesday, February 11th, 2025

First of all I’d like to blame Peter Ross for ignoring this peculiar format from his favourite company. Apparently he prefers to dig Lead instead.

Anyway, as I was scraping bottom of the barrel for FMV game formats to support in na_game_tool (and I still haven’t found good candidates for some letters, a rant about it will come later), I encountered a game called Psychic Detective.

It stores video in large .str files with some external means to signal where a segment starts and what format it has (as it may switch between 160×120 and 320×240 video and 11kHz stereo and 22kHz mono audio).

Audio is bog standard IMA ADPCM, video is while being intra-frame only is much more curious.

First of all, it employs vector quantisation with the same approach as Cinepak: there is a codebook of 2×2 blocks that get scaled to 4×4 output block, there is a codebook of 2×2 sub-blocks used to compose 4×4 output blocks, there are block mode bits telling whether it’s one- or four-vector block, and finally there are vector indices. And for larger (320×240) videos there is even a second codebook that replaces four-vector codebook after a provided line, a lot like Cinepak slices. The main difference is the structure: while Cinepak has more flexible frame structure with chunks for codebook updates, indices and such, here all data is stored in the fixed order with its sizes transmitted in the frame header.

Oh, and there’s another minor detail: frames simultaneously code 8-bit paletted and YUV video (rendered as 15- or 16-bit RGB). This is achieved by transmitting actual palette and duplicating codebook information first as palette indices and then as YUV blocks (so the decoder can decide which one to use). Also YUV to RGB conversion is simplified to look a lot like Cinepak formula as well.

I keep repeating the same thing again and again because it still holds true: those old codecs are much more interesting to look at because sometimes you find out crazy methods like this one.

This month in na_game_tool

Tuesday, January 21st, 2025

Since I’ve managed to locate a couple of FMV games I decided to make a short digest on what I’ve been working (and will keep working for a bit longer).

Ravenloft ANM

This is a predecessor of DFA, the first format implemented in libav. It is simpler but has its own peculiar decisions: interframes may be updated as a series of line segments on each column, there’s very interlaced raw picture format (for 4×4 blocks), and there’s a special picture mode which tells “decode this other delta picture N times” (though I’ve not managed to locate a sample for that).

ReadySoft scenes

This company is known for the ports of the original FMV games (you know, arcade ones using Laserdisc). I’ve managed to locate samples from three of them, namely Dragon’s Lair, Space Ace and Brain Dead 13. All three turned out to be in different formats while sharing some common traits.

I’ll start with last game and keep going in the reverse. Its videos are stored in one single BD.DAT file but are easy to extract (32-bit header size followed by the TOC with 32-bit video ID, offset and size). Videos themselves are composed of two layers—background and sprite(s). Both are updated independently and the final image is composed from them. Background data employs RLE compression, sprite employs RLE with skips. What makes it remarkable is that it not merely updates background, but also issues commands on how to scroll it around.

(Side note: this makes me think about the experimental FFV codec that used field-of-view classification to split video into layers for better compression; IIRC the technology was sold for the use in some video editor and the compression part was ditched completely. Sadly the links to it are equally dead and were not archived.)

Then there’s Space Ace which is mostly similar but uses an additional mask with sprite telling which backgrounds blocks to update and which to ignore (since they’ll be overwritten anyway). There are two additional annoying features: while the output image is 320×200, background is 328×208 for some reason (for better scrolling?); and the output is vertically interlaced. As the result it stores every fourth column in both background and sprite grouped together, so you’ll have to do some tricks to restore the proper image. Take moving into account and you’ll understand why I gave up and committed my buggy version with the words “eh, good enough”.

Dragon’s Lair seems to be the oldest of them all and uses the same RLE but with different file format. I haven’t even finished figuring out details. Maybe some other day, maybe never.

Ascon videos

This is a format used in some games by ASCARON Entertainment GmbH when it had a slightly shorter name. The format is very peculiar and I’m not talking about German chunk names like BILD or ENDE.

The earlier version codes planar YUV frames (5-bit luma and 8-bit chroma components) either in raw form or as delta with possible run for unchanged area of each component. Additionally, while some YUV codecs (Cinepak and Indeo 3 come to mind) allowed displaying their output as paletted video, here the files start with large PALT chunk specifying both the palette and a way to map 15-bit YUV value to palette index.

Then the format was extended to support 6-bit luma as well and an additional frame format that first codes offset in the reference buffer for each 8×8 block. But that’s not all, there’s a completely new frame compression method that now works in RGB and employs LZSS directly on pixels and using whole frame instead of a limited window.

I still have to figure out some details like special cases for offset wraparound but the decoder should be complete soon.


Discovering such crazy codecs is definitely more interesting than, say, watching AV2 development. I’m yet to see how the console codec (suggested by Paul) works but I don’t expect much from it.

Looking at some more exotic animation formats

Thursday, December 19th, 2024

I keep looking for old games with interesting animation formats and I’ve found another two, from Israeli companies this time.

First is the format used in Armed & Delirious. Since all of the files are in the custom archive (except for a single file with “please change CD” animation) I’m not going to support it, though I still documented it for posterity. Apparently it has two operating modes: updating some lines where each line can have its own coding mode (all are RLE variations) and updating tiles, now with each tile having its own coding mode. The only interesting thing is that tile coding operates on a sub-set of colours so it can use 3-6 bits for index. I remember some formats resorting to 16 colours and 4-bit indices but there are more variations here.

And then there’s VID format used in Soul Hunt and, apparently, some other games by the same company. It features DPCM-compressed audio and depending on version RLE- or JPEG-compressed images (and both versions are present in the game). That’s right, they use code (probably borrowed from libjpeg but I’m not sure about that) to decode data in JPEG-like format (8×8 blocks, IDCT and such) and then use some large lookup table to convert it from YUV to paletted RGB. Of course there are video codecs with such built-in functionality like Cinepak or Indeo 3 but it’s still surprising to see such thing in a random codec.

Update from December 21st: I’ve looked at JPEG-inspired coding again and I have a better understanding what it does (so maybe I’ll even be able to support it eventually):

  • there’s intra- and inter-coding, the former operates on 256×16 megablocks (consisting of 32×2 Y blocks and 16 U and V blocks each), the latter has a macroblock update mask and codes only updated macroblocks;
  • there are two quantisation matrices sets used in intra and inter mode, the binary specifications calls them “good” and “bad” factors;
  • the colour conversion code and IDCT seem to come from libjpeg while coefficient coding is their own invention;
  • coefficient coding seems to employ a rather simple set of codes: xxx0 is used for -4..4 values (codes are LSB first), xxxxxx01 is used for larger values, xxxxxx11 is used to code zero runs and xxxxxxxx 11111111 is used to code large values;
  • DC prediction is present and works the following way: decode block, dequantise it, add last DC value (and update it afterwards), scale block DC value by 32.

Initially I was discouraged by the coefficient decoding routines being implemented as state machines with computed label, so Ghidra cannot decompile it properly. I.e. it starts with “refill bit buffer” state, then moves to “decode new coefficient having 32 bits”, then it handles one of four cases listed above and moves to “decode new coefficient having 28 bits”, or “decode new coefficient having 24 bits”, or “decode new coefficient having 16 bits” state—unless it decoded the full block and saves that state to keep working from it the next time the function is called. Oh well, at least it turned out to be not that much complicated in the end.

Update from December 27th: I dug a bit more and while decoding macroblock data looks feasible, reconstructing it properly is bonkers, as the game reads quantisation matrices and scale factor for good/bad case from quants.ini text file. So I’m not so sure it’s worth the effort…

Some words about Alien Isolation CDA2

Wednesday, December 11th, 2024

Some of you might’ve heard about a Finnish adventure game called Alien Incident. Apparently it had a CD release with intro and final cutscenes re-done as an animation format. Of course that’s enough to draw my attention.

It turned out that it has several features making it one of the most advanced game formats: multiple soft subtitles and checksums for each frame. The file header is followed by the text block with subtitles in several languages that are rendered by the player over the video (and the font itself is RLE-compressed). Then there’s a table of 32-bit checksums for each frame, and only after that there’s frame size table followed by actual frame data.

Video is coded in 32×40 tiles with one of several coding modes: read full tile, update marked pixels in the tile, update 2×2 blocks in the tile, or update 4×4 blocks in the tile. That data is further compressed with slightly modified LZSS. Additionally frames carry audio data and some additional commands such as fading or setting frame duration. By default player operates on 70 or 75Hz clock and each frame is displayed for several ticks (usually 5-8). So a special command in the frame data tells player to display each frame for N ticks until further notice.

And now it is time for a rant. There is an issue uncovered by decoding these files. Both files are long (finale is over 11 minutes at 18.75 fps) and have lots of palette changes (because of both scene changes and fading)—and those two things helped uncover a problem with FFmpeg. Its AVI demuxer is the problem: it scans index, finds palette change chunks (which I explicitly mark with AVIIF_NO_TIME flag), adds them to the video stream statistics (despite the flag), concludes that video stream has significantly more frames than audio stream and switches to non-interleaved mode; in that mode it disregards actual index contents and treats palette change chunks as video data. Personally I don’t care because I have my own set of tools for decoding, transcoding or playing videos that does not have this problem, but considering that virtually every other piece of software uses libavformat for handling input data, that may pose a problem for everybody else (I can afford to not care but somebody else would have to change perfectly valid output just to work around third-party bug). This is a fun case demonstrating that monopoly is evil, even if it’s a monopoly of open-source software.

P.S. Probably it’s a good occasion to remind that librempeg exists and probably both it and you can benefit from your attention to it.

Some more game formats

Sunday, December 8th, 2024

In my recent post about na_game_tool 0.2.5 release I complained that I still miss formats starting with letters B, O, W, Y and Z. Well, after an extensive search I’ve managed to find two formats to cover some missing letters.

First is the animation format used in some DOS version of the game Baldies (it’s an RTS game released on consoles as well as on Windows and DOS—and there was even an early Amiga demo apparently). CD with DOS/Windows version employs ordinary FLIC, (floppy?) DOS version and demos used its own animation format instead. It’s rather ordinary RLE anyway in a BAL(d) file as the rest of game resources.

The second game, Los Justicieros (or Zorton Brothers, which is a much better title for my purposes) is much more interesting game. It has a format with various compression methods as well as audio chunks and palette manipulation commands (like fade to black or fade to a new palette). And the compression methods are a mix of RLE and tile-based VQ (in both senses). One method decodes picture as RLE, another one uses RLE on updates to the previous frame, third method either codes whole frame in 4×2 two-colour tiles or codes an update mask first and draws only updated tiles. The fourth method uses RLE on updates as one of the previously described methods, but instead of pixels it codes two-colour 4×4 tiles. Another fun thing is that there are (at least in the version I was able to locate) five files in this format: four of those code one still image and the fifth one codes over half an hour of all video scenes.

In either case it was a very curious format—exactly the reason why I like to examine those old games.

Another annoying game video format

Thursday, October 31st, 2024

Since I had nothing better to do and remembered about one mostly finished format, I decided to add its support to na_game_tool. The game in question is called either Cydonia: Mars – The First Manned Mission or Lightbringer (with two variations of sub-title).

The main problem is that there may be different audio and video formats inside but you cannot easily detect them. The header contains only the dimensions (which can be any as long at it’s 640×320 as the game uses hard-coded dimensions in the decoder), number of video frames (also rather pointless as it does not really affect anything) and audio present flag (the only useful information there).

First annoyance is audio format detection. The simplest solution I could devise is looking at the first audio block size and depending on its size setting the format (22050 bytes means 11kHz mono, 44100 bytes are for 22kHz mono and 88200 bytes are for 22kHz stereo). As long as you don’t encounter those extra-short files with a single audio block of different size you should be fine.

Then, video. Game demo (and maybe some versions of the full game) uses paletted video while the full game (at least the version I could find) uses 16-bit video instead. So if you discover palette chunk before video it must be a paletted format. At least the compression schemes remain the same.

And what do you know, video compression is also annoying. Both compression methods employ LZ77-based algorithm with some variations. Method 3 always decodes 640*320 bytes (or twice as much for 16-bit video) and employs an additional code for leaving data unchanged from the previous frame. Method 2 uses the same coding method (minus the “keep previous data” code) to code inter frame data of variable length (without an end code apparently). Essentially if the next 24-bit code is a valid offset (which is coded as x+y*632) then copy a block from the previous frame at the given position, otherwise decode block data (64 or 128 bytes depending on bit-depth). As I mentioned before, you don’t know compressed data size beforehand and you don’t have end-of-stream marker so you have to decode the needed amount of data as you paint the frame.

Overall, this is rather interesting video compression scheme but Paco also serves as an example of how not to design a container format. This reminds me of RoQ hack where the game engine used slightly different decoding mode if the filename was in a special list. And Nova Logic KDV but there it were different flavours in different games at least.