Author Archive

I feel old

Sunday, April 4th, 2021

Probably it’s exactly when you start complaining about things changing you realize you’ve become old. And as you can guess this is my turn to complain about things changing.

The last tipping point for me was when I tried to update rustc from version 1.33 I’d been using. I wanted to do it mostly for three things: atomic types beside bool and usize (for the use in NihAV video player that should be written eventually), replacing now deprecated mem::uninitialized(), and being able to switch to a newer version of SDL2 bindings for the future video player (because old version depends on about 25 crates more than a newer ones).

So I tried latest-and-greatest rustc 1.51 and ran cargo clippy to see what has changed meanwhile. And beside seeing that now there’s a special macro matches!() as a convenient shorthand for checking object type to be some variant(s) I could not see anything useful because the linter spammed everything with “selected name is bad, you should change NASomething into NaSomething“. Which looks ugly and dropping the NA prefix entirely may make names too generic and collide with the standard ones. And before you tell me: I’m aware of the lint suppressor flag and that there’s a fix for it that makes it not to complain on public names. Still, I find this brain-damaged and thus I’ve settled on rustc 1.46 for now.

Then there’s an even funnier thing. I’ve discovered that crates.io (the site for navigating Rust packages) has stopped working in Firefox 52 (docs.rs still works fine—for now). Probably because of some JavaScript new feature (which is invoked inside rather large bundle) the scripts cannot be parsed and it simply gives you a cryptic message “Sorry, it looks like we were not able to load the page.” without explaining much. The problem is most likely at your side, you find it out.

My friend Luca actually wasted some time to create an issue for that and got an obvious reply that the browser is outdated and this is expected. For the record GitHub at least prints a message that the browser version is too old and not supported (yet the main functionality is still working), the same is true for WordPress instance where I’m typing this post.

So why don’t I update this four-year old browser? Because it’s painful. The browser is tied to the Linux distribution so either I should compile it myself (I tried that once with earlier Firefox, ran out of disk space and almost of swap space too; so I’m not eager to compile any browser more complex than elinks). The other alternative is updating the distribution and that is even more painful because of the drastic changes in software.

I’m not talking about desktop environments per se even if they expose the problem. I don’t care much about how the windows look like or where launch menu is located. But I do care about the programs I used to being no longer the part of the distributive or changing their interface in radical way. Simple example: for various reasons I like to have several input layouts and methods (for English, Ukrainian, Russian and Japanese language). On Ubuntu 12.04 I have keyboard layout switching between English and Ukrainian layouts (the latter can also produce Russian or Belarussian letters with AltGr) plus mozc to input Japanese (previously it was Anthy and who knows what will be the default Japanese IME in 2024). On Ubuntu 18.04 (which I use on a different machine) you can’t set it up the same way, Ukrainian layout does not have AltGr support and mozc by default outputs Latin characters with no setting or key combination to make it output kana by default (of course I can simply press kana mode change key on my Japanese keyboard—but that means connecting an external keyboard just for that). And even if my fingers are the wurst I have sausage fingers hardly hitting a correct key on the first time, I still want to perform keyboard actions using keyboard.

The sad thing is that I somewhat understand why this happens. Web sites get bloated and do not work with older browsers because of the browser war (no plural, you know The Browser) and shiny features developers are eager to try (and testing for older versions takes time and efforts better spent elsewhere—if people remember about it at all). Some programs need to be updated because of security issues (e.g. I upgraded from Ubuntu 10.04 mainly because of TLS troubles leading to programs not being able to open half of the sites over HTTPS). Some programs get replaced because the maintainer left and there’s nobody to step in. Some interfaces need to be adapted to the new reality (while Debian on Nokia smartphones is not so popular now, Ubuntu on tablets seems to be the next popular thing). And there’s GNOME and freedesktop.org which seem to be the main sources of disruptions. I can’t explain the logic by which they change things but it’s because of their view the mountpoint for network shares in the next release will probably be different from two previous places (and when you’re still using command line to access files on those shares like I do this feels annoying).

