More words on the same game format

March 14th, 2021

In my last post I said something about video compression but now I have much clearer picture in my head so I’d better document it a bit.

So it turns out bitmaps and videos share the same compression methods (just 1 and 3, 0 and 5 are video-only) and they’re even more interesting than at the first glance.

  • Compression 0 is simple stream with 8- or 16-bit opcodes with follow-up pixel data. Top two bits mean operation – skip, error, copy, repeat; next bit signals whether actual operation length is 5 or 13 bits; next bits are obviously operation size.
  • Compression 1 is tiling compression. Frame data is split into three chunks with first two starting with chunk size. First chunk is bit flags telling which 40×40 tiles in the frame are updated (this chunk can be ignored). Second chunk contains its own tile dimensions and tile metadata (one bit signals that tile is coded, 3 additional bits tell tile type). The last chunk contains tile contents in form of pixels and pattern data. Tile can be skipped, filled with single colour, filled with raw pixels, or it can be filled with 2-16 colours (with all intermediate values allowed) using 1-4 bits as index.
  • Compression 3 is LZ77-like and works on two lines at once. It reads a code using static codebook (one for intra-frames, another one for inter-frames), for code 0 is for literal (reads and output two pixel values, one for each line), all other code values are treated as copy length which is followed by offset (and in case of inter frame also direction bit telling if data should be copied from start to end or from end to start).
  • Compression 5 is virtually the same as compression 1 but tile type takes 4 bits now to fit operation 8 (copy tile from the same place in some previous frame).
    1. Indeed, this game turned out to have very original formats.

Some words on yet another game format

March 13th, 2021

In my recent post about video in Russian quests I said that the Russian adventure games I looked at used standard video formats (except for one game employing custom-modified FLIC). Well, now I can say there’s one game with an original format.

Escape from the Haunted House as its English version is known (unlike the original Russian title which translates to Spectre of the Old Park—because the goal of the game is to escape haunted house naturally) is a Myst or 7th Guest clone which means it should use animations for scene transitions and it has lots of them.

Almost all game resources are stored in a single 600 MB file in a peculiar format: unlike the usual fixed-size record pointing at actual resources, here you have 16-bit tag followed by the tag-speficic data (may be none, may be 1-128 bytes, may be some arbitrary size declared in fixed-size header). And 90% of the data are animations.

Animations by themselves are rather peculiar. First you have a header starting with " AN 0.90" (or some other floating point number), then you have a palette, chunk table and actual chunks. Audio is 5-bit DPCM (one bit for difference sign and four bits to update step index) which actually codes sample as x[i] = x[i - 1] * 2 - x[i - 2] + delta, I don’t remember seeing audio coding like this even if it’s rather simple.

Video coding employs RLE and static codebooks (depending on coding method) and some second pass to output image data in specific form. Nothing really complicated but quite original.

The problem with binary specification was the way it’s written (it’s fun to force Ghidra to decompile a function which it turns back into data because the code is self-modifying), particularly first I managed to locate a function to create those IMV data archives and only then its counterpart for loading data from archive. And after extracting data I found which type corresponds to animations and which functions handle it.

At least this all turned out to be even more original than I was asking for.

Looking at AVX format

March 9th, 2021

Since I had been looking at video files in various games I’ve decided to look at AVX format in Jack Orlando, a Polish adventure game.

The format is not very complicated but somewhat WTFy. It combines audio track compressed with IMA ADPCM and RLE-compressed video. The format is organised into chunks (audio, video, palette update). Sound easy enough?

Well, here are WTFy bits:

  • audio violates chunking structure: file starts with 32-bit word to signal this is video file, then you always have ~110kB of audio data (that starts with its own header) and only then you have video header and chunks;
  • speaking of which, video frames are packed together with audio chunks so after reading/decoding one you have audio data without the usual chunk header (you can have standalone audio chunk of course);
  • oh, and another thing—the video file header seems to list number of audio frames (which is usually several times larger than the number of video frames);
  • another fun fact about video header: it may occur several times throughout the file;
  • and another fun fact: while the format is paletted, palette can be either 24-bit (I’ve seen that only in intro) or 16-bit (all other files, which are predominantly short game over animations). And by 16-bit palette I mean 256-colour palette with actual colours represented in RGB565, I’ve never seen that before;
  • as a cherry on top of that sometimes chunks start earlier or later than you’d expect from declared size.

