The Guitar Hero 3 Bot [Obsolete!]

Software

Part 4 - Software

Please note, all software will be freely available with source. See bottom of page for links.
Also: I cannot legally (and therefore do not) provide the xen files. Ask google. I know other sites have visual representations of the 'charts' ripped from the disc, this is bascially what my cheat files are but in text format. Im not sure if I can legally distribute them. If anyone knows please contact me.

Introduction

In my oppinion, this was the part of the project that would make it successful, or deem it a waste of money. (I say this because I was fairly confident that the hardware side would work).

I'm not really sure why, but I chose Through the Fire and Flames on hard to test my work so far. I started by working out the tempo (beats per minute) which was 200 for full speed and 160 for 'Slow'.
My initial idea was to use a file in the format of #|bbbbbb where # is the beat (as a double) and the 6 b's are bits representing green-orange and strum. The file was ordered by beat with one on each line.
I manually wrote the file in notepad with the first 1200 notes of TTFAF.

My program, written in Visual Basic .NET 2008 uses the Now.Ticks value. Ticks is a number that represents the date as time of a given instance, 10000 ticks is one millisecond (I think). I used a loop and it waited for the next beat (which was converted to a measure of ticks from when the program started).

(If this doesn't make sense to you don't worry, its not really important, and I'm not the best at phrasing things when I'm in a hurry.)

Anyway...this worked, very well (as in it got a perfect 1200 note streak) but it took me about 10 hours to do those 1200 notes by going through the training mode on slower or very slow!

Ouch, now what?!

Well, obviously doing every song that way would take far, far too long. I bought GH3 for the PC a while back for custom modding the songs so, I thought if people can insert MIDI files as the 'Chart' to be played then why can't it be extracted, so I copied the files from the DATA\SONGS directory (which is where the custom songs were saved) and started to look at them in VS.NET.
After about 10 minutes I was convinced I would never work it out, so I turned to Google. After a further 40 minutes of web browsing I found a topic on ScoreHero (many thanks to the people who worked on that thread) which started with some C code on the first page, and by page 3 provided a link to 3 downloadable executables.

So, the 3 EXEs.

UnPak.exe - Extracts Mid.Qb and Qb files from the pak.xen file in the DATA\SONGS directory (but it does require DATA\PAK\dbg.pak.xen).
UnPakMidQb.exe - Extracts allsorts of files from the Mid.Qb files (but it does require DATA\PAK\dbg.pak.xen).
DumpChart.exe - Reads the files extracted from Mid.Qb and outputs in Command Prompt the Chart (I will show the format later).

TTFAF, Expert, using my newfound EXE's

Yes it was ambitious, but this is how it went:

WAIT! Quick note on the file system!

Ok, I just want to show you how I set up my filesystem so that I could easily find all the files I needed:
Please note the GH3CheatExplorer and GH3IndexGen(explained later) app I wrote relies on this structure, this can be changed in the source code.
fs
\bin
Contains the 3 exe's plus the ones I made (will be discussed later on)

\data\gh3cheat
Files converted from raw to my gh3cheat format using an app I wrote (will be discussed later on)

\data\raw
The result of running DumpChart.exe %songname%_song_%difficulty% %songname%_%difficulty%_Star > %SongName%.raw in command prompt

\data\unmidqb
Files that result from running UnPakMidQb.exe on a %songname%.mid.qb file

\data\unpak
Files that result from running UnPak.exe on a %songname%.pak.xen file

\data\xen
These are all the files from that DATA\SONGS GH3PC directory and dbg.pak.xen


Step 1 - UnPak.exe
Usage:
C:\GH3CheatSystem\bin>UnPAK.exe
GHIII PAK file extractor v1.0 by Invo
-------------------------------------

Usage: UnPAK.exe < Path to dbg.pak.xen > <.pak input file> < Output dir >


