Converting the Missing Songs to Guitar Hero: Warriors of Rock

Since releasing my Missing Guitar Hero 5 (GH5) and Band Hero (BH) missing exports, I’ve had some questions as to how it was done. Since the files between GH5, BH, and Warriors of Rock (WoR) are all pretty similar, most of the changes involved changing the checksums that the game looks for. Both in the game files as well as the audio files. All files were then compiled into a WoR DLC file.

Checksums

I feel it would be a good idea to explain what a checksum is first. In short, checksum algorithm is an error checking tool. It derives a 32-bit hash (called a QB key) from any string fed into it and even if the input is slightly different, it produces a completely different checksum:

Image showing the difference one letter makes

All of Neversoft’s games use these checksums everywhere. Every song uses checksums to determine what animations to use, what charts belong to which songs, what scripts to use, etc. Please see this article for more info about checksums used in Neversoft games.

This means that each song uses its own checksums to look for its files. The game uses the internal name as part of the checksum, but they changed when being read as an export (for example “Mr. Roboto” is called “mrroboto” internally on the BH disc, but as a WoR dlc song, it’s “dlc638”). What that means is when porting songs from GH5 and BH, all checksums need to be changed.

The downside to checksums is that you cannot reverse engineer them, as too much data is stripped away to generate this QB key. Luckily, for every game, Neversoft decided to keep their “debug” files on-disc, including a cross-reference of most QB keys and their original strings. Using this debug file I could look at the original values on the game discs and swap them out with checksums generated using their dlc name.

So to convert a song to WoR, the following checksums needed changing (excerpt from my script):

Any string in “ids_pre” have the internal name before the string. For example “mrroboto_song_scripts” is AE80311B, which becomes 1ED80389 (“dlc638_song_scripts”)

“ids_post” have the internal name after the string (for example the checksum for “car_male_anim_struct_mrroboto” gets swapped with “car_male_anim_struct_dlc638”)

Finally, “ids_song” have the pattern “songs\{internal name}{x}” where x is the string. For example “songs\mrroboto.mid.qb” gets swapped with “songs\dlc638.mid.qb”

In addition to the internal name itself (all references to the checksum of just “mrroboto” get swapped with the checksum of “dlc638”), all the above need to be swapped too in order to get the official charts, animations, cameras, etc. to show up in WoR.

That by itself is already quite a bit to change, but it is luckily automated now. Once I did get the script working to swap these references, I didn’t even have to extract the game’s file to do so! I just needed to de-compress the files, swap all references, and put it in the LIVE file. But I wasn’t done, as the audio needs changes too.

Audio

The audio files in Neversoft games are individually encrypted using the song’s name as well. Each song has 4 audio files:

Each audio file uses the name as its encryption key*, so to get mrroboto_1 working in WoR, I first needed to decrypt the audio using “mrroboto_1” as its key, and then re-encrypt it with the key “dlc638_1” and then rename it to “adlc638_1” as all audio files in dlc start with “a”, but it’s not a part of the encryption key.

*It’s not that simple either, the audio name is used to derive the encryption key, but it’s not the key itself. I’ve included the encryption key code at the end of this post for your perusal.

LIVE file

The final part of the puzzle was to make a LIVE file that WoR would read. Luckily, Onyx does most of the work. It can create a DLC file with all the properties WoR expects. I enlisted the help of Freg, another WoR enthusiast, and he got Onyx to create a single song with 638 as the ID (Mr. Roboto was the first song I ported). Then I could replace the files and it pretty much just worked. The WoR disc has all DLC from exports defined (even the unexported ones), so the game will use the values found on-disc rather than needing to define it in the LIVE file.

In order to make a “pack” I had to modify the files inside the LIVE file:

The cmanifest file contains the details of the pack and what song IDs are included (almost like a manifest, if you will). Using my PAK tools I extracted the files and edited the QB file found inside to include all dlc ids:

This is the qb file inside the cmanifest file. Converted with my pak-extractor

Once I re-compiled this back into the manifest file, I could add all the songs to the LIVE file and the songs would show up in-game!

Other

As promised above, this is the Python code I used to generate a key:

def generate_fsb_key(to_gen):
    xor = 0xffffffff
    encstr = ""
    cycle = 32

    for i in range(0,cycle):
        ch = to_gen[i % len(to_gen)]
        crc = int(QBKey(ch), 16)
        xor = crc ^ xor

        index = xor % len(to_gen)
        encstr += to_gen[index]

    key = []

    for i in range(0, cycle - 1):
        ch = encstr[i]
        crc = int(QBKey(ch), 16)
        xor = crc ^ xor

        c = i & 0x03

        xor = xor >> c

        z = 0 # Set to 0
        for x in range(0, 32-c):
            z += (1<<x)

        xor = xor & z

        checkByte = int(hex(xor)[-2:],16)

        if checkByte == 0:
            break

        key.append(checkByte)

    key_bytes = bytearray(key)
    return key_bytes

Posted

in

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *