Skip to main content

Hotline Miami PC game: Extract OGG Vorbis OST/soundtrack from .wad file

Quick summary

Humble Indie Bundle #8 (still available, get yours quickly!) includes seven games, most of them with (FLAC and MP3) soundtrack as dedicated downloads. With Hotline Miami, one of the bundle's most exciting games, no soundtrack is included. Well, maybe it is! :-) Friend Jonathan and I wrote a command line tool to extract the original OGG Vorbis music files from the game's .wad file today. It's free software licensed under GPL v3 or later and hosted at Github.

Superficial file format analysis

The game consists of a few files only, the biggest file is HotlineMiami_GL.wad. Using a hex viewer like od(1) you see filenames on the first page, already. However, the .wad seemed to be in a proprietary format and we could not figure it out quick enough. (If you find a way to extract all files from the archive, please comment below!) Using the strings(1) command a list of Music/*.ogg files can be found:

$ strings HotlineMiami_GL.wad | grep -Eo '^.+\.ogg'
Music/ANewMorning.ogg
Music/Crush.ogg
Music/Crystals.ogg
Music/Daisuke.ogg
Music/DeepCover.ogg
Music/ElectricDreams.ogg
Music/Flatline.ogg
Music/HorseSteppin.ogg
Music/Hotline.ogg
Music/Hydrogen.ogg
Music/InnerAnimal.ogg
Music/ItsSafeNow.ogg
Music/Knock.ogg
Music/Miami2.ogg
Music/Musikk2.ogg
Music/Paris2.ogg
Music/Perturbator.ogg
Music/Release.ogg
Music/SilverLights.ogg
Music/Static.ogg
Music/ToTheTop.ogg
Music/TurfIntro.ogg
Music/TurfMain.ogg

So we knew we were looking for OGG Vorbis content. Jonathan had the idea to just scan for any OGG Vorbis content in the file (i.e. guessing the offsets), rather than trying to understand where those Music/*.ogg file offsets where located. The OGG file format is well suited for that. Basically we just had to search for the byte sequence "OggS", extract a few bytes from the header starting at that location, do some simple math, and write a block of continues bytes to a dedicated file.

Our tool in action

Clone, compile and run:

$ make
cc -std=c99 -Wall -Wextra -pedantic   -c -o extract.o extract.c
cc   extract.o -o extract-hotline-miami-soundtrack

$ ./extract-hotline-miami-soundtrack
File "ANewMorning.ogg" (offset 324769444 to 328796370, size 4026926 bytes) extracted.
File "Crush.ogg" (offset 328796370 to 331873115, size 3076745 bytes) extracted.
File "Crystals.ogg" (offset 331873115 to 338070714, size 6197599 bytes) extracted.
File "Daisuke.ogg" (offset 338070714 to 342209815, size 4139101 bytes) extracted.
File "DeepCover.ogg" (offset 342209815 to 354220376, size 12010561 bytes) extracted.
File "ElectricDreams.ogg" (offset 354220376 to 361621106, size 7400730 bytes) extracted.
File "Flatline.ogg" (offset 361621106 to 364436799, size 2815693 bytes) extracted.
File "HorseSteppin.ogg" (offset 364436799 to 379380866, size 14944067 bytes) extracted.
File "Hotline.ogg" (offset 379380866 to 384817467, size 5436601 bytes) extracted.
File "Hydrogen.ogg" (offset 384817467 to 393673098, size 8855631 bytes) extracted.
File "InnerAnimal.ogg" (offset 393673098 to 401464171, size 7791073 bytes) extracted.
File "ItsSafeNow.ogg" (offset 401464171 to 407138611, size 5674440 bytes) extracted.
File "Knock.ogg" (offset 407138611 to 414801118, size 7662507 bytes) extracted.
File "Miami2.ogg" (offset 414801118 to 420456265, size 5655147 bytes) extracted.
File "Musikk2.ogg" (offset 420456265 to 425787691, size 5331426 bytes) extracted.
File "Paris2.ogg" (offset 425787691 to 433210181, size 7422490 bytes) extracted.
File "Perturbator.ogg" (offset 433210181 to 441536474, size 8326293 bytes) extracted.
File "Release.ogg" (offset 441536474 to 452985194, size 11448720 bytes) extracted.
File "SilverLights.ogg" (offset 452985194 to 462700814, size 9715620 bytes) extracted.
File "Static.ogg" (offset 462700814 to 464811086, size 2110272 bytes) extracted.
File "ToTheTop.ogg" (offset 464811086 to 468529275, size 3718189 bytes) extracted.
File "TurfIntro.ogg" (offset 468529275 to 472214580, size 3685305 bytes) extracted.
File "TurfMain.ogg" (offset 472214580 to 480864247, size 8649667 bytes) extracted.

While not all files seem to contain proper tags, all of them seem perfectly playable. The bitrate seems constant 224 kb/s for all, could be worse. At least to our ears, these files sound like higher quality than this "Hotline Miami Soundtrack (Full)" video on YouTube. But you don't need that anymore now anyway, right? :-) Again, the code is up here.

[EDIT]: Someone uploaded track "Daisuke" to The Infinite Jukeboxcheck it out!

[EDIT]: Our extractor inspired Andy to take it a little further and extract all files from the .wad file. Check out his code on GitHub, it's GPL 3, too.