An example:
C:\GH3CheatSystem\bin>UnPAK.exe ..\data\xen\dbg.pak.xen ..\data\xen\thrufireandf
lames_song.pak.xen ..\data\unpak
GHIII PAK file extractor v1.0 by Invo
-------------------------------------

Reading the dbg.pak.xen header... Done! (1361 entries)
Preparing CRC32 cache... Done! (100082 entries cached)
Reading the input PAK file... Done! (8 entries)
Writing files:

ID: 0   Length: 841716  FileCRC:890eae52        ObjectCRC: 40797add
        File Name:      thrufireandflames.mid.qb
        Object Name:    thrufireandflames

ID: 1   Length: 72      FileCRC:6d29ac68        ObjectCRC: be3ed261
        File Name:      thrufireandflames_song_scripts.qb

ID: 2   Length: 667016  FileCRC:bb456986        ObjectCRC: bb456986
        File Name:      GH3_Singer_Male_ThruFireNFlames_1
        Object Name:    GH3_Singer_Male_ThruFireNFlames_1

ID: 3   Length: 684936  FileCRC:224c383c        ObjectCRC: 224c383c
        File Name:      GH3_Singer_Male_ThruFireNFlames_2
        Object Name:    GH3_Singer_Male_ThruFireNFlames_2

ID: 4   Length: 456968  FileCRC:554b08aa        ObjectCRC: 554b08aa
        File Name:      GH3_Singer_Male_ThruFireNFlames_3
        Object Name:    GH3_Singer_Male_ThruFireNFlames_3

ID: 5   Length: 695048  FileCRC:cb2f9d09        ObjectCRC: cb2f9d09
        File Name:      GH3_Singer_Male_ThruFireNFlames_4
        Object Name:    GH3_Singer_Male_ThruFireNFlames_4

ID: 6   Length: 271240  FileCRC:bc28ad9f        ObjectCRC: bc28ad9f
        File Name:      GH3_Singer_Male_ThruFireNFlames_5
        Object Name:    GH3_Singer_Male_ThruFireNFlames_5

ID: 7   Length: 697224  FileCRC:2521fc25        ObjectCRC: 2521fc25
        File Name:      GH3_Singer_Male_ThruFireNFlames_6
        Object Name:    GH3_Singer_Male_ThruFireNFlames_6
This generates:
GH3_Singer_Male_ThruFireNFlames_1
GH3_Singer_Male_ThruFireNFlames_2
GH3_Singer_Male_ThruFireNFlames_3
GH3_Singer_Male_ThruFireNFlames_4
GH3_Singer_Male_ThruFireNFlames_5
GH3_Singer_Male_ThruFireNFlames_6
thrufireandflames.mid.qb
thrufireandflames_song_scripts.qb

We only want thrufireandflames.mid.qb as that contains the 'charts' that we want the program to play.

Step 2 - UnPakMidQb.exe

Usage:
C:\GH3CheatSystem\bin>UnPAKMidQB.exe
GHIII MID.QB file extractor v1.0 by Invo
----------------------------------------

Usage: UnPAKMidQB.exe < Path to dbg.pak.xen > <.mid.qb input file> 

An Example:
C:\GH3CheatSystem\bin>UnPAKMidQB.exe ..\data\xen\dbg.pak.xen ..\data\unpak\thruf
ireandflames.mid.qb ..\data\unmidqb
GHIII MID.QB file extractor v1.0 by Invo
----------------------------------------

Reading the dbg.pak.xen header... Done! (1361 entries)
Preparing CRC32 cache... Done! (100082 entries cached)
Reading file (841716 Bytes)... Done!

Dumping file:

Found object at offset 0x1c:
        thrufireandflames_song_Easy
Found object at offset 0x33e4:
        thrufireandflames_song_Medium
Found object at offset 0x8978:
        thrufireandflames_song_Hard
Found object at offset 0x1093c:
        thrufireandflames_song_Expert
Found object at offset 0x1b7d4:
        thrufireandflames_Easy_Star
