Archive for the ‘NihAV’ Category

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.

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.

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 words about AVSS format

Thursday, December 5th, 2024

Back in the day I had a cursory glance at AVS. Out of curiosity I decided to add AVSS format support to NihAV. Despite it looking like an obscure format nobody has ever heard of, it’s well-documented. Under the name of Intel DVI (you know, Digital Video Interactive—mostly remembered for DVI ADPCM under the name IMA ADPCM).

Anyway, I’ve managed to locate just one sample containing single RTV2.1 stream so I was curious how it fares.

Well, it turned out to be the standard Indeo 2 format but for some reason actual image being down-sampled compared to what the headers claim (160×100 instead of 320×200). Nothing much to say but it was still curious to see that system from the past.

na_game_tool 0.2.5 released

Saturday, November 30th, 2024

I know that I released version 0.2.0 merely two months ago while saying it’d probably take me a year for a next release. Well, that’s still true but I wanted to make public some quality-of-life improvements as well as move some formats from NihAV (mostly Actimagine VX) so those who care have a simple way of decoding them. That is why it is a micro release.

The main reasons for release are improved AVI writer and VX decoder. The problem with my AVI writer is that it writes raw video and audio and those tend to become large—so I introduced OpenDML support in 0.2.0. But as I didn’t thought it through, I simply enabled it for videos with large frames. Now it works automatically if the file gets large enough so you should not hit size limit unless the total file size will approach 4GB.

But even if it’s a micro release I could not release it with just those two things so it introduces support for two formats reverse engineered by me recently, two formats reverse engineered by me long time ago (both are called Paco), two formats also imported from NihAV and two formats implemented after the description or code produced by others.

As always, grab it from the dedicated page if you really care.

P.S. I’ll probably keep doing what I’ve been doing so far (polishing my code, reverse engineering random formats, moving some more format from NihAV to na_game_tool—in other words, nothing to show). Meanwhile there’s still more new and exciting stuff at Librempeg.

P.P.S. Two formats were added for a rather non-technical reason: I want to have in my tool decoding support for formats for each letter of the alphabet. So far letters B, O, W, Y and Z are missing. That is why I intend to import Beam Software formats support from NihAV, maybe implement Psygnosis YOP and some Westwood format if I can’t find anything to RE instead (and I lost my chance to name PMV and RLF after Zork games). In either case 0.3.0 will still probably take half a year to a year to get enough supported formats.

Technical: NihAV repository snapshots are available over HTTPS

Monday, November 18th, 2024

Some people complained that they can’t clone NihAV code. I suspect the problem comes from the hosting provider blocking connections thanks to excessive mirroring requests and I can’t do much about it. But for the curious ones I’ve put git bundles on https://nihav.org/ which can be used as a source of cloning.

Considering the glacial pace of the project development I don’t see a reason to update them often so there’s no point in constantly checking if there’s a new version available on the server. But if you’re curious about the things my software does not support or fails to do—you’re welcome to check it out.

MPEG-4 ASP: done for now

Tuesday, October 15th, 2024

In my last post I mentioned I need to deal with MP3 in AVI and multi-threaded decoding. The former turned out to be a simple bug (I should’ve not trusted AVI header reporting 12-bit audio), and I gave up on the latter.

The main reason for that is what seems to be the main contribution of MPEG to the world of video coding, namely B-frames. While the idea behind them is reasonable (to code scene transitions or smooth movements as an interpolation between two keyframes), practical implementation brings headaches because those frames are coded in an order different from the display order (after all, you can’t interpolate between two frames if you haven’t decoded both of them). And of course it got worse in H.264 and later codecs where B-frames can reference other B-frames so you need to code information about the frame structure (references and how to update them).

And the problem with MPEG-4 ASP is that while it can have B-frames, its popularity it tied more to AVI container which lacks means to signal frame reordering (fun fact: the MPEG-4 ASP video files in MOV that I have would be perfect candidates for B-frames but lack them entirely). Of course later there other containers gaining popularity like Matroska or OGM (or even MP4 occasionally) but the gilded age seems to be tied to AVI. And of course that created difficulties.