And if you thought video compression would be sane, think again:

  • actual data is compressed in two passes: first it groups data into coded segments in the form (1 byte - number of skipped pixels, 1 byte - number of coded pixels, 0-254 bytes - actual pixels) and then all that data is RLE coded (0xFF – escape flag after which run value and run count bytes follow, otherwise byte value should be copied as is);
  • since this is too easy it also uses pixel value 0 as skip value;
  • plus there’s a global offset in the beginning of the chunk telling from which pixel to start decoding;
  • plus there are two video chunk types that seem to differ only in one header field being missing in one of them;
  • and the actual video is 640×480 but it is coded as 1024×480 with right part of the frame being blank.

Some game formats are interesting but this one borders with being unbearably interesting.

Fixing SVQ1 decoding bug

March 6th, 2021

In the comments to the previous post a certain Paul B. pointed out that SVQ1 decoder (the one in libavcodec or mine) decodes certain files with visual artefacts. So I opened the old dreary QuickTime.qts with Ghidra to look at its contents once again (last time it was for QDesign Music details but luckily I’ve marked SVQ1 decoder functions as well).

The official binary specification turned out to have slightly different design with just one block decoding function that gets intra or inter codebooks passed to it (so intra block is essentially adding residue to zero block using intra codebooks). And, more curiously, the codec uses 16-bit values for pixels up to the very end of decoding.

As you can guess, the artefacts looking like white blocks are caused by the pixel value going out of 8-bit range. I actually hooked GDB script to mplayer2 that loads QuickTime decoder (and presents some garbage instead of proper decoded frame) to see what happens with the block showing such artefact. It turned out that pixel with the original value 0xCF got increased to 0x14F during codebook additions and the reference decoder had output it as 0x4F. So I changed clamping to discarding top bits and it works much better.

Considering that codebooks are stored as single .dll resource and block decoding function works (for performance reasons) as a chain of block modifying functions with stackless calling convention I call the results good enough and let those who want more dig there instead of me.

Videos in Russian quests – FLIC and Indeo

February 19th, 2021

It should be obvious by the fact that in ex-USSR countries there are usually “quest games” or simply “quests” instead of adventure games that Sierra games were favoured way more than anything else (while Germany seems to be more Lucas Arts land). But unlike either of these companies, Russian quest games history is much more limited both in time and quantity.

There are just a couple of games that can be called Russian quests. They appeared in 1997-1998 and remembered dearly up to this day. Almost anything coming has been forgotten and for good reasons too.

First I’d like to give a short review of the games:
Read the rest of this entry »

Done with VGM/XVD

February 18th, 2021

Since the time I first looked at XVD-related codecs I dug deeper and at one point considered implementing it all for NihAV. But every time I look at Muzip or some logic inside video decoders I lose all interest. So finally I’ve documented my finds on The Wiki and now I can forget about it and move to something else.

Some of it was easy to investigate since VGM demuxer along with Muzip CTP06/CTP07, Domen and VT2k decoders are present in Java applets that can be easily decompiled. Some like V2K-II or XVD can be easily decompiled with Ghidra and produce mostly understandable code (except for wavelet decoding part in XVD). Muzip4 and VT on the other hand have hard to follow logic. And VGM2 demuxer is available only as DirectShow splitter which is a pain to search for the COM object responsible for the demuxing itself.

Funny enough now Alaris VGPixel looks more related since VT codec has similar mode of compression. Additionally both the official player and demo programs from VGM-XVD developer site use the same trick—they put all .dlls in compressed form (the standard SZDD compression) at the end of executable, which decompresses and loads them at start.

Also it’s worth mentioning that all decoders (except for VGPixel) have the same interface via the functions UCF_InitCodec, UCF_ProcessFrame and such. Anybody interested enough can write his own program that demuxes VGM or VGM2, loads the proper decoder libraries and does something with the result. At least I’ve documented it as much as I could (or cared) so there’s some foundation to start from.

Looking at fabulous game format

February 14th, 2021

