Author Archive

NihAV: hardware-accelerated playback revisited

Monday, March 10th, 2025

Recently I’ve made a mistake of upgrading one of my laptops to systemd 24.04. I can talk about various quality of life improvements there (like brightness control not working any longer so I have to evoke xrandr instead) but it’s so useless rant that it does not deserve to be written. What is worth talking about is hardware acceleration. Previously my player on that laptop had rather unreliable playback with VA-API decoding (i.e. it worked but some videos made it too laggy); now the situation has improved—it’s reliably unusable. Additionally it seems to consume only slightly less CPU than with software decoding. So I finally looked at the way to speed it up (spoiler alert: and failed).

Conceptually it’s simple: after you decode VA-API picture you need to obtain its internal parameters with vaExportSurfaceHandle(), create an EGL picture using eglCreateImage() (or eglCreateImageKHR()), blit it onto OpenGL texture with glEGLImageTargetTexture2DOES() and you’re done. It was not so simple in practice though.

Exporting descriptors is easy, I just modified my fork of VA-API wrapper to do that and it even seemed to produce correct output. The problems started with OpenGL integration. My player uses SDL2 so I spent a lot of time trying to make it work. First of all, it’s not clear how to obtain a proper OpenGL context for the calls, then there’s this problem of it being finicky and not liking multi-threaded execution. And of course you have to load all those functions mentioned above manually (because SDL2 offers only a small subset of all possible OpenGL functions—not surprising, considering how many of those are optionally supported extensions or missing in certain profiles).

Anyway, I threw away most of my player functionality, leaving just loading an input file, decoding it and trying to display only the first frame. It ended with a segfault.

It is probably because of (poorly documented) SDL2 wrapper doing, but it can’t provide a sane OpenGL context probably. So a call to eglGetCurrentDisplay() returns either NULL or a pointer that looks like a small negative value; the same happens with eglCreateImage() (fun thing that eglGetError() returns the same value, -424 if somebody is curious); at glEGLImageTargetTexture2DOES() call it finally segfaults.

At that point I actually tried searching for some alternative crates that would allow me to create an OpenGL window and call those functions—and found none fitting the purpose. They all are either provide rather limited OpenGL subset which is enough for drawing a triangle with shaders (and probably expect you to locate and load the library with the additional functions by yourself) or even simply provide OpenGL bindings, leaving even window creation to you.

In other words, not my kind of fun. I’ll simply disable hardware acceleration for all cases there until I find a better alternative.

P.S. Vulkan is not really an option either. My hardware is too old for ANV driver (and for HASVK driver too).

Random NihAV news

Saturday, March 8th, 2025

Since I can’t do anything about the world largest countries run by over 70-year old dictators, I try to find a distraction elsewhere. It usually works only until the next time I read next. Anyway, here’s something different for a change.

With all the work on na_game_tool I’ve been mostly neglecting the original NihAV (not that it makes much difference). So I’ve tried to improve it a bit and I have something to report.

First of all, I decided to make ARMovie support more complete (after discovering that e.g. the only thing that can play Eidos Escape 122 codec is their own DOS player). So I’ve added all three video codecs with known samples (Escape 122, 124 and 130) as well as their ADPCM codec. Sadly Escape 122 description in The Wiki is somewhat unclear, so I referred to the original DOS player for it. Similarly I looked at ADPCM decoding because what libavcodec produces is not quite right (but I guess Paul can tell you more stories about all those IMA ADPCM flavours). So I guess now my project has the most complete ARMovie formats support out there. There’s only one other third-party format I’m aware of (The Complete Animation film, it may be stand-alone or encapsulated in RPL) and I might get to it eventually.

The other thing is TrueMotion S. When you think there’s nothing unknown left about it, it manages to surprise you anyway. So I was looking at Discmaster search results for potential candidates (“aviAudio” is a good format for that—sometimes it is really AVI with audio track only, sometimes it is AVI with unknown video codec) and found three .duk files that were TM1 in AVI and which could not be decoded. It turned out to use codebook 0—which is not present in the open-sourced version of the decoder. Another thing is that it does not use so-called fat deltas (i.e. larger difference values), so code zero means eight zeroes instead of an escape value. Remarkably, this is demo of The Horde game by Toys For Bob, known to employ yet another exotic version of the codec in their 3DO version of Star Control II. It makes me wonder if they had the same relationship with Duck as JVC NWC with RAD (you know, the company which released a game with Bink-b videos not found anywhere else and bundling Bink-d decoder with one of their other games—all while others started with Bink-f or later).

Hopefully I’ll be able to do more in the future, but I wanted to share these stories while they’re still fresh.

na_game_tool 0.3.0 released

Tuesday, March 4th, 2025

This is finally a release I’ve been wanting to make—with a format for each letter of the alphabet! It features about twenty new formats supported, a dozen of them being newly reverse engineered by me and the rest coming from NihAV, various open-source game engines and my older RE work. The games are diverse too, as some of them come from Argentina, Finland, France, Germany, Israel, Japan, Spain—beside the usual English-speaking countries (I’ve not tried to achieve it but that’s a nice thing too).