Found object at offset 0x1bab0:
        thrufireandflames_Medium_Star
Found object at offset 0x1bd8c:
        thrufireandflames_Hard_Star
Found object at offset 0x1c068:
        thrufireandflames_Expert_Star
Found object at offset 0x1c344:
        thrufireandflames_Easy_StarBattleMode
Found object at offset 0x1c770:
        thrufireandflames_Medium_StarBattleMode
Found object at offset 0x1cb9c:
        thrufireandflames_Hard_StarBattleMode
Found object at offset 0x1cfc8:
        thrufireandflames_Expert_StarBattleMode
Found object at offset 0x1d3f4:
        thrufireandflames_song_rhythm_Easy
Found object at offset 0x1d414:
        thrufireandflames_song_rhythm_Medium
Found object at offset 0x1d434:
        thrufireandflames_song_rhythm_Hard
Found object at offset 0x1d454:
        thrufireandflames_song_rhythm_Expert
Found object at offset 0x1d474:
        thrufireandflames_rhythm_Easy_Star
Found object at offset 0x1d494:
        thrufireandflames_rhythm_Medium_Star
Found object at offset 0x1d4b4:
        thrufireandflames_rhythm_Hard_Star
Found object at offset 0x1d4d4:
        thrufireandflames_rhythm_Expert_Star
Found object at offset 0x1d4f4:
        thrufireandflames_rhythm_Easy_StarBattleMode
Found object at offset 0x1d514:
        thrufireandflames_rhythm_Medium_StarBattleMode
Found object at offset 0x1d534:
        thrufireandflames_rhythm_Hard_StarBattleMode
Found object at offset 0x1d554:
        thrufireandflames_rhythm_Expert_StarBattleMode
Found object at offset 0x1d574:
        thrufireandflames_song_guitarcoop_Easy
Found object at offset 0x2099c:
        thrufireandflames_song_guitarcoop_Medium
Found object at offset 0x25e40:
        thrufireandflames_song_guitarcoop_Hard
Found object at offset 0x2dcf0:
        thrufireandflames_song_guitarcoop_Expert
Found object at offset 0x38534:
        thrufireandflames_guitarcoop_Easy_Star
Found object at offset 0x386c0:
        thrufireandflames_guitarcoop_Medium_Star
Found object at offset 0x3884c:
        thrufireandflames_guitarcoop_Hard_Star
Found object at offset 0x389d8:
        thrufireandflames_guitarcoop_Expert_Star
Found object at offset 0x38b64:
        thrufireandflames_guitarcoop_Easy_StarBattleMode
Found object at offset 0x38b84:
        thrufireandflames_guitarcoop_Medium_StarBattleMode
Found object at offset 0x38ba4:
        thrufireandflames_guitarcoop_Hard_StarBattleMode
Found object at offset 0x38bc4:
        thrufireandflames_guitarcoop_Expert_StarBattleMode
Found object at offset 0x38be4:
        thrufireandflames_song_rhythmcoop_Easy
Found object at offset 0x3bb80:
        thrufireandflames_song_rhythmcoop_Medium
Found object at offset 0x40868:
        thrufireandflames_song_rhythmcoop_Hard
Found object at offset 0x47d70:
        thrufireandflames_song_rhythmcoop_Expert
Found object at offset 0x515f4:
        thrufireandflames_rhythmcoop_Easy_Star
Found object at offset 0x51780:
        thrufireandflames_rhythmcoop_Medium_Star
Found object at offset 0x5190c:
        thrufireandflames_rhythmcoop_Hard_Star
Found object at offset 0x51a98:
        thrufireandflames_rhythmcoop_Expert_Star
Found object at offset 0x51c24:
        thrufireandflames_rhythmcoop_Easy_StarBattleMode
Found object at offset 0x51c44:
        thrufireandflames_rhythmcoop_Medium_StarBattleMode
