Breaking Eggs And Making Omelettes

Topics On Multimedia Technology and Reverse Engineering


Archives:

Solid Snake Oggs

April 4th, 2008 by Multimedia Mike

I was studying a file called vox.dat scavenged from the GameCube version of Metal Gear Solid: The Twin Snakes, the seminal, tactical, tip-toeing game starring Solid Snake. The file contains a lot of multi-lingual subtitle strings as well as the actual English speech recited along with the subtitle presentation. What format does this commercial game use? Would you believe Ogg Vorbis? The constituent audio streams are all tagged with the string “Xiph.Org libVorbis I 20020717”, which is quite old. The current version of the Xiph’s ogg123 playback tool does not decode a stream properly. Some of the data is audible, but a lot of audio chunks are skipped. FFmpeg fares a little bit better but still scrambles some audio.


Metal Gear Solid logo

Is this a case of poor backwards compatibility? Or perhaps the creators — Silicon Knights — deliberately monkeyed with the bitstream? I found that last situation a bit implausible as I assumed developers would treat this third party codec stuff as a black box. But as an experiment, let’s go back in time, courtesy of Xiph’s source control:

svn co -r {20020717} http://svn.xiph.org/trunk/ogg ogg-svn
svn co -r {20020717} http://svn.xiph.org/trunk/vorbis vorbis-svn
svn co -r {20020717} http://svn.xiph.org/trunk/vorbis-tools vorbis-tools-svn

I removed all of the related components on my system for good measure. With a little persistence and a lot of disabled options while building the tool set, I was finally able to get the components to build. Those old tools still have the same trouble with these Ogg Vorbis files:

$ oggdec mgs1-sample1.ogg
OggDec 1.0
Decoding "mgs1-sample1.ogg" to "mgs1-sample1.wav"
        [  1.5%]Warning: hole in data
        [  4.5%]Warning: hole in data
        [  6.5%]Warning: hole in data
[...]
        [127.5%]Warning: hole in data
        [130.5%]Warning: hole in data
        [132.5%]Warning: hole in data
        [134.5%]

Or maybe the tool is just extremely capable if it can decode more than 130% of the file.

I have placed three manually ripped samples in the archive; each is 512 KB. I would start ripping at offsets where I saw an ‘OggS’ marker that was followed soon after by the libVorbis ID string. If you care enough, have a look. And to what end? Isn’t it obvious? To create a “Learn English With Solid Snake And Friends” application.


Solid Snake and Liquid Snake

Learn handy, everyday phrases like, “I’m no rookie!” and “Don’t think! Shoot!” English speakers will be able to learn the same phrases in other languages, though they won’t have the benefit of pronunciation.

I’m still working out the details of the vox.dat file format. I have some things sorted out. Perhaps readers who know German, French, Italian, or Spanish, and who understand non-ASCII character encodings can answer whether these schemes fit any well-known encodings (I know that the 0x0A is a line break in the subtitle):

             53 70 72 69  63 68 20 6E  69 63 68 74      Sprich nicht
20 7A 75 20  6D 69 72 20  77 69 65 20  7A 75 0A 65   zu mir wie zu.e
69 6E 65 6D  20 41 6E 66  1F 0B 6E 67  65 72 21     inem Anf..nger!

             4C 61 20 66  65 72 6D 65  2C 20 6C 1F      La ferme, l.
09 2D 64 65  64 61 6E 73  20 21                     .-dedans !

             5A 69 74 74  6F 20 6C 1F  09 20 64 65      Zitto l.. de
6E 74 72 6F  21                                     ntro!

             1F 42 1F 42  41 20 71 75  1F 0F 20 65       .B.BA qu.. e
73 74 1F 08  73 20 65 73  70 65 72 61  6E 64 6F 21  st..s esperando!
21 0A 1F 42  1F 42 44 69  73 70 61 72  61 21 21     !..B.BDispara!!

Empirical analysis simply implies that a character 0x1F is followed immediately by a character not in the standard ASCII set.

Posted in Game Hacking | 8 Comments »

8 Responses

  1. astrange Says:

    “Sprich nicht zu mir wie zu einem Anfänger!” – Don’t talk to me like I’m a rookie!

    It might be a custom encoding; I can tell you it’s not UTF-8+, Shift_JIS, or Latin-1/2.

  2. Reimar Says:

    I’d guess they have a second font for the non-ASCII stuff and whatever is after 0x1F is the index in that second font – so I doubt there is any kind of system to it.
    0x1F seems to be “unit separator” in ASCII, but I guess they just misused it…

  3. Reimar Says:

    Btw. MPlayer ogg demuxer complains a lot about those files, so I think the container is the problem and they are not actually ogg. Maybe there is some meta-data (e.g. subtitle markers) in-between or something like that.

  4. Reimar Says:

    And another update, if you look through e.g. mgs1-sample1.ogg you will see some lines that do not fit in, i.e. they contain a lot of 0 and things like that typical for uncompressed data (which Vorbis sure is not) and do not belong to the OggS header.
    Look at e.g. offset 0x16910.
    The last 4 bytes of that block seem to indicate the length of data before the next metadata block.
    I guess this is some kind of wrapper above the Ogg level, just like UltraVox is.

  5. Diego Flameeyes Pettenò Says:

    The encoding is not anyone that iconv can recognise. Both the Italian and French phrases use the “a with grave accent” symbol (à), and no encoding that iconv supports has it encoded as 0x091F, or 0x1F09 or even 0x09.

    “Zitto là dentro!”
    “La ferme, là-dedans !”

    [both should be “Be quiet inside there!”, if my French is still good enough to read simple phrases like that]

  6. Reimar Says:

    Jup, your translation is okay, though I learned it that “La ferme” in French is not only colloquial but also quite rude, so strictly speaking it shut at least be “Shut up” instead of “Be quiet” ;-)
    Going by the given examples this is again one of the games where it is an understatement to say that the German translation sucks, even compared to the other translations which usually are bad enough. Unfortunately that’s nothing unusual though…

  7. Multimedia Mike Says:

    No, actually, you guys have been spot on with the translations so far. One of the phrases in question was a guard telling a prisoner, “Shut up in here, will ya?” So rudeness was called for. (German: “Ruhe da drinnen!”) Thanks for the metadata tips. If I study the Ogg format some more, maybe I can come up with a proper extractor.

  8. Reimar Says:

    As a little information and blatant advertisement ;-):
    http://sourceforge.net/projects/extractor-gtk (the SVN version) can now handle the vox.dat format and extract the oggs in a working way.