As usual, it’s available here (but who really cares?).

Considering that I’ve mostly exhausted the games to look at and the goals for the next release are at least twelve new formats and to support over hundred formats in total (i.e. about twelve in total), I’m not sure the next release will happen this year. I’ll find other stuff to do meanwhile.

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.

A bit on USA

Sunday, February 2nd, 2025

As usual, I don’t have to say what has been put to words in much better way by somebody else already.

At the banquet, last winter, of that organization which calls itself the Ends of the Earth Club, the chairman, a retired regular army officer of high grade, proclaimed in a loud voice, and with fervency,

“We are of the Anglo-Saxon race, and when the Anglo-Saxon wants a thing he just takes it.”

That utterance was applauded to the echo. There were perhaps seventy-five civilians present and twenty-five military and naval men. It took those people nearly two minutes to work off their stormy admiration of that great sentiment; and meanwhile the inspired prophet who had discharged it—from his liver, or his intestines, or his esophagus, or wherever he had bred it—stood there glowing and beaming and smiling, and issuing rays of happiness from every pore—rays that were so intense that they were visible, and made him look like the old-time picture in the almanac of the man who stands discharging signs of the zodiac in every direction, and so absorbed in happiness, so steeped in happiness, that he smiles and smiles, and has plainly forgotten that he is painfully and dangerously ruptured and exposed amidships, and needs sewing up right away.

The soldier man’s great utterance, interpreted by the expression which he put into it, meant, in plain English—

“The English and the Americans are thieves, highwaymen, pirates, and we are proud to be of the combination.”

[…]

The initial welcome of that strange sentiment was not an unwary betrayal, to be repented of upon reflection; and this was shown by the fact that whenever, during the rest of the evening, a speaker found that he was becoming uninteresting and wearisome, he only needed to inject that great Anglo-Saxon moral into the midst of his platitudes to start up that glad storm again. After all, it was only the human race on exhibition. It has always been a peculiarity of the human race that it keeps two sets of morals in stock—the private and real, and the public and artificial.

And here’s a link to the full writing in case you haven’t read it already.

Professional metric benders

Tuesday, January 28th, 2025

Today on “things that Kostya cannot change so he rants about them instead” is something different from the usual political or open-source political rants.

There are several groups of people whose occupation is (in theory) to evaluate certain things. So (again, in theory) you can call them the metric for those things. In practice though they rather do the opposite and try to make things conform to the valuations they give, or at least to make public perceive those things in the way that would confirm the original claims (and truth be damned!).

Of course some would see nothing wrong with it, others would even try to tell you that they’re always right because they cannot be wrong and thus only their opinion is the true one. Well, I’ll present three examples and see for yourself.

Let’s start with the most prominent example, namely lawyers. In an ideal world, lawyers are a part of judicial process, making sure that the side they support is represented fairly—and that means that judging is done according to the laws, without glaring mistakes or prejudices. In practice though lawyers tend to get associated with paid justice, meaning that quite often the outcome of the trial or litigation depends on the pay-grades of the lawyers involved instead of actual known facts (or even laws). Which sometimes leads to the fun systems as the British one with two mandatory kinds of lawyers (barristers and solicitors) and USian one—resembling quantum dynamics—where you can call lawyers elementary particles responsible for any interactions between entities (except that quantum dynamics is easier to comprehend).

Then there’s another often disliked group of people called philosophers. In theory philosophy is a way to explain the world or some of its aspects. So one would expect philosopher to be a thinker who studies the world (or part of it) and makes some conclusions about how it works and what implications that gives for the rest of the things. For instance, science may study human morals as a thing emerging in collectives and affecting interactions between members of those collectives, while philosophy may ponder how morality defines human itself and what should be considered the ideal moral. But the modern philosophers seem to work in the reverse: first they start with a conviction (quite often a small one and benefiting them directly) and work up from that to build a system that will provide an excuse for their beliefs. Of course this is unlikely a modern trend, but history preserved enough examples of real philosophers for any epoch and different countries as well—which is hard to say about the modern world.

And finally art critics. One would naïvely expect them to be people with certain tastes who appraise certain kinds of art (paintings, sculptures, books, movies, video games etc etc) and tell public their opinion about it. You may like them or not, agree with them or not, but in either case such reviews should not merely give an abstract score but also provide an explanation of what was done right, what could be improved, and what hidden qualities may make it even better than your first impression told you. There’s a reason why people still remember and quote Roger Ebert (of Chicago Sun-Times) or Scorpia (of Computer Gaming World). But the majority of the modern art critics seem to start from the premise of having to praise the reviewed product (often, apparently, out of fear for the salary and other benefits—disappointed owners of the badly-reviewed product may stop advertising in your media or provide early access to the next products they release and so on) and construct up the review leading to the goal without mentioning the actual reasons. What makes it worse is that often it’s accompanied not by the notion “if you love X and Y then this is definitely a thing for you, otherwise you may want to skip it” but rather “if you don’t like it you’re a dumb bad person”. Thanks, I still remember a bit of Soviet Union to reject it at a visceral level.

So there you have it. Of course this effect is nothing new but I felt that for some reason I need to say it, so here it is.