Breaking Eggs And Making Omelettes

Topics On Multimedia Technology and Reverse Engineering


Brute Force Dimensional Analysis

July 14th, 2010 by Multimedia Mike

I was poking at the data files of a really bad (is there any other kind?) interactive movie video game known simply by one letter: D. The Sega Saturn version of the game is comprised primarily of Sega FILM/CPK files, about which I wrote the book. The second most prolific file type bears the extension ‘.dg2’. Cursory examination of sample files revealed an apparently headerless format. Many of the video files are 288×144 in resolution. Multiplying that width by that height and then doubling it (as in, 2 bytes/pixel) yields 82944, which happens to be the size of a number of these DG2 files. Now, if only I had a tool that could take a suspected raw RGB file and convert it to a more standard image format.

Here’s the FFmpeg conversion recipe I used:

 ffmpeg -f rawvideo -pix_fmt rgb555 -s 288x144 -i raw_file -y output.png

So that covers the files that are suspected to be 288×144 in dimension. But what about other file sizes? My brute force approach was to try all possible dimensions that would yield a particular file size. The Python code for performing this operation is listed at the end of this post.

It’s interesting to view the progression as the script compresses to different sizes:

That ‘D’ is supposed to be red. So right away, we see that rgb555(le) is not the correct input format. Annoyingly, FFmpeg cannot handle rgb5[5|6]5be as a raw input format. But this little project worked well enough as a proof of concept.

If you want to toy around with these files (and I know you do), I have uploaded a selection at:

Here is my quick Python script for converting one of these files to every acceptable resolution.

Posted in Game Hacking, Python | 13 Comments »

13 Responses

  1. Reimar Says:

    Well, rgb555be/rgb565be you can get by just running on your PowerPC hardware… Also adding support for it really shouldn’t be hard, it just needs an additional swap at some point.
    Lastly, I think I mentioned it already, but I always find gimp quite useful for this kind of thing. Its raw opening method has a real-time preview while you adjust width, height and offset. I just think it supports too few input formats.

  2. Timmm Says:

    Heh, misleading title! Dimensional analysis is actually an engineering trick to work out the equations for a physical system.

  3. Multimedia Mike Says:

    @Timmm: Yep. I went for wit over accuracy this time. :-)

  4. clone2727 Says:

    I’m going to guess that the pixel format is really bgr555be. Most of the non-zero data is close to 0x8014. If you say it’s red, that would mean the red data is in bits 0-4. The highest bit is probably alpha.

  5. someone Says:

    hint: there are more effective algorithms to factorize a number (not that it mattered in this case)

  6. Anonymous Says:

    @someone: Hence, “brute force.” :-)

  7. Reimar Says:

    @someone: if you want to complain about efficiency, doing the filesize & 1 == 0 check inside the loop would be more obvious thing…
    Although I suspect it was supposed to be i & 1 == 0…
    Also the task here is not factorization but enumerating all fractions, and at least I can’t tell right now if the worst case number of fractions is below O(sqrt(n)) – if not above algorithm would even be optimal…

  8. Multimedia Mike Says:

    @Reimar: Indeed, after I copy and pasted the code into the blog post, I couldn’t understand why I wrote “filesize & 1 == 0″. But it was working so I left it.

  9. n Says:

    rgba4444 is another possibility.

  10. clone2727 Says:

    @n: From what I’ve worked with, Saturn games use bgr555be as their pixel format and in this case it’s true too (see my earlier comment).

  11. clone2727 Says:

    I wrote up a quick tool to convert some of the files to BMP, based on the file size. It works for all the samples given (and it should work for a 288×144 file, but there weren’t any samples of that). Correct color even! :)

    It can be found here:

  12. Multimedia Mike Says:

    @clone2727: Nice hustle. :-)

  13. Jakub Piotr CÅ‚apa Says:

    Mike: You may try numpy and PIL for playing with image data. With numpy you can use fast slices, bitmasks and shifting to separate the channels and then make a PIL image with numpy arrays converted to uint8 to binary strings.