If you have I- and P-frames only, there’s nothing to care about—but multi-threading won’t be that effective either. Newer implementations (Xvid 1.3.7 is rather fresh BTW) output B-frames as is so good luck knowing that in advance and performing reorder. In this case I see if the coded timebase is the same as the one reported by the container and simply re-assign timestamps from the bitstream (and if this does not work—well, tough luck). But there was a funnier intermediate solution with one frame containing data for both P- and B-frame and the following frame being a skip frame, so a decoder could replace it with an appropriate frame. This reminds of Indeo 4 which performed the same trick. And making that a multi-threaded decoding would be a mess requiring either saving frame data and scheduling it for later decoding or scheduling both frames and then trying to tie it to the upcoming frame decoding request. And playing back typical video takes about 20% of CPU load…

Thus I’ve committed what I find to be good enough for my needs and I shall forget about it—at least until some decoding artefact will annoy me enough. There’s more boring and unremarkable stuff I want to do on NihAV, working on this decoder reminded me that it can always be worse (or uglier).

P.S. For some reason repository cloning or updating from git.nihav.org still does not work (but the web interface is fine). I’ve reported the problem and hopefully it will be resolved soon. I suspect that the provider blocked it because of too many synchronisation requests from other sites trying to mirror the repositories. In either case I’m still grateful for the hosting.

Woes of implementing MPEG-4 ASP decoder

Friday, October 11th, 2024

So, for a last month or even more (it feels like an eternity anyway) I was mostly trying to force myself to write a MPEG-4 ASP decoder. Why? Because I still have some content around that I’d like to play with my own player. Of course I have not implemented a lot of the features (nor am I going to do that) but even what I had to deal with made me write this rant.
(more…)

Announcing na_game_tool 0.2.0

Saturday, September 14th, 2024

As hinted in my previous posts, I’ve released na_game_tool version 0.2.0. Of course it is available at its dedicated page (and now there’s a link to that page in the “Multimedia Projects” link category). Here I’d like to talk about what’s changed in it and in NihAV.

Probably the most important part is a support of a dozen new video formats—that’s the main task the tool should do after all. I’m not going to duplicate the changelog already presented at its page so those zero people who care may look there. But in the same time it’s worth nothing that I’ve move support for three obscure formats from NihAV (i.e. adapted the code from there and removed it from nihav-game crate). After all, I added support for some game formats there in the first place because I had no other place for that but I did that mainly to test whether I understood their workings right. Now as na_game_tool exists it’s much more appropriate place for such experiments. Maybe I’ll move more formats in the future but not those I care about (like Smacker or VMD) and I might still add new ones like game-specific AVI codec (like IPMA or KMVC).

Now I want to talk about less important technical details. One of the improvements I’m proud about is adding a better detection using regular expression on filename. It is described in a post about Nova Logic FMV formats and it solves a rather annoying problem of certain formats having different flavours that are impossible to detect from the file contents but the naming helps distinguish those.

Also I’ve fixed all spotted bugs in AVI output and added OpenDML support for writing large AVIs. This was needed because some Arxel Tribe games have 24-bit videos in 800×450 resolution and over a minute long so decoded raw AVIs exceed 2GB in certain cases (and intro and advertisement videos from Ur-Quan Masters approached 1GB limit, ending results in ~1.4GB AVI). Additionally I’ve added BMP format for image sequence writer (I don’t think anybody will use it but maybe it’ll come in handy one day for analysing frame palettes).

Having said that, I put the project on pause. As mentioned in the post dedicated to the first release of the tool, my intent is to make releases when it accumulates support for at least a dozen new formats (the ones moved from NihAV do not really count)—and I don’t expect to encounter enough games with undiscovered video formats in the near future. Not that I’d refuse to work on it if it’s not too annoying (see my previous post on Psygnosis games for an example of those) but it may take a year or more to collect enough formats (plus some time to reverse engineer them), so I’d rather concentrate on other things like documenting already implemented formats.

