.CHC

From Gitaroo Pals
Jump to navigation Jump to search

The .CHC file format is used in Gitaroo Man and Gitaroo Man Lives!. It contains the song charts and factors such as starting energy and damage. And while the file itself contains no audio or visuals, it determines which audio/visuals to use with different song charts.

Notes:

  • Not everything has been verified on both consoles
  • need to document some new findings by sonicfind et al


Data types used in this article (all little-endian):

  • int32: signed 4-byte integer
  • uint32: unsigned 4-byte integer
  • float32: 4-byte floating-point decimal

File Layout

Song

First comes this section, which affects the entire song. It controls such things as volume and gameplay speed.

offset size data
+0x00 4 Magic stamp, always 'SNGS'
+0x04 4 unknown constant 0x00001800 [ignored by game]
+0x08 12 all 0 [ignored by game]
+0x14 4 unknown value, always something like 0x000010xx [ignored by game]
+0x18 12 all 0 or junk values [ignored by game]
+0x24 256 PS2 version: null-terminated string: location of .IMC file used for this stage's music and sound effects.
  • In the Japanese version, this string is used as-is.
  • In the US version, the first 16 characters of the string are ignored (even null bytes will have no effect). The characters after that point are appended to /PROJECTS/STDATA/US to get the real location of the IMC file.
  • EU/KR versions presumably are similar to US