The sad thing is that all other non-toy OSes have the same problems. Windows users might still remember Windows Vista GUI affectionately and like how Windows 10 changes GUI elements time from time. *BSD seems to be more stable but they still support GNOME. macOS users might be still ashamed for their muscle memory failing them when OS update decided to reverse scroll direction. This is also why Linux kernel is still precious: it still cares about its interfaces being backward compatible so the userspace can rely on them while you can’t say the same about glibc 2.16.

And here we have it. As I said in the beginning this whining about programs and environments changing constantly mostly tells that I’ve become old. On the other hand if you think this “move fast and break things” motto is a good idea—remember who coined it and think again.

And another one weird game

Thursday, March 25th, 2021

Last time I forgot to mention another obscure Russian adventure game called either Adventure History or Sin(d)bad’s Eighth Adventure which has quite interesting selection of video in its resources.

So it has some game sprites in FLIC format (most of the sprites are in its own custom format), half of the game size is occupied by clips from Soviet movie (the one featuring the same hero) in AVI with MJPEG format, and finally logo and ending are in the custom HSA format.

HSA is video-only format that is very simple: 32 bits – video width, 32 bits – video height, then you have video frames data prefixed with 32-bit size (0 means end of file) and followed by 768 bytes of VGA palette. And yes, each video frame has palette following it. And of course each frame is compressed independently (using unmodified classic LZSS.C).

At least that’s more variety than you usually get in the games.

A brief look at various game video formats

Wednesday, March 24th, 2021

Today I’d like to sum up my experience looking at various game video formats, none really finished or worth documenting. In case you wonder I’ve not played (or plan to play) either of these games, I just found a place with some adventure games and looked at them for anything not known to me (and below is what’s left after discarding games using Cinepak, Smacker or Truemotion).

First of all, SIFF format used by Beam Software. It turns out that in their game The Dame Was Loaded has various resources in this container format but even larger ones look more like special game resources than videos (think about .RBT vs .VMD in SCI32 games). But there’s Alien Earth with a newer video compression and audio—both 16-bit now. Since I was unable to find the code that plays it, I’ve found the details by studying the files. The compression seems to remain largely the same except that pixels are 16-bit, pattern coding has changed (and the patterns are coded in the binary) and old “palette present” flag is reused to signal that fill values take one byte instead of two (for black values it’s enough).

Now let’s look at various Cyberflix games like Dust: A Tale of the Wired West or Titanic: Adventure out of Time. From what I could find the .mov files found there are similar in the structure with other kinds of resource files. And even if the game explicitly demands 256-colour video mode I could not see anything resembling a palette inside those files. My conclusion is that they’re not real video files either but rather some game scripts and graphics.

And let’s end it with The Vampire Diaries. This is another game with video files without palette. It seems to store just video frames either uncompressed or compressed with LZSS scheme. It’s not interesting enough to dig further.

I guess this is it and I should finally return to writing proper NihAV video player.

A quick look on movies for handhelds

Sunday, March 21st, 2021

In not-exactly-recent news there was a piece about some guy who decided not to listen to the advice of a director of some blockbuster and instead of going to cinema to watch it he encoded it to watch on Game Boy cartridges instead. While people doing stupid things is hardly news, it sparked a mild interest in me so I looked what are the options on underpowered hardware for storing video.

