Moving with REing game codecs

As I’ve mentioned before, NihAV now can decode Bink2 files more or less decently. I don’t have many samples but I can decode all samples I could find from KB2f to KB2j quite well (the only exception is KB2a — there’s only one partial sample known with no indication which game uses it and no version of RAD tools understands it either).

I’ve omitted support for full-resolution Bink2 files (no samples) and reconstruction is not perfect because there’s an in-loop deblocking filter with some additional crazy functions invoked in some cases. It’s messy and does not affect actual bitstream decoding so I’m not going to work on it now. Maybe if I get some inspiration later…

Anyway, I moved to REing Discworld Noir BMV format instead. While the game is nice, it’s hard to run on any modern OS and there’s almost no hope for its engine being reimplemented. So maybe I’ll be able to re-watch cutscenes from it… I’ve figured out container and audio long time ago, video is not that easy. It seems to be an upgrade of Discworld II BMV that outputs 16-bit video but the way it’s implemented is baffling.

While locating the functions responsible for the decoding was easy, understanding them was hard. For the disassembler. No, the code was recognized fine but its flow makes even disassembler freak out. Here’s how it works:

  1. The frame decoding function reads pixel values, fills certain arrays and patches functions that return pixel values (nice start, isn’t it?) and then the real frame decoding starts;
  2. Frame decoding is done like a state machine (which complements coroutines used elsewhere in the engine) with several tables for handling 256 opcodes (or less in some cases);
  3. In result you read byte, jump to one of the labels, perform the operation, read the next opcode, jump using the same or different table;
  4. Except when it’s opcodes 00-3F, then you usually have to construct length word, perform some pixel output loop and then jump to another opcode handler which performs some operation and then jump to the address calculated by the previous operation;
  5. Of course pixel functions are some permuted array of 256 pointers to the functions of three different kinds: return fixed value (set by the decoding function in the beginning), read byte and return pixel value from the corresponding array or read new pixel value from the stream;
  6. And to make it all even better, all those operations are obviously not actual functions but small(er) chunks of assembly code that use fixed registers as arguments and they’re located both before and after decoding function “body”.

Anyway, I’ve made some progress and I reckon it will be possible to support this format in NihAV though maybe not soon enough.

11 Responses to “Moving with REing game codecs”

  1. anon says:

    full-resolution Bink2 files?
    do you mean Bink2 files that goes by 1920×1080 resolution and anything beyond that?

  2. Kostya says:

    No, 1920×1080 is nothing special. I meant files without subsampling that might be either YUV444 or even RGB.

  3. anon says:

    damn, that’s not good
    not to mention that what RAD Video Tools can say about your bink2 video file can’t even be remotely useful by this point, as in you get no information about chroma subsampling regarding said video whatsoever, it’s just “uses full y-cr-cb colorplane” or some horrendous shit like that

  4. Kostya says:

    Nah, it’s trivial if you have a sample—just decode all three planes and see if they fit either RGB or YUV.

  5. anon says:

    *thinking*

    speaking of which, can i send you some sample or…?

  6. anon says:

    why thank you
    https://www.sendspace.com/file/sp5ddv

    i used this one program for the .7z file
    https://github.com/mcmilk/7-Zip-zstd
    normal 7-Zip can’t actually grasp zstd-compressed files, so go for this program instead

    if you need any more of this let me know

  7. Kostya says:

    This is an ordinary KB2i file. And here’s how my decoder currently handles it (frame 127 of the decoded output). https://codecs.multimedia.cx/wp-content/uploads/bink2.jpg

    Anyway, Paul B. is working on Bink2 decoder for CEmpeg, I guess he’ll have to deal with an inflow of samples later so everything will be supported eventually.

  8. anon says:

    *thinking*

    well that’s gotta be something at least

  9. DrMcCoy says:

    Great work on Bink2 🙂

    Is that Bink2 decoding code public somewhere, with a GPLv3+-compatible license?

    I’m interested in it for the xoreos project, because Aspyr’s Android and iOS ports of Jade Empire use Bink2 (KB2j) for some reason instead of Bink1 (BIKi) like the Xbox and Windows versions.

    It’s not super high priority (it’s not like xoreos is going anywhere fast), but I would like to have it supported one day in the distant future.

    As for Discworld Noir, there might be hope for it within ResidualVM, the ScummVM sister project. Ages ago, somebody did start work on it, but stopped because of RL intruding. It’s still based on the Tinsel engine that powers Discworld 1 and 2. I’m certainly hoping for that to materialize some day; I love that game, and I’m a sucker for Noir-ish stuff anyway.

  10. Kostya says:

    There’s https://github.com/richardpl/FFmpeg/tree/bink2
    From what I heard it’s in a slightly worse shape but should be enough to serve as a base.
    Also pity there are no additional references to complete that VX decoder description.