PSP version: unused (PSP version doesn't use IMC files)


The following pairs of values-- first and last frames-- each define a set of frames to be played from this stage's .SSQ file. (The SSQ file control the 3D models displayed in the background.)

offset size data event that causes frames to play
+0x124 4 float32: Win A first frame Player wins the stage.
+0x128 4 float32: Win A last frame
+0x12C 4 float32: Win B first frame None, Win B seems to be unused. (Note: I haven't checked whether multiplayer uses this)
+0x130 4 float32: Win B last frame
+0x134 4 float32: Lost Pre first frame Player loses the stage.
+0x138 4 float32: Lost Pre last frame
+0x13C 4 float32: Lose Post first frame Loops endlessly after Lost Pre, while "Try Again?" is displayed onscreen.
+0x140 4 float32: Lose Post last frame


The following values control volume and pan for different audio channels. Values are as follows:

  • Volume: ranges from 0 to 32767
  • Pan: ranges from 0 (left) to 32767 (right). 16383 places audio in the center.
offset size PS2 version data PS2 version purpose PSP version data PSP version purpose
+0x144 4 uint32: 1st channel volume Background music [left channel] unused no effect
0x148 4 uint32: 1st channel pan unused
+0x14C 4 uint32: 2nd channel volume Background music [right channel] unused no effect
0x150 4 uint32: 2nd channel pan unused
+0x154 4 uint32: 3rd channel volume Player 1 audio uint32: 2nd track left channel volume Player 1 audio [left channel]
0x158 4 uint32: 3rd channel pan unused
+0x15C 4 uint32: 4th channel volume Player 2 audio uint32: 2nd track right channel volume Player 1 audio [right channel]
0x160 4 uint32: 4th channel pan unused
+0x164 4 uint32: 5th channel volume Player 3 audio; can be Player 1 audio [right channel] if stereo phrases are enabled uint32: 3rd track left channel volume (Multi-player modes only) Player 2 audio [left channel] in Multi-player modes, no effect in Single-player mode
0x168 4 uint32: 5th channel pan unused
+0x16C 4 uint32: 6th channel volume Player 4 audio; can be Player 2 audio [right channel] if stereo phrases are enabled uint32: 3rd track right channel volume (Multi-player modes only) Player 2 audio [right channel] in Multi-player modes, no effect in Single-player mode
0x170 4 uint32: 6th channel pan unused
+0x174 4 uint32: 7th channel volume Voice & sound effects [left channel] uint32: 3rd track left channel volume (Single-player mode only) Player 2 audio [left channel] in Single-player mode, no effect in Multi-player modes
0x178 4 uint32: 7th channel pan unused
+0x17C 4 uint32: 8th channel volume Voice & sound effects [right channel] uint32: 3rd track right channel volume (Single-player mode only) Player 2 audio [right channel] in Single-player mode, no effect in Multi-player modes
0x180 4 uint32: 8th channel pan unused


Continuing with the rest of this section:

offset size data
+0x184 4 float32: gameplay speed factor. The lower this value, the faster the Trace Line and Guard marks go, making gameplay more difficult.

Specifically, this might be the ratio of samples to pixels. The timing of trace lines, phrase bars, and guard marks are in samples (where 48000 samples = 1 second of music). So, with a speed factor of 240, a phrase bar of 24000 samples would appear 100 pixels long onscreen.


Random stuff observed on PSP:
  • Setting this to a negative value has strange results-- guard marks approach from opposite their usual direction, and trace lines become unplayable or crash the game.
  • a mismatch in this value between the ST00A and ST00B charts will make the traceline very strange in the first chart, possibly crashing the game.
+0x188 4 uint32: number of Cues that appear in this file. Also the number of SongSections, since there is always a Cue for each SongSection.

Cue

Then come Cues, as many as were specified above (at address 0x188 of Song). A Cue is a pairing of audio and background visuals. Each Cue goes with a SongSection, e.g. the first Cue in the file goes with the first SongSection in the file. The Cue's audio and visuals will be played when its SongSection is played.

offset size data
+0x00 4 uint32: index value for the cue. Seems to be based on the order of which each cue is added to the song, so indexes may skip forth or back a few numbers. [ignored by game]
+0x04 16 null-terminated string: seems to be unused. It's the name of an audio section like below, but the game doesn't seem to use it. Usually identical to the used one below, but in PS2 multiplayer charts you will often see a slightly different string here.
+0x14 16 null-terminated string: name of an audio section from the currently loaded .IMC file.

PSP version: this instead refers to an audio file located in the "MS" or "MSE"/"MSJ" folder (relative to this CHC file's location on the disc). Usually "MSE" (English) or "MSJ" (Japanese) is used with single-player mode, and "MS" is used with multi-player mode, but the game is not consistent about this-- it depends on the level.

+0x24 4 float32: first frame to play from stage's .SSQ file
+0x28 4 float32: last frame to play from stage's .SSQ file
+0x2C 4 probably junk [ignored by game]

SongSection

Then come SongSections, as many as were specified above (at address 0x188 of Song). A SongSection contains Conditions and Charts. Also, each SongSection goes with a Cue, e.g. the first SongSection in the file goes with the first Cue in the file. When a SongSection is played, its Charts are displayed onscreen, and its Cue's audio and visuals are played in the background. Then as the SongSection finishes playing, its Conditions determine what to do next.

offset size data
+0x00 4 Magic stamp, always 'CHLS'
+0x04 4 unknown constant 0x00001300 [ignored by game]
+0x08 4 uint32: unknown, appears related to size of this SongSection [ignored by game]
+0x0C 8 all 0 [ignored by game]
+0x14 16 all 0 or junk values [ignored by game]
+0x24 4 uint32: battle phase
0 - Intro displays INTRO in corner
1 - Charge displays CHARGE onscreen and in corner
2 - Battle BATTLE onscreen, ATTACK/GUARD in corner
3 - unused Final FINAL onscreen, ATTACK/GUARD in corner
4 - Harmony FINAL onscreen, HARMONY in corner
5 - End FINAL onscreen, END in corner
6+ - unused Final FINAL onscreen, previously shown words or INTRO in corner
+0x28 4 float32: tempo in beats per minute. Only used in the PSP version. This is used to make sure background animations match the beat of the music-- it has no effect on music or gameplay speed. (The PS2 version ignores this, instead using a single tempo for the entire song, specified in ALBUMDEF.TXT.)
+0x2C 4 uint32: duration of this SongSection in samples (where 1 sample = 1/48000th of a second)
+0x30 4 always 0 [ignored by game]
+0x34 4 uint32: number of Conditions
+0x38 ? Conditions
?+0x00 4 uint32: number of players, always 4 (can be changed safely, though rather pointless)
?+0x04 4 uint32: number of charts per player
?+0x08 ? Charts. number of Charts = (number of players) * (number of charts per player). Charts are listed in order by player-- all of Player 1's Charts come first, then all of Player 2's Charts, etc.

Note on Players 3 and 4: If there is not a Player 3 participating in the match (i.e. it's single-player or 2-player versus mode), Player 1 gets Player 3's Charts. And if there isn't a Player 4, Player 2 gets Player 4's charts.

Condition

A Condition determines what to do when the current SongSection ends, perhaps depending on such factors as player energy or randomness.

offset size data
+0x00 4 uint32: condition type
0 [Unconditional] always True
1 [Left side Energy] True if Player 1's energy is less than the condition argument (see below for condition argument). False otherwise.
2 [Right side Energy] True if Player 2's energy is less than the condition argument. False otherwise.
3 [Random] Generates a random number between 0.0 and 1.0, True if the random number is less than the condition argument (e.g. with a condition argument of 0.20, this has a 20% chance of being True). False otherwise.
4 [Left side unavail] False if this match has a Player 3 participating (only possible in Versus mode). True otherwise.
5 [Right side unavail] False if this match has a Player 4 participating (only possible in Versus mode). True otherwise.
6 [Left side < Right side] True if Player 1's energy is less than Player 2's energy. False otherwise.
+0x04 4 float32: condition argument. Used with condition types 1, 2, and 3.
+0x08 4 int32: True effect. This is invoked if the condition above is True. This value has different effects depending on its value.

If True effect is less than 0:

  • In this case, this value determines the next Condition to test. -1 goes to the next Condition, -2 goes to the Condition after that, etc. (In this way, the game chains multiple conditions together, e.g. randomly chooses between 3 SongSections when Player 2's health reaches 50%)

If True effect is 0 or greater:

  • In this case, this value determines the next SongSection to play after this one ends (e.g. a value of 0 will take you to the first SongSection in the file). If the SongSection doesn't exist (e.g. a value of 6 when there only SongSections 0 to 5), the song ends and the player wins the stage.
+0x0C 4 int32: False effect. Same as above, but invoked if the condition above is False.

Chart

Each Chart contains a trace line, phrase bars, and guard marks, defining the lines and button presses the player must follow. Note: whenever "samples" are mentioned here, 1 sample is equal to 1/48000th of a second.

offset size data
+0x00 4 Magic stamp, always 'CHCH'
+0x04 4 unknown constant 0x00001300 [ignored by game]
+0x08 4 uint32: size of this chart in bytes - 44 [ignored by game]
+0x0C 4 always 0 [ignored by game]
+0x10 4 always 0, game crashes if this value is changed
+0x14 16 all 0 or junk [ignored by game]
+0x24 4 uint32: start time of this Chart in samples (relative to whenever the SongSection starts playing)
+0x28 4 uint32: end time of this Chart in samples. (Not sure if it's actually used for anything, though-- messing with this value causes no visible differences.)
+0x2C 4 number of Trace Line fragments (must be at least 1)
+0x30 ? Trace Line fragments
?+0x00 4 number of Phrase fragments
?+0x04 ? Phrase fragments
?+0x00 4 number of Guard fragments
?+0x04 ? Guard fragments
?+0x08 4 always 0 [ignored by game]

Trace Line fragment

Trace Line fragments join to form a Trace Line. Every Chart must contain at least 1 Trace Line fragment or else the game will crash. To make this single Trace Line fragment invisible, give it a duration of 1 sample.

offset size data
+0x00 4 int32: start time in samples, relative to Chart's start time. (Negative start times are not tolerated well-- in one attempt, the Trace Line was invisible until it reached a fragment with a positive start time.)
+0x04 4 uint32: duration in samples. (The duration should match the difference between this fragment's and the next fragment's start times.)
+0x08 4 float32: angle in radians, opposite of how it appears in-game. (e.g. an angle pi/4 radians is supposed to be up-right, but this will make the Trace Line approach from down-left.)
+0x0C 4 uint32: curve, always 0 or 1. If it's 0, this fragment will go straight until the next fragment. If it's 1, this fragment will gradually curve between its own angle and that of the next fragment.

Phrase fragment

Each Phrase Bar that appears on the Trace Line is made of one or more Phrase fragments. Phrase fragments are also used to show the charging and attacks made by computer-controlled players.

A single Trace Line fragment can contain multiple Phrase fragments, but a single Phrase fragment should not span multiple Trace Line fragments. If a Phrase Bar needs to span multiple Trace Line fragments, the bar should be split into multiple Phrase fragments.

offset size data
+0x00 4 int32: start time in samples, relative to Chart's start time. (Negative start times seem to be tolerated okay, even though they're never used in the game.)
+0x04 4 uint32: duration in samples. (If this fragment is connected to the next one, duration should be equal to the difference between their start times.)
+0x08 4 uint32: Phrase Bar start, always 0 or 1. If it's 1, this Phrase fragment begins with an Attack Point, a circle that the player must hit. This should be set to 0 only if this fragment is connected to the previous one, otherwise the game will almost certainly crash.
+0x0C 4 uint32: Phrase Bar end, always 0 or 1. If it's 1, this Phrase fragment is terminated by a rounded end. This should be set to 0 only if this fragment is connected to the next one, otherwise the game could crash.
+0x10 4 uint32: character animation, always 0, 1, or 2. A playable character has up to 3 possible animations when playing a Phrase Bar-- this value chooses which of those animations to use. (A value greater than 2 causes the phrase fragment to disappear so that it can't be played.)
+0x14 4 probably junk [ignored by game]
+0x18 4 probably junk [ignored by game]
+0x1C 4 probably junk [ignored by game]

Guard fragment

Each Guard fragment creates a button icon that the player must dodge.

offset size data
+0x00 4 int32: start time in samples, relative to Chart's start time. The game always uses negative start times, but positive start times also seem to work.
+0x00 4 uint32: guard button
  • 0 - [] Square
  • 1 - X Cross
  • 2 - O Circle
  • 3 - /\ Triangle

Below, their directions are shown:

   3           ^
 0   2  ->  []   O
   1           X
+0x00 4 always 0 [ignored by game]
+0x00 4 always 0 [ignored by game]

Player Energy/Damage Factors

These values control the players' energy and how much is gained or lost during different battle phases.

offset size data
+0x00 4 uint32: always 20 (0x14)
+0x04 32 Player 1 Intro factors (see table below)
+0x24 32 Player 1 Charge factors
+0x44 32 Player 1 Battle factors
+0x64 32 Player 1 Harmony factors
+0x84 32 Player 1 End factors
+0xA4 32 Player 2 Intro factors
+0xC4 32 Player 2 Charge factors
+0xE4 32 Player 2 Battle factors
+0x104 32 Player 2 Harmony factors
+0x124 32 Player 2 End factors
+0x144 160 all of Player 3's factors, probably unused in PSP
+0x1E4 160 all of Player 4's factors, probably unused in PSP

Each set of factors goes like is as follows. Values can be made negative to have the opposite effect.

offset size data
+0x00 4 float32: starting energy (1.0 = full energy)
+0x04 4 float32: Charge: energy gained (initial button press)
+0x08 4 float32: Attack: damage to other player (initial button press, and also after button release?)
+0x0C 4 float32: Guard: energy gained (used in multiplayer)
+0x10 4 float32: Attack: damage taken on miss
+0x14 4 float32: Guard: damage taken on miss
+0x18 4 float32: Charge: energy gained (after button release)
+0x1C 4 float32: Attack: damage to other player (after button release)

Note: In the PSP version (and maybe PS2 version, haven't checked yet), each battle phase only uses certain factors. For example, only Intro uses starting energy, End ignores any damage done to Player 1, etc. Unfortunately, this means no damaging your enemy during the Charge phase or anything like that.