Found object at offset 0x51c64:
        thrufireandflames_rhythmcoop_Hard_StarBattleMode
Found object at offset 0x51c84:
        thrufireandflames_rhythmcoop_Expert_StarBattleMode
Found object at offset 0x51ca4:
        thrufireandflames_FaceOffP1
Found object at offset 0x52474:
        thrufireandflames_FaceOffP2
Found object at offset 0x52c8c:
        thrufireandflames_BossBattleP1
Found object at offset 0x52cac:
        thrufireandflames_BossBattleP2
Found object at offset 0x52ccc:
        thrufireandflames_timesig
Found object at offset 0x52d04:
        thrufireandflames_fretbars
Found object at offset 0x543c4:
        thrufireandflames_markers
Found object at offset 0x54964:
        thrufireandflames_scripts_notes
Found object at offset 0x54984:
        thrufireandflames_anim_notes
Found object at offset 0x6d2d8:
        thrufireandflames_triggers_notes
Found object at offset 0x6d2f8:
        thrufireandflames_cameras_notes
Found object at offset 0x6dd28:
        thrufireandflames_lightshow_notes
Found object at offset 0x85e10:
        thrufireandflames_crowd_notes
Found object at offset 0x8607c:
        thrufireandflames_drums_notes
Found object at offset 0xcb910:
        thrufireandflames_performance_notes
Found object at offset 0xcb9d8:
        thrufireandflames_scripts
Found object at offset 0xcba50:
        thrufireandflames_anim
Found object at offset 0xcba70:
        thrufireandflames_triggers
Found object at offset 0xcba90:
        thrufireandflames_cameras
Found object at offset 0xcbab0:
        thrufireandflames_lightshow
Found object at offset 0xcc550:
        thrufireandflames_crowd
Found object at offset 0xcc570:
        thrufireandflames_drums
Found object at offset 0xcc590:
        thrufireandflames_performance

To get the 'charts' for a single player song from these files we need thrufireandflames_song_Expert and thrufireandflames_Expert_Star as these are what DumpChart.exe requires.
You can get it from co-op songs, look for guitarcoop and rhythmcoop.

DumpChart.exe
Usage:
C:\GH3CheatSystem\bin>DumpChart.exe
GHIII chart extractor v1.0 by Invo
----------------------------------

Usage: DumpChart.exe < notes input file > < star power input file >

An Example:
C:\GH3CheatSystem\bin>DumpChart.exe ..\data\unmidqb\thrufireandflames_song_Exper
t ..\data\unmidqb\thrufireandflames_Expert_Star > ..\data\raw\thrufireandflames.
raw

The "> ...raw" dumps the output into the raw file. If you look at the raw file you will see it is in the format:
GHIII chart extractor v1.0 by Invo
----------------------------------

Reading file (44696 Bytes)... Done!
Dumping chart file (times are in milliseconds):

Timestamp:2414		Duration:50		Note:   R 
Timestamp:2489		Duration:37		Note:    G
Timestamp:2565		Duration:50		Note:  Y  
Timestamp:2640		Duration:37		Note:    G
Timestamp:2715		Duration:50		Note: B   
Timestamp:2791		Duration:37		Note:    G
Timestamp:2866		Duration:50		Note:   R 
etc...

Reading file (732 Bytes)... Done!
Dumping star power (times are in milliseconds):

	Number of star power verses: 25
Timestamp:4828		Number of notes:8
Timestamp:17431		Number of notes:8
Timestamp:30052		Number of notes:12
Timestamp:48025		Number of notes:9
etc...

A change to my program!


Now the timestamp and duration are in milliseconds, so I ditched the BPM idea, so that I don't have to work out the BPM for every song.
The program now just uses the timestamp, but it still uses my original format of #|bbbbbb (though the last b is just always just 1 now).
I wrote a program called GH3RawToGH3.exe which converts the .raw files to .gh3cheat files and gives an output like this:
0|010001
750000|100001
1510000|001001
2260000|100001
3010000|000101
3770000|100001
4520000|010001
5280000|100001
6030000|001001

