Notes:Guitar Hero
This page contains notes for the game Guitar Hero.
All information found in .dtb files presented in detokenized .dta format (equivalent to the custom scripting language used to develop the game). Paths are relative to the root of the ARK file contents, as extracted by ARK Expander (link forthcoming). I'm working with the US retail release, SLUS-21224. Your mileage may vary using any other region. Huge dump ahead.
Found in /config/gen/beatmatch_controller.dtb, I'm pretty sure the "egozy" layout is leftover from the early days when the frets were colored ROYGB:
(joypad (slots kPad_L2 0 kPad_L1 1 kPad_R1 2 kPad_R2 3 kPad_X 4)) (lefty_joypad (slots kPad_X 0 kPad_R2 1 kPad_R1 2 kPad_L1 3 kPad_L2 4)) (guitar (slots kPad_R2 0 kPad_Circle 1 kPad_Tri 2 kPad_X 3 kPad_Square 4)) (egozy (slots kPad_R2 0 kPad_R1 1 kPad_Tri 2 kPad_Square 3 kPad_X 4))}
Found in /config/gen/cheats.dtb, this is part of the debugging interface. I have yet to find a way to reenable it on the retail game or any of the demos, I believe there is a necessary .IRX driver that we don't have a copy of.
(keyboard (KB_F2 {toggle_fake_player1_cheat}) (KB_F3 {toggle_scoring_debug}) (KB_F4 {toggle_lights_debug}) (KB_F5 {cheat_empty_star_power}) (KB_F6 {track_panel toggle_gems}) (KB_F7 {track_panel toggle_surface}) (KB_F8 {track_panel toggle_nowbar}) (KB_F11 {test_screen_transitions}) (0 {toggle_time_paused}) (1 {set $no_crowd {! $no_crowd}} {update_crowd}) (2 {guitarist0 debug_driver {switch $guitarist0.driver (0 main.drv) (1 left_hand.drv) (2 right_hand.drv)}} {set $guitarist0.driver {mod {+ 1 $guitarist0.driver} 3}}) (3 {paramedit edit {find $syscfg charsys guitar_face_params face_data} {guitarist0 update_params}}) (5 {if {meta is_up} {{ui panel sel_song} beat_song 1000000}}) (# {if {game is_up} {player0::player win 3}}) ($ {if_else {game is_up} {player0::player win 4} {cheat_add_cash}}) (% {if {game is_up} {player0::player win 5}}) (a {a_cheat}) (A {A_cheat}) (b {b_cheat}) (B {set $barf_cheat {! $barf_cheat}}) (c {if {game is_up} {force_pick_shot}}) (C {rnd toggle_overlay camera}) (d {toggle_dual_perspective}) (e {adjust_crowd_rating -0.10}) (E {adjust_crowd_rating 0.10}) (f {toggle_fretboard}) (g {guitarist0 toggle_debug}) (G {rnd toggle_overlay guitar}) (j {guitarist0 walk_prev}) (k {guitarist0 walk_next}) (h {if {exists hud} {hud set_showing {! {hud showing}}}}) (H {hide_2d_crowd}) (l {player0::player lose}) (L {toggle_lipsync_test}) (m {toggle_crowd_meter}) (M {toggle_mute_global}) (O {rnd save_objects dump.rnd ui}) (p {toggle_auto_play}) (P {cycle_music_speed}) (q {toggle_solo_quantize}) (r {reload_song}) (R {reload_track_hud}) (s {if {game is_up} {rnd toggle_overlay score}}) (S {fill_star_meter}) (t {rnd toggle_overlay time}) (T {rnd toggle_timers} {rnd toggle_overlay rate}) (u {next_tutorial_lesson}) (U {prev_tutorial_lesson}) (w {player0::player win 3}) (W {toggle_walks}) (x {toggle_cam}) (Z {set $arena.camtest 1}) (> {tutorial reset_vo}) (. {camtest_next_shots}) (, {camtest_pick_shot})) (right (kPad_Circle {cycle_free_camera}) (kPad_X {toggle_shuttle}) (kPad_Square {meta print_current_screen}))
Related but much longer, from /config/gen/cheats_funcs.dtb:
{func cheat_msg ($msg) {rnd show_overlay cheats TRUE} {rnd reflect cheats {print $msg " "}} {set $cheat.clear_time {+ {ui frame} CHEAT_DISPLAY_MS}} {ui delay_task CHEAT_DISPLAY_MS {if {>= {ui frame} $cheat.clear_time} {rnd show_overlay cheats FALSE}}}} {func cheat_msg_bool ($label $val) {cheat_msg {sprint $label ": " {if_else $val "ON" "OFF"}}}} {func audio_array {find $syscfg beatmatch audio}} {func get_audio {elem {elem {audio_array} 1} 0}} {func set_audio ($val) {set {elem_var {elem {audio_array} 1} 0} $val} {cheat_msg {sprint "New audio mode: " $val}}} {func toggle_audio_mode {if {meta is_up} {cond ({== {get_audio} slipstream} {set_audio unmute}) ({== {get_audio} unmute} {set_audio slipstream})}}} {func a_cheat {if_else {meta is_up} {toggle_audio_mode} {arena set_showing {! {arena showing}}}}} {func A_cheat {if_else {meta is_up} {if {! {{ui panel sel_song} is_up}} {do (($new {! {campaign all_access}})) {campaign set_all_access $new} {campaign set_tutorial_access $new} {cheat_msg_bool "All Access" $new} {if {== {ui current_screen} {ui screen main}} {{ui screen main} access_all}}}} {toggle_crowd_audio}}} {func b_cheat {if_else {meta is_up} {{ui panel sel_song} beat_song 1} {set $debug.beep {! $debug.beep}}}} {func hide_2d_crowd {set $show {! {arena::Crowd01.mm showing}}} {foreach_int $i 1 6 {set $name {sprintf "arena::Crowd0%d.mm" $i}} {if {exists $name} {$name set_showing $show}}}} {func cycle_free_camera {with_namespace player0 {if_else {track free_camera_active} {do {track free_camera FALSE} {cheat_msg "Free camera: off"}} {if_else {arena free_camera_active} {do {arena free_camera FALSE} {track free_camera TRUE $cheat.controller} {cheat_msg "Free camera: Fretboard"}} {do {arena free_camera TRUE $cheat.controller} {cheat_msg "Free camera: Arena"}}}}}} {func toggle_crowd_meter {with_namespace player0 {do (($new {! {player crowd_rating_active}})) {player set_crowd_rating_active $new} {cheat_msg_bool "Crowd meter" $new}}}} {func start_shuttle {if_else {rnd overlay_showing time} {set $cheat.show_time FALSE} {do {rnd show_overlay time TRUE} {set $cheat.show_time TRUE}}} {game set_time_paused TRUE} {arena_panel set_paused TRUE} {player0::player set_crowd_rating_active FALSE} {beatmatch set_shuttle TRUE $cheat.controller}} {func stop_shuttle {beatmatch set_shuttle FALSE} {game set_time_paused FALSE} {arena_panel set_paused FALSE} {if $cheat.show_time {rnd show_overlay time FALSE}}} {func toggle_shuttle {if_else {beatmatch shuttle_active} {stop_shuttle} {start_shuttle}}} {func toggle_mute_global {if_else {mixer mute} {do {mixer set_mute FALSE} {cheat_msg "Mute all: FALSE"}} {do {mixer set_mute TRUE} {cheat_msg "Mute all: TRUE"}}}} {func next_tutorial_lesson {if {tutorial is_up} {tutorial tutorial_inc 1}}} {func prev_tutorial_lesson {if {tutorial is_up} {tutorial tutorial_inc -1}}} {func toggle_crowd_audio {do (($new {! {crowd_audio enabled}})) {crowd_audio set_enabled $new} {cheat_msg_bool "CrowdAudio" $new}}} {func toggle_walks {do (($new {! {guitarist0 walks_enabled}})) {guitarist0 set_walks_enabled $new} {cheat_msg_bool "Walks" $new}}} {func toggle_auto_solo {with_namespace player0 {do (($new {! {player_matcher auto_solo}})) {player_matcher set_auto_solo $new} {cheat_msg_bool "Auto freestyle" $new}}}} {func toggle_solo_quantize {with_namespace player0 {player_matcher toggle_solo_quantize}}} {func toggle_auto_play {if_else {game multiplayer} {cycle_multiplayer_auto_play} {with_namespace player0 {do (($new {! {player_matcher auto_play}})) {player_matcher set_auto_play $new} {cheat_msg_bool "Autoplay" $new}}}}} #define MULTI_AUTO_STATES (((FALSE FALSE "off") (TRUE FALSE "player1") (FALSE TRUE "player2") (TRUE TRUE "both"))) {set $multi_auto_index 0} {func cycle_multiplayer_auto_play {do (($new_index {mod {+ $multi_auto_index 1} 4}) ($state {elem MULTI_AUTO_STATES $new_index})) {player0::player_matcher set_auto_play {elem $state 0}} {player1::player_matcher set_auto_play {elem $state 1}} {cheat_msg {sprint "Autoplay: " {elem $state 2}}} {set $multi_auto_index $new_index}}} {func adjust_crowd_rating ($delta) {with_namespace player0 {player set_crowd_rating {+ {player crowd_rating} $delta}}}} {func toggle_lipsync_test {toggle_camera_lipsync}} {func toggle_fake_player1_cheat {if_else {toggle_fake_player1} {cheat_msg "Faking Player 2"} {cheat_msg "Normal Player 1"}}} {func toggle_dual_perspective {do (($new {! {track_panel dual_perspective}})) {track_panel set_dual_perspective $new} {cheat_msg_bool "Dual-perspective" $new}}} {func reload_song {game thread_task (preserve $ms $auto0 $auto1) {game set_time_paused TRUE} {arena_panel set_paused TRUE} {set $ms {game ms}} {set $auto0 {player0::player_matcher auto_play}} {if {game multiplayer} {set $auto1 {player1::player_matcher auto_play}}} {game load_song {game get_song}} {$task wait {! {game loaded}}} {cheat_msg {sprint "Reloaded song: " {game get_song}}} {arena_panel set_paused FALSE} {game set_skip_intro TRUE} {game set_start_paused TRUE} {game start_song_now} {track_panel set_track_out} {beatmatch jump $ms} {game set_skip_intro FALSE} {game set_start_paused TRUE} {player0::player_matcher set_auto_play $auto0} {if {game multiplayer} {player1::player_matcher set_auto_play $auto1}}}} {func toggle_time_paused {do (($new {! {game time_paused}})) {game set_time_paused $new} {crowd_audio set_paused $new}}} {func toggle_fretboard {if {! {meta is_up}} {track_panel set_showing {! {track_panel showing}}}}} {func reload_track_hud {game thread_task (preserve $ms) {game set_time_paused TRUE} {set $ms {game ms}} {ui goto_screen reload_hud_track} {$task wait {! {track_panel is_up}}} {$task wait {! {hud is_up}}} {track_panel intro_skip} {track_panel set_track_out} {hud intro_skip} {beatmatch jump $ms}}} #define MUSIC_SPEEDS ((1.00 0.50 0.25 0.10)) {set $speed_index 0} {func cycle_music_speed {if {! {meta is_up}} {do (($new_index {mod {+ $speed_index 1} {size MUSIC_SPEEDS}}) ($speed {elem MUSIC_SPEEDS $new_index})) {beatmatch set_music_speed $speed} {cheat_msg {sprint "Track speed: " $speed}} {set $speed_index $new_index}}}} #define DEBUG_TASK ((init {$this set active FALSE}) (start {$this set active TRUE} {$this on_start} {$this poll}) (is_active {$this get active}) (stop {$this on_stop} {$this set active FALSE}) (poll {$this on_poll} {if {$this get active} {game delay_task 15 (preserve $this) {$this poll}}})) {class ScoringDebug DEBUG_TASK (on_start {rnd show_overlay score_debug TRUE}) (on_stop {rnd show_overlay score_debug FALSE}) (on_poll {if_else {game is_up} {rnd reflect score_debug {with_namespace player0 {printf "Crowd: %.2f-%.2f Notes: %d-%d-%d Mult: %.2f " {player raw_crowd_rating} {player crowd_rating} {player current_streak} {player longest_streak} {player notes_hit} {/ {player score} {beatmatch base_max_score 0}}}}} {$this stop}})} {new ScoringDebug scoring_debug} {func toggle_scoring_debug {if_else {scoring_debug is_active} {scoring_debug stop} {scoring_debug start}}} {func toggle_lights_debug {do (($new_state {! {rnd overlay_showing lights}})) {rnd show_overlay lights $new_state}}} {func lights_debug ($msg) {rnd reflect lights {print "Lights: " $msg " "}}} {func toggle_cam {if {exists cam} {cam toggle_enabled} {cheat_msg_bool "camera logic" {cam get_enabled}}}} {func cheat_add_cash {if {store is_up} {campaign add_cash 100} {store update_total_cash_display}}} {func fill_star_meter {if {! {meta is_up}} {if_else {game multiplayer} {if_else {fake_player1} {player1::player fill_star_power} {player0::player fill_star_power}} {player0::player fill_star_power}}}} {func cheat_empty_star_power {if {! {meta is_up}} {if_else {game multiplayer} {if_else {fake_player1} {player1::player empty_star_power} {player0::player empty_star_power}} {player0::player empty_star_power}}}} {func print_transition_test_status {if {&& $transition_screen_0 $transition_screen_1} {rnd reflect transition_test {printf "%s - %s - %d " {screen_name $transition_screen_0} {screen_name $transition_screen_1} $transition_count}}}} {func test_screen_transitions {if {meta is_up} {if_else {! $transition_screen_0} {do {set $transition_screen_0 {ui current_screen}} {rnd show_overlay transition_test TRUE} {rnd reflect transition_test {print {screen_name $transition_screen_0} " - "}}} {if_else {! $transition_screen_1} {do {set $transition_screen_1 {ui current_screen}} {set $transition_test_active TRUE} {set $transition_count 0} {print_transition_test_status} {run_transition_test}} {do {set $transition_screen_0 FALSE} {set $transition_screen_1 FALSE} {set $transition_test_active FALSE} {set $transition_count 0} {rnd show_overlay transition_test FALSE}}}}}} {func run_transition_test {ui thread_task {ui goto_screen $transition_screen_0} {$task wait {ui in_transition}} {++ $transition_count 1} {print_transition_test_status} {ui goto_screen $transition_screen_1} {$task wait {ui in_transition}} {++ $transition_count 1} {print_transition_test_status} {if $transition_test_active {run_transition_test}}}}
Found in /config/gen/gh.dtb, this is where I found out we needed more files (possibly HMX-specific) for debug mode (also notice the reference to mtapman being set to FALSE on the shipping version):
(system (script #include system_script.dta ) (language (force eng)) (iop_modules (iop/scrtchpd.irx) (iop/sio2man.irx) (iop/mcman.irx) (iop/mcserv.irx) #ifdef _SHIP (iop/usbd.irx FALSE) (iop/usbkb.irx FALSE) #else (iop/usbd.irx) (iop/usbkb.irx "keybd=1" "debug=0") #endif (iop/padman.irx) (iop/msifrpc.irx) #ifdef _SHIP (iop/mtapman.irx FALSE) #else (iop/mtapman.irx) #endif (iop/libsd.irx) (iop/sdrdrv.irx) (iop/cdvdstm.irx)))
Same file, there's also a bit more mention of on-screen debug meters, if I'm reading the scripting right:
(rnd (title "Guitar Hero") (show_timers FALSE) (overlays (time (lines 1) (showing FALSE) (color 0 0 0 0.70)) (cheats (lines 1) (showing FALSE) (color 0 0 0 0.70)) (camera (lines 3) (showing FALSE)) (score (lines 15) (showing FALSE)) (guitar (lines 1) (showing FALSE)) (guitarist0_status (lines 1) (showing FALSE)) (guitarist0_history (lines 3) (showing FALSE)) (player0_freestyle (lines 1) (showing FALSE)) (score_debug (lines 1) (showing FALSE)) (lights (lines 1) (showing FALSE)) (camtest (lines 1) (showing FALSE)) (transition_test (lines 1) (showing FALSE))))
Sole contents of /config/gen/gh_version.dtb, so we know the US version was built September 17, 2005 for release on November 1:
"Build: 050917_E"
Juicy dev info, reference to something called "ghedit" which I'm guessing probably ran on a PS2 TOOL, either on the PS2 but communicating with a companion program on the PC side, or directly on the PC side and interfacing with the game engine itself. As best as I can tell, this tool is nowhere on the retail disc but would likely be present in any development build of the game. First, from /config/gen/ghedit.dtb:
(rndedit (title GHEdit) (extension gh) (target "ghedit_tool_%c.elf") (prog_id GHEdit.File) (max_paths (HMX_SYSTEM_RUN "%s/../../system/run") (HMX_SYSTEM_MAX "%s/../../system/tool/max"))) (namespaces (ghui 2500 20000)) (ghui #merge ../ghui/config.dta ) #merge ../../../system/run/config/rndedit.dta
Also, from /config/gen/ghedit_tool.dtb:
(namespaces (ghui 2500 20000)) (ghui #merge ../ghui/config.dta ) #merge ../../../system/run/config/rndedit_tool.dta
Found in /config/gen/mc.dtb, editing these settings along with hexediting the main ELF file can be used to change the display name and disc ID for savefile purposes, allowing multiple saves to be used with different custom discs instead of other discs clobbering all the high scores:
(base_dir "BASLUS-21224") (elf_name "SLUS_212.24")
Found in /config/gen/mem.dtb, this points to the possibility that at one time, they had planned for a PC version as well as the known initial discussions with MadCatz regarding controllers for a potential original Xbox version of the game (although this one isn't explicitly listed here, there is a fall through which I think is meant for it):
(heaps #ifdef HX_EE (main (size 20500000)) (rnd (size 5500000) (handle TRUE)) #else #ifdef HX_PC (main (size 50000000)) #else (main (size 26000000))
Excerpt from /config/gen/scoring.dtb, all floats within 0.00<=x<=1.00 are percentages. Notice "recharge_rate 0.00" under star_power, this is the percentage of the star power bar to automatically gain per measure. Never used in game (and AFAIK, I think it still exists even nowadays in the RB3 engine). Also including star rating thresholds, as you may know there is no one- or two-star:
(star_power (recharge_rate 0.00) (deploy_rate 0.12) (star_phrase 0.25) (whammy_rate 0.03) (ready_level 0.50) (multiplier 2) (crowd_boost 6) (min_length 2.00) (whammy_speed 0.05) (whammy_timeout 0.50)) (star_ratings (thresholds (kDifficultyEasy 2.00 3.00) (kDifficultyMedium 2.00 3.00) (kDifficultyHard 2.00 3.00) (kDifficultyExpert 2.00 3.00)) (symbols (3_star 4_star 5_star)))
Not much interesting in GH1's /config/gen/songs.dtb. The cool and juicy stuff is when I get to the GH2 demos and retail build. Here, the tutorial songs do have names and artists (as would be displayed on screen normally) but they're never used, here's an example:
(tutorial102 (name "Basic 2 Playing Notes") (artist "You")
As an aside, here is part of my personal addition to GH1's songs.dtb to add the two "secret" songs (there are other files that need to be edited as well):
(advharmony (name "Trippolette") (artist "Andrew Buch") (song (name songs/advharmony/advharmony) (tracks 1) (slip_tracks ((2 3))) (pans (-1.00 1.00 -1.00 1.00)) (vols (0.80 0.80 0.90 0.90)) (cores (-1 -1 1 1)) (solo (riffs standard))) (bank sfx/song_default) (bpm 120) (anim_tempo kTempoFast) (preview 9845 44150) (midi_file songs/advharmony/advharmony.mid) (quickplay (character nu_metal) (guitar gibson_flying_v) (venue fest))) (graveyardshift (name "Graveyard Shift") (artist "Unknown") (song (name songs/graveyardshift/graveyardshift) (tracks 1) (slip_tracks ((2 3))) (pans (-1.00 1.00 -1.00 1.00)) (vols (0.80 0.80 0.90 0.90)) (cores (-1 -1 1 1)) (solo (riffs standard))) (bank sfx/song_default) (bpm 120) (anim_tempo kTempoFast) (preview 9845 44150) (midi_file songs/graveyardshift/graveyardshift.mid) (quickplay (character nu_metal) (guitar gibson_flying_v) (venue fest)))
Similarly, here's the song section of /config/gen/store.dtb, as modified by me to add *Trip and GS to the in the store, making them "buyable" (but making them cost $0 so it doesn't mess up the rest of the store with the total money you get if you 5* everything):
(song (fireitup (price 300)) (cheatonthechurch (price 300)) (cavemanrejoice (price 300)) (eureka (price 300)) (allofthis (price 250)) (behindthemask (price 250)) (breakingwheel (price 250)) (callout (price 250)) (decontrol (price 250)) (evenrats (price 250)) (farewellmyth (price 250)) (flyonthewall (price 250)) (getready2rokk (price 250)) (guitarhero (price 250)) (hey (price 250)) (sailyourshipby (price 250)) (storyofmylove (price 250)) (advharmony (price 0)) (graveyardshift (price 0)))
Found in /config/gen/track_graphics.dtb, are settings pertaining to the visual appearance of the fretboard, including scroll speed (called "track_speed", with 1.0 being equivalent to normal Easy scroll speed and 2.1 equivalent to GH2 Hard/Expert with Hyperspeed enabled). Most of these values I have not modified, although they should modify the angle, position, and rate of fade at the entry point in the distance. Also notice that HMX can't spell for shit - "dual_perspecitve":
(gem (fps 30) (mat_formats (gem gem_%s) (tail tail_%s) (tail_glow tail_glow_%s) (star gem_starpower_%s) (dot dot_top_hopo2_%s)) (tail_glow_width 1.50) (tail_glow_tight_width 0.70) (sparkle_len 1000)) (track_width 20) (horizon_y 110) (remove_y -10) (track_speed (kDifficultyEasy 1) (kDifficultyMedium 1) (kDifficultyHard 1.40) (kDifficultyExpert 1.40)) (alpha_dist 40) (horizon_tail_clip 7) (nowbar_tail_clip 1.50) (cam (near_plane 50) (far_plane 200) (z_start 0) (z_end 0.10)) (free_camera (rotate_rate 0.00) (slew_rate 0.10) (near_far_plane 2 200)) (init_gems 25) (init_tails 16) (multiplayer (normal (track_offset 8.85 0 0) (track_scale 0.85 0.85 0.85)) (dual_perspecitve (track_scale 0.76 0.76 0.76)) (use_dual_perspective TRUE)) (fade (multi ((x 128) (y 236)) ((x 384) (y 236))) (normal (x 256) (y 216)))
In GH2 there's a file called /config/gen/modes.dtb that stores default settings for attract mode (which is actually the game autoplaying the chart with the equivalent of performance mode enabled), quickplay, career, practice, and multiplayer. I don't know where these settings are stored in GH1, however.
Nothing really interesting in GH1's /ui/gen/ folder, although when I cover the GH2 demos we'll see more in there as far as re-enabling locked away menus.
That's all for tonight, tomorrow I'll go through and dig out some interesting imagery. LocalH 03:55, 11 August 2011 (EDT)