Since I need some distraction from VGM-XVD formats, I decided to look at some simple game format and somehow my eyes turned to Fable. This is a point-and-click adventure from 1996 from a studio that made only this game. Overall it could’ve been better with a better beginning, no whiplash-inducing ending and no aliens in the premise so it does not resemble a bad imitation of Might and Magic series.

Anyway, the game contains three videos: 50-second logos+opening, 3-minute intro and 50-second ending (it may be different for North American release but I’ve not seen that version). And the compression employed there turned out to be interesting.

It looks like they took PCX RLE for the inspiration but they made it more complex: depending on top bits you can have run, skip or raw copy. And raw copy is where it gets interesting. During decoding of the whole video file the raw pixel sequences are added to the special buffer which can be used later to copy pixels from. This reminds me somewhat of VPx golden frame which could be updated in some versions with fresh decoded blocks and referenced even many frames later.

And here is why I like to look at those old formats—they sometimes offer an interesting coding approach while modern codecs seem to be made from the standard blocks.

Hopefully final stupid question

February 13th, 2021

Since my previous question got a satisfying answer (even two) maybe I’ll get some answers for this question. It’s not been bugging me but it’s been with me for a long time.

First, the background. What we have:

  • there’s a significant demand for video editing software for all those content creators on various video hosting platforms;
  • there are some commercial products that got mentioned rather often (usually with complaints about their stability);
  • there are some freeware or shareware products (less mentioned but you can see them in paid advertisements) that are built on opensource technologies (many of those have libavcodec in some form, one even turned MEncoder into .dll form; I checked the programs specifically to see if they have some interesting decoders bundled with, no luck so far);
  • there are some open-source video editors as well like Cinelerra, Kdenlive or LiVES that keep existing in obscurity (AviSynth or Blender are more popular but they’re a different class of programs);
  • most of the building blocks for input/output formats support or filters are already there (and if not I’m pretty sure Paul B. Mahol can add more on request);
  • there’s a certain traffic cone shaped foundation (maybe VLC secretly stands for cône de Lübeck video) that is known for making an opensource video player that majority of people have heard of and use—on various platforms too;
  • beside the player (which can also stream and do other things) they have supported other projects (like x264 or dav1d).

So the question (or rather a tree of related questions) is: why can’t those people organise and make a popular open-source video editor? Are they not interested in a product with less then ten million potential users? Are there any principal issues in creating a video editor that I’ve not seen (I remember VLME which did not even look like a serious attempt)? Or maybe there are some ideological reasons preventing its creation?

To me it looked like it’s possible to build an opensource video editor, it should use mostly the same blocks as video player, it should have some demand and it is possible to make a popular open-source product. So why it is not done, what I’m missing in the picture?

…and silence will be the answer.

Another stupid question

February 10th, 2021

Here’s another thing that has been bothering me for some time. As we all know RDBMSes more complex than SQLite have data management that is more complex than simply writing all data into one file sequentially plus you have database users belonging to different roles with different permissions on different databases. And you’re supposed to connect it via the usual networking mechanism even if you’re running it on the same machine. And advanced features include multi-machine interaction like sharding, replication and such.

So the question is: if this all looks like a standalone operating system then why enterprise-grade RDBMS are running as applications instead of their own OSes build on some kernel to manage CPU cores, storage and network interface? And in the age of containers we don’t really need to have an app version even for legacy version, just replace the driver (or merely its settings).

But maybe like the last time I wondered why GPUs do not have raytracing, I’ll learn that it’s a trend already and I’m just oblivious to it.

A quick glance at Bink Audio

February 2nd, 2021

Since my attention was drawn to this format (and binary specification was provided as well) I’ve briefly looked at it—and a brief look should be enough.

From what I see it’s the same Bink Audio but in its own container instead of Bink. It has 24-byte header, a table of 16-bit audio block sizes and actual audio data (each frame may be prefixed with 0x99 0x99 but I’m not sure since I’ve not seen a single file in that format).

Frame header:

  • 1FCB magic;
  • one byte of version (version 2 groups audio frames together, previous one does not);
  • one byte with number of blocks per frame;
  • two-byte sampling rate;
  • four-byte variable, probably frame length in samples;
  • four-byte unknown variable, maybe suggested input buffer size?
  • four-byte unknown variable
  • four-byte variable, number of frames in seek table.

So as expected it’s nothing special.