It subtracts the first timestamp from all the timestamps so it starts at 0, and multiplies them by 10000 so they are in ticks. Due to this you must start the cheat program (by pressing enter) just as the song should start...(which may require some practise).

Usage:
GH3RawToGH3.exe SourceFile|DestinationFile

Finally - My App (GH3Cheat.exe)

It's a simple console application which starts by opening the file specified in the command line arguement, connects to the usb board, then waits for the enter key to be pressed. Once pressed it starts playing the file until the end.

It does not use the duration of the note. It strums and plays every not, white or not (because there is not distinction in dumpchart.exe) and just relases the strum half way between the current note and the next note, therefore working with long notes, but never releasing the strum too late.


At the moment it auto-star-powers, in other words, ever time it strums it also presses back so that if there is star power, it uses it.
Later on I shall probably make a more user fiendly program with optional star powering and tweak buttons for the timing so if you start it too soon or late you don't have to restart the song.

The Code:
Module Module1
    Private Declare Function OpenDevice Lib "k8055d.dll" (ByVal CardAddress As Integer) As Integer
    Private Declare Sub CloseDevice Lib "k8055d.dll" ()
    Private Declare Function ReadAnalogChannel Lib "k8055d.dll" (ByVal Channel As Integer) As Integer
    Private Declare Sub ReadAllAnalog Lib "k8055d.dll" (ByRef Data1 As Integer, ByRef Data2 As Integer)
    Private Declare Sub OutputAnalogChannel Lib "k8055d.dll" (ByVal Channel As Integer, ByVal Data As Integer)
    Private Declare Sub OutputAllAnalog Lib "k8055d.dll" (ByVal Data1 As Integer, ByVal Data2 As Integer)
    Private Declare Sub ClearAnalogChannel Lib "k8055d.dll" (ByVal Channel As Integer)
    Private Declare Sub SetAllAnalog Lib "k8055d.dll" ()
    Private Declare Sub ClearAllAnalog Lib "k8055d.dll" ()
    Private Declare Sub SetAnalogChannel Lib "k8055d.dll" (ByVal Channel As Integer)
    Private Declare Sub WriteAllDigital Lib "k8055d.dll" (ByVal Data As Integer)
    Private Declare Sub ClearDigitalChannel Lib "k8055d.dll" (ByVal Channel As Integer)
    Private Declare Sub ClearAllDigital Lib "k8055d.dll" ()
    Private Declare Sub SetDigitalChannel Lib "k8055d.dll" (ByVal Channel As Integer)
    Private Declare Sub SetAllDigital Lib "k8055d.dll" ()
    Private Declare Function ReadDigitalChannel Lib "k8055d.dll" (ByVal Channel As Integer) As Boolean
    Private Declare Function ReadAllDigital Lib "k8055d.dll" () As Integer
    Private Declare Function ReadCounter Lib "k8055d.dll" (ByVal CounterNr As Integer) As Integer
    Private Declare Sub ResetCounter Lib "k8055d.dll" (ByVal CounterNr As Integer)
    Private Declare Sub SetCounterDebounceTime Lib "k8055d.dll" (ByVal CounterNr As Integer, ByVal DebounceTime As Integer)
    Const gGreen As Integer = 1
    Const gRed As Integer = 2
    Const gYellow As Integer = 4
    Const gBlue As Integer = 8
    Const gOrange As Integer = 16
    Const gStar As Integer = 32
    Const gStrum As Integer = 64
    Sub Main()
        Dim CardAddress As Integer
        Dim h As Integer
        Console.Write("Connecting to card 0...")
        CardAddress = 0
        h = OpenDevice(CardAddress)
        Select Case h
            Case 0, 1, 2, 3
                Console.WriteLine("Connected")
            Case -1
                Console.WriteLine("Card not found!")
                GoTo nd
            Case -2
                Console.WriteLine("EXE NOT FOUND?!")
                GoTo nd
        End Select
        WriteAllDigital(0)
        Dim cs As String = Replace(Command, """", "")
        Console.WriteLine("Loading File..." & cs)
        FileOpen(1, cs, OpenMode.Input)
        Dim Data(10000, 3) As Double
        Dim n As Integer = 0
        Dim s As Double = -1
        Do Until EOF(1)
            Dim d As String = ""
            Input(1, d)
            If d <> "" And Left(d, 1) <> "#" Then
                n += 1
                Dim ds() As String = Split(d, "|")
                Data(n, 0) = ds(0)
                If s = -1 Then s = ds(0)
                Data(n, 1) = Play(Mid(ds(1), 1, 1), Mid(ds(1), 2, 1), Mid(ds(1), 3, 1),_
                 Mid(ds(1), 4, 1), Mid(ds(1), 5, 1), Mid(ds(1), 6, 1))
                Data(n, 3) = Play(Mid(ds(1), 1, 1), Mid(ds(1), 2, 1), Mid(ds(1), 3, 1),_
                 Mid(ds(1), 4, 1), Mid(ds(1), 5, 1), 0)
                Data(n, 2) = Mid(ds(1), 6, 1)
            End If
        Loop
        FileClose(1)
        Console.WriteLine(n & " lines of data read.")
        Dim b As Double
        Dim c As Integer = 1
        Console.WriteLine("Press enter to start")
        Console.ReadLine()
        Dim OldTicks As Long = Now.Ticks - 100000
        Do Until c > n
            b = Now.Ticks - OldTicks
            'b = ((Now.Ticks - OldTicks) / Difference)
            If b >= Data(c, 0) - s Then
                Console.WriteLine("Beat (ticks): " & b & ", Data: " & Data(c, 1))
                WriteAllDigital(Data(c, 1))
                c += 1
            End If
            If Data(c, 2) = 1 And Data(c - 1, 2) = 1 And b >= Data(c - 1, 0) +_
             ((Data(c, 0) - Data(c - 1, 0)) / 2) - s Then WriteAllDigital(Data(c - 1, 3))
        Loop
        Threading.Thread.Sleep(1000)
        WriteAllDigital(Data(c - 1, 3))
nd:
        Console.WriteLine("Done, press enter to exit")
        Console.ReadLine()
        WriteAllDigital(0)
        CloseDevice()
    End Sub
    Function Play(ByVal Green As Boolean, ByVal Red As Boolean, ByVal Yellow As Boolean,_
      ByVal Blue As Boolean, ByVal Orange As Boolean, ByVal Strum As Boolean) As Integer
        Dim d As Integer = 0

        If Green Then d = d + gGreen
        If Red Then d = d + gRed
        If Yellow Then d = d + gYellow
        If Blue Then d = d + gBlue
        If Orange Then d = d + gOrange
        If Strum Then d = d + gStrum + gStar 'Remove + gStar if you dont want auto-starring
        Play = d
    End Function
End Module

Yes it's not the tidyest thing but I don't care. It works!

Other Apps


I also wrote an GH3CheatIndexGen.exe (Cheat Index Generator) which, if you use my file system layout and fill the xen folder with the required files will do all the work and populate the gh3cheat folder. Note you need unpak.exe unpakmidqb.exe dumpchart.exe and gh3rawtogh3.exe in the bin folder for this to work.
There is also a GH3CheatExplorer.exe which lists all the files in the gh3cheat directory (also using my file system) and sorts them by difficulty. Double click it and it will shell the file, so if you associate gh3cheat with the gh3cheat.exe it will automatically open the file with the exe.

File Downloads

All GH3Bot downloads.

Copyright © Paul Ridgway 2009 | Pictures by Amanda Taylor | HTML Layout & Base code by James Ridgway