It turned out there are at least three formats for coding not just cutscenes but whole movies (or at least episodes of various series) to fit into 32MB GBA cartridge. And those three formats seem to be built on vector quantisation and they all embed video into the player program (well, the cartridge in this case does not have segments or filesystem for different resources).

  • GBA Video is probably the most famous and the most official one (there were official releases of couple dozens animated movies and cartoon series that used the format). It’s been developed by Majesco and it seems to use vector quantisation and deflate and since it checks codebook size to be 256*6, it’s most likely to be something like Cinepak using 2×2 YUV 420 codebook entries for compression. Additionally it seems to use left prediction (i.e. code pixel as a difference to the left one);
  • Caiman video codec seemed to come in two flavours, the original one coding 8×8 blocks using either four 4×4 pixel codebooks or just one scaled (that reminds me of Cinepak again for some reason, maybe because it did the same albeit using 2×2 vectors), next version of the codec introduced codebooks of different sizes and 8×8 block could be split recursively for that (also that version got motion compensation);
  • METEO is some Japanese format that seems to be the choice for the GBA enthusiasts since there’s a free encoder for it. I actually looked into it to see what it does (it’s a standalone binary about two hundred kilobytes large) and it turns out to decode input videos using standard Windows interfaces and encode frames with Cinepak encoder and write them into their own container.

All these formats make me think that if I look at other gaming consoles I can find Cinepak there as well. Let’s look what those FMV games used

Curiosity satisfied, I should move to something else.

Looking at Infogrames video format

Saturday, March 20th, 2021

Since I still have nothing better to do I keep looking at various formats in adventure games. And it turned out Prisoner of Ice has cutscenes in MUX format (that’s a stupid name in my opinion but what you can do now). IIRC there’s a newer version of Time Game that uses Smacker, maybe this game got a new release too but my interest was not in playing cutscenes but rather see how they’re packed. And the scheme turned out to be rather interesting.

Originally The Wiki said about it that it’s similar to HNM version 1 from Cryo (subtype 173 after investigating more thoroughly) and that’s all. As it turned out the ideas are very similar but the implementation details are sufficiently different (were they all inspired by the same book or code?).

So it turned out you have a format with 8-bit PCM audio and video that optionally employs simple LZ77-based scheme and small-codebook RLE. The main problem during REing was the way the code was written: where it reads nibbles it conditionally jumps into the middle of NOP instruction (that does a different thing then, isn’t x86 fun?); in other place you have self-modifying code, functions modifying three or four registers for return value and opcode tables. Still after figuring out some of those I’ve managed to decode all cutscenes from Prisoner of Ice, Time Gate and half of those from Chaos Control. The rest of the files in that game use a completely different method that I’ve not seen elsewhere.

This method 8 (I called it that because it’s signalled by frame flags defining compression method are set to 8 in this case) uses RLE over several line with opcodes by adding several pixels at the end of decoded part of some image row and some rows below. You can imagine it as each row being a piece of string or wire and commands are like “take box with red beads, put three of them on this row, two of them on next row and one of them on the following row” and you repeat that until all rows are filled. Since this method has too confusing implementation and I don’t care much about it to figure out exact details, feel free to document it yourself.

Overall, this was still an interesting experience.

Final words about Escape from Haunted House formats

Wednesday, March 17th, 2021

Since I don’t like my work to go completely to waste I decided to document the formats on a separate page in this blog.

I’m not sure these formats are that fitting to be documented in The Wiki since they’re in an archive and not standalone. But since I’m too lazy to find a proper wiki for game formats and register there I dumped it here instead.

Why I don’t consider Monkey Island games to be the best adventure games

Monday, March 15th, 2021

Disclaimer: I try to write posts mostly about multimedia stuff but some things are nagging me for a long time. So I write this to get rid of that nagging and move along with my lack of life.

First of all, I need to say that even if grew up in a land that mostly favoured Sierra games, I don’t think low of Monkey Island series (the first three games for sure). The setting is interesting and fun, the graphics was good (for the first three games at least), the music is memorable (even if iMUSE system was under-appreciated), the characters became part of the culture. I’ve played them countless times (MI1 both floppy and CD versions too) and would probably play again soon. I agree that those are very good games but there’s one thing about them that prevents me from agreeing with the majority that MI 1 and MI 2 are one of the best adventure games of all time.
(more…)

More words on the same game format

Sunday, 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

Saturday, 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

Tuesday, 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.