Looking at Nova Logic FMV formats

Friday, August 23rd, 2024

So there’s this company known mostly for helicopter simulators and those games use KDV format for animation. That alone is enough to make me look at the formats and what have I found?

  • the original Comanche game used a simple FMV based on PCX RLE. It was enough to just look at the file with a hex viewer to figure out all of it;
  • Armored Fist used KDV file with a different format which I still figured out after looking at it with a hex viewer and correcting my mistakes after image reconstruction somewhat started to work. The main lucky guess was that it uses 2-bit block modes for 4×4 blocks; then figuring out that block modes use 1/2/4/16-colour mode with patterns;
  • Werewolf vs. Comanche has almost the same format but for some reason Armored Fist reads only 3 colours for 4-color block (first colour is explicitly zero) so this one was more natural to RE first;
  • Comanche Gold tweaked format again, with the main change being that mode 3 means skip/fill/paint new block in the same way as the previous block, using a new pattern (for patterned modes) but keeping old colours. For this and the following format I actually had to look into the binary specification;
  • and finally Ukrainian planes simulators (F-16/MiG-29) use 24-bit version of the format above (adding cached colours, more about it below).

The main principle remained the same for all but the first KDV format: split picture into 4×4 blocks, use two-bit mode for each block, pack four modes into one byte followed by block mode data, modes being skip, fill, 2-colour pattern mode, 4-colour pattern mode and raw, colour 0 being used for the pixels that should be left unchanged (or to signal the special mode extension). The details changed though: in first two flavours raw mode was signalled by “fill with 0” mode, in last two flavours it’s “2-colour pattern with the same/zero colours” signals raw block mode and “fill with 0” means skip. An interesting feature of 24-bit format is that it introduced colour cache: if the first colour byte has top bit set, it is really an index in the cache (low 7 bits of that byte are), otherwise it is the first byte of 24-bit colour value which should be also added to the cache (it is organised as a circular buffer, so 128th value replaces 0th, 129th value replaces 1st and so on). And it still uses 0,0,0 as “leave unchanged” value (or a special flag for raw mode when 2-colour pattern uses two zero triplets).

I’ve added support for them all to na_game_tool (a couple more formats and I can make a 0.2 release before switching to a completely different activity) and I want to say some words about format detection.

As mentioned above, the main problem with the format is distinguishing the flavours. It’s very simple for the last two—Comanche Gold uses larger header and 24-bit format uses larger header, lacks palette chunks and stores frame data in K24i chunks (instead of KDVi chunks as the rest). The problem is to distinguish the first two formats without resorting to an ugly hack by trying to decode it both ways and seeing which one sticks. That’s where a new feature of na_game_tool comes into play—detecting format by regular expression. Since I know that most Werewolf vs. Comanche videos start with prefix “w_” I could simply add a rule for it, just like this:

    DetectConditions {
        demux_name: "kdv-wc",
        extensions: ".kdv",
        regex:      "bumper.kdv,w_*.kdv",
        conditions: &[CheckItem{offs: 0, cond: &CC::Str(b"xVDK")},
                      CheckItem{offs: 4, cond: &CC::Eq(Arg::U32LE(0x14))}]
    },

So files with this extension, regex and magic will be detected as this flavour of KDV while files not matching it (but with the same extension and header) will be classified as files from Armored Fist. It’s not something useful for a general multimedia converter but it’s useful for the game files—another case is CRH format that has two flavours for two different games (differing by the hardcoded height and number of bits for image offset) where you also have to rely on the file names to distinguish which one is which.

Of course I have some other changes for the upcoming na_game_tool release (maybe in September, provided I can find enough formats to add by that time) but they’re equally unexciting. Keep staying out of the loop.