Research / Sonic 2 / The Sonic music hacking guide

The Sonic music hacking guide:


*Created by Tweaker on May 25 2005.*
*Thanks to Saxman and fuzzbuzz.*
*Corrected by Sonic Hachelle-Bee.*

This guide will teach, even the complete clueless individual, how to edit the music in the Sonic the Hedgehog games for the Sega Mega Drive. Be warned however: you must have at least basic hex knowledge. If you have no idea what hex is, then I suggest you steer clear of this guide and figure things out first.

Update history:


March 29 2005: Initial release.

April 22 2005: Updated Chaotix info. Also added explanation on Sonic 2 Final pointer format and corrected a few bits of incorrect info. Turns out you CAN use 6 FM channels and the DAC at the same time, thanks to the music engine.

May 24 2005: Updated with even more Sonic 2 Final info. Also added music pointer locations for Ristar and Micheal Jackson's Moonwalker.

Pointer format:


First off, what is a pointer? Well, a pointer is a set of hexadecimal values that point to a location in the ROM (or, in other cases, RAM. More advanced stuff there though). There are different types of pointers.

Some are part of an offset index. These kinds of data pointers are usually 16-bits (2 bytes) long and are determined by adding the pointer value to the current location in the ROM (program counter). So if one offset index added to $80000, and a pointer read $0890, then it is reading offset $80890, which would be the location of the data it is looking for.

Other pointers are very basic. 32-bit pointers are the easiest to deal with. They are big endian when dealing with the Megadrive and define the exact location using four bytes. So let's use the previous example. Our location was $80890. The pointer appears as "00 08 08 90". Couldn't be any simpler.

The pointer format in the Sonic games music differs from game to game. I will list the pointer format for each incarnation of the music engine. Follow along.

Sonic 1, Ristar, and Moonwalker:


These pointers are relatively easy to deal with. These pointers are like the offset index pointers talked about earlier. They are relative 16-bit pointers that add the pointer value to the current location in the ROM. Here is an example:

Let's say that the music data started at $EC000. Now, our voice pointer says $0180. So, from $EC000 we add $180 to the value, making the location of the voice data at $EC180. You see? That is simple. There are some other things to note about these pointers that I will mention later that have to do with coordination flags.

Sonic 2 Beta, 3, Crackers, Chaotix and 3D:


These pointers are also pretty easy to deal with, once you understand their format. These pointers are also 16-bit, but they are absolute pointers. This means that they add to a specified location, which is usually even. Now, what you must understand is that these pointers are little endian, because the sound driver runs on the Z80. Little endian simply means that the bytes are swapped. A good example would be if a location was $8180 (big endian) for voice data, the pointer would read $8081 (little endian). This may seem confusing at first, but I will explain further.

You see, these pointers always read "8000", regardless of the starting location. So if the starting location of the music was $C0000 for one song, and the starting location of another was $C8000, the resulting pointer would still be $0080. You see, 8000 bytes is one music bank. So when 8000 bytes are used up by the first bank of music data, the second set of music pointers will add to that second bank location. So if the first bank's location was $C0000, and the second was $C8000, then the first set of pointers would add to $C0000, and the second to $C8000. Not too complicated. So lets break things down now.

Lets say the voice pointer for one song was $F289. Since these are little endian, swap the bytes. This makes $89F2. Now, lets say that the current bank adds to $C8000. So we can deduce that the location of the voice data is $C89F2. You get it now? It is easier to find things with these pointers, but it becomes a bit of a problem if you are porting music, since you have to either put the music in its "original" location or fix all the pointers in the song.

Sonic 2 Final:


All pointers add to a certain constant, including those in coordination flags. This constant is $1380. With these pointers, $1380 acts as zero. So lets say that the voice pointer reads $1915. Since $1380 is zero, we would subtract 1380 from 1915 and we get the distance away from the beginning of the song that the voice data is. Essentially the pointers in Sonic 2 Beta, but with a different constant. Note that each song is treated as it's own bank, and the beginning of the song is the beginning of the bank, while the end of the song is the end of the bank.

Exceptions: Credits music is uncompressed, unlike all the other musics. Uses the S2B pointer format. So do the pointers to the music data itself at $F8000.

Header format:


Sonic 1, Sonic 2, Sonic 3, Sonic & Knuckles, Sonic 3D Blast, and Sonic Crackers:


All pointers in this section differ according to the game you are hacking. Remember, relative for Sonic 1, Ristar, and Moonwalker, and absolute little endian for the others. The music header format listed is a universal format used in all the major Megadrive Sonic games, including Sonic 1, Sonic 2, Sonic 3, Sonic & Knuckles, Sonic 3D Blast, and Sonic Crackers.

Bytes positionDescription
00 & 01Voice pointer. This points to the location of the voice data, or instruments in the song.
02 & 03Channel setup. This is usually 0603, and means there are 5 FM channels, 1 DAC, and 3 PSG channels. Changing these bytes will either make the header larger or smaller, depending on what you change them to. If you want to use the 6th FM channel, the 6th FM channel will be located after the 5th FM channel modifier. The same applies if you decide to use the 4th PSG channel. It will be located right after the two redundant bytes after the 3rd PSG modifier.
04 & 05Tempo modifier. First byte is the dividing timing, and the second is the main tempo modifier. Change the second byte to make the music faster or slower.
06 & 07DAC pointer. This points to the drums you hear in the music. In Chaotix, this points to the PWM channel used instead of the DAC channel. Treat them as the same for now.
0A & 0BDunno. They seem to be redundant.
0C & 0DFM channel 1 pointer. It points to FM channel 1.
0E & 0FFM channel 1 modifier. First byte modifies pitch,
and second byte modifies volume (same for all).
10 & 11FM channel 2 pointer.
12 & 13FM channel 2 modifier.
14 & 15FM channel 3 pointer.
16 & 17FM channel 3 modifier.
18 & 19FM channel 4 pointer.
1A & 1BFM channel 4 modifier.
1C & 1DFM channel 5 pointer.
1E & 1FFM channel 5 modifier.
20 & 21PSG channel 1 pointer.
22 & 23PSG channel 1 modifier.
24 & 25Redundant. Does nothing.
26 & 27PSG channel 2 pointer.
28 & 29PSG channel 2 modifier.
2A & 2BRedundant. Does nothing.
2C & 2DPSG channel 3 pointer.
2E & 2FPSG channel 3 modifier.
30 & 31Redundant. Does nothing.


Knuckles Chaotix:


In Knuckles Chaotix, this format is slightly different to accomodate to the 32x's hardware. I have listed it below.

Bytes positionDescription
00 & 01Voice pointer. This points to the location of the voice data, or instruments in the song.
02 & 03Channel setup. This is usually 0603, and means there are 6 FM channels, and 3 PSG channels. Changing these bytes will either make the header larger or smaller, depending on what you change them to. If you decide to use the 4th PSG channel, It will be located right after the redundant two bytes after the PSG 3 modifier. Following that will be the PWM pointers.
04 & 05Tempo modifier. First byte is the dividing timing, and the second is the main tempo modifier. Change the second byte to make the music faster or slower.
06 & 07FM channel 1 pointer. It points to FM channel 1.
08 & 09FM channel 1 modifier. First byte modifies pitch, and second byte modifies volume (same for all).
0A & 0BFM channel 2 pointer.
0C & 0DFM channel 2 modifier.
0E & 0FFM channel 3 pointer.
10 & 11FM channel 3 modifier.
12 & 13FM channel 4 pointer.
14 & 15FM channel 4 modifier.
16 & 17FM channel 5 pointer.
18 & 19FM channel 5 modifier.
1A & 1BFM channel 6 pointer.
1C & 1DFM channel 6 modifier.
1E & 1FPSG channel 1 pointer.
20 & 21PSG channel 1 modifier.
22 & 23Redundant. Does nothing.
24 & 25PSG channel 2 pointer.
26 & 27PSG channel 2 modifier.
28 & 29Redundant. Does nothing.
2A & 2BPSG channel 3 pointer.
2C & 2DPSG channel 3 modifier.
2E & 2FRedundant. Does nothing.
30 & 31PWM channel 1 pointer.
32 & 33Redundant. Does nothing.
34 & 35PWM channel 2 pointer.
36 & 37Redundant. Does nothing.
38 & 39PWM channel 3 pointer.
3A & 3BRedundant. Does nothing.
3C & 3DPWM channel 3 pointer.
3E & 3FRedundant. Does nothing.


Understanding the header is essential for editing music. This is the basis of basic music editing, such as pitch and tempo editing. Once you understand the pointers and the header, then you are ready to start learning more advanced things.

Voice editing:


Voices are the instruments that you hear playing in the music throught the FM channels. To edit them correctly, you need to know FM synthesis. Voice swapping is easy enough though. A voice is 19 hex bytes, and has no header. It is raw data that gives info to the YM2612 FM chip in the Megadrive to give the desired sound output. The format of a voice is as follows.

Bytes positionDescription
00Next 3 bits - FeedbackLower 3 bits - Algorithm
01Left nyble - Detune of operator 4Right nyble - Coarse-frequency of operator 4
02Left nyble - Detune of operator 3Right nyble - Coarse-frequency of operator 3
03Left nyble - Detune of operator 2Right nyble - Coarse-frequency of operator 2
04Left nyble - Detune of operator 1Right nyble - Coarse-frequency of operator 1
05Upper 2 bits - [RS] of operator 4Lower 5 bits - Attack rate [AR] of operator 4
06Upper 2 bits - [RS] of operator 3Lower 5 bits - Attack rate [AR] of operator 3
07Upper 2 bits - [RS] of operator 2Lower 5 bits - Attack rate [AR] of operator 2
08Upper 2 bits - [RS] of operator 1Lower 5 bits - Attack rate [AR] of operator 1
09[AM] of operator 4Lower 5 bits - First decay rate [D1R] of operator 4
0A[AM] of operator 3Lower 5 bits - First decay rate [D1R] of operator 3
0B[AM] of operator 2Lower 5 bits - First decay rate [D1R] of operator 2
0C[AM] of operator 1Lower 5 bits - First decay rate [D1R] of operator 1
0DSecond decay rate [D2R] of operator 4 (00-14)
0ESecond decay rate [D2R] of operator 3 (00-14)
0FSecond decay rate [D2R] of operator 2 (00-14)
10Second decay rate [D2R] of operator 1 (00-14)
11Left nyble - First decay level [D1L] of operator 4Right nyble - Release rate [RR] of operator 4
12Left nyble - First decay level [D1L] of operator 3Right nyble - Release rate [RR] of operator 3
13Left nyble - First decay level [D1L] of operator 2Right nyble - Release rate [RR] of operator 2
14Left nyble - First decay level [D1L] of operator 1Right nyble - Release rate [RR] of operator 1
15Output level of operator 4
16Output level of operator 3
17Output level of operator 2
18Output level of operator 1


So to swap voices, select the voice you want and copy those 19 hex bytes onto another voice to hear your changes in game.

Note editing:


The way the music is set up in the Sonic games is similar to how music is structured in a MIDI file. Here are some values that will help you directly edit notation data in the music.

00 -> 7F: Note duration (how long a note is held for).
80 -> DF: Notes (80 is a rest).
E0 -> FF: Coordination flags.

Now, the DAC channel uses values starting with 81 (as with FM and PSG, 80 is used as a rest) to define the DAC drum sample that is played. Here are the sample definitions for a few games. Expect this section to be updated with more soon.

GameNotes
Sonic 181Kick
82Snare
83Timpani
84Noise
85Noise
86Silent
87 or higherSega sound
Sonic 2 Beta81Kick
82Snare
83Clap
84Scratch
85Timpani
86Tom
Sonic 2 Final81Kick
82Snare
83Clap
84Scratch
85Timpani
86 to 8ATom variations
8A to 8ETimpani variations
8FClap copy
91Bongo
Sonic Crackers81Kick
82Snare
83Tom
84Tom
85Tom
86Voice sample: "Let's go!"
87Voice sample: "Hey!"
88Beep/screech


For DAC samples, any value beyond 86 in Sonic 2 will contain variations of Tom up to value 8A. 8A starts variations of Timpani, which goes up to around 8F, which is a copy of the clap. I forget what 90 is, but 91 is a bongo, used in MCZ 2P music. This bongo is not in Sonic 2 Beta.

The Timpani definitions are the same for both Sonic 1 and 2, so go wild.

Coordination flags:


Coordination flags alter the music in real time. They are what tell the game to jump from one part of the song to another and to set up the channels. They are also what makes the music loop in the games. They are complicated, and it is recommended that you understand the YM2612 more before messing with them.

The coordination flags differ from game to game. They are the same in Sonic 1 and 2, but different in the others. For now, I will only give the flags for Sonic 1 and 2. Not all of them are known, but a majority are.

Coordination flagDescription
E0xxxx - Value
Table of each bit
Bit 7Left channel status
Bit 6Right channel status
Bit 5 and 4AMS
Bit 3Always 0
Bit 2, 1 and 0FMS
E6xxxx - Signed value
Change channel volume with xx
E7xxPrevent next note from attacking
E8xxSet note fill amount to xx
E9xxAdd xx to channel key
EAxxSet music tempo to xx
EBxxChange tempo modifier to xx for all channels
ECxxxx - Signed value
Change channel volume by xx
EESomething with voice selection
EFxxSet voice selection to xx
F0wwxxyyzzModulation
Table of each character
wwWait for ww period of time before modulation starts
xxModulation speed
yyModulation change per modulation step
zzNumber of steps in modulation
F1Turn on modulation
F2Stop the track
F4Turn off modulation
F5xxStore xx into the voice storage
F6yyyyJump to position yyyy
F7xxyyyyRepeat xx times at position yyyy before moving on
F8yyyyJump to sub-position yyyy (keep previous position in memory for returning)
F9Return from sub-position


Now, you will notice that some of these flags speak of a signed value. Signed values have the capability to be positive or negative. What makes a hexadecimal value signed? Bit number 7, the first bit on the left, will be 1 for negative and 0 for positive. So, a hexadecimal value that is between 00 and 7F is positive, and values between 80 and FF are negative. Here's an example:

Let's say that you wanted to go back 9 bytes to locate some music data in Sonic 1. Sonic 1 uses relative pointers, so let's use a signed value. With signed bytes, 0000 is the lowest value you can have. So FFFF would be -1, FFFE would be -2, etc. Signed values are used to locate data before the current location. So if I wanted to locate data that was 9 bytes back from my current location, I would take 0000 and subtract 9 bytes in hex from it. This leaves me with FFF7. If you wanted to go forward 9 bytes, you would take 0000 and add 9 to it (while keeping it 16-bit), which would be 0009. This is confusing, and kinda advanced, but if you plan on learning 68k ASM at all, it's something you have to know.

Game specifics:


Sonic 2:


Master Playlist:
Sonic 2 has a special Master playlist that defines what music ID plays in what slot. All values for music subtract 1 from the value. So to change Track 81 to Track 82, change 80 to 81. 80 is 81, 81 is 82, etc. These values go up to slot 9F, or 1F in the final version of the game. The locations are as follows.

Master Playlist in Sonic 2 Beta: $ECE9F
Master Playlist in Sonic 2 Final: $ECF36

As said before, track 81 is represented by 80, 82 is reresented by 81, etc. If you see an FF, skip it and move on to the next byte. This master playlist is only in Sonic 2 as far as I know. If I find it in any other games, I will update this section.

Music Compression:
In Sonic 2 Final, there is a compression applied to all music data in the game except for the credits. This format has been dubbed the Saxman compression, named after the person who cracked the format. I will not note how to manually decompress this format -- Refer to Saxman's hacking guide to do so. The music can be decompressed by using Magus' Sega Data Compressor. Refer to the pointer format to edit the music properly.

Music locations:


Now that you know all the basics, you can start editing music. Here are some locations for various games that will help. You can use the music pointers to locate the music data for now, but I may document the locations of each individual track in the future.

Sonic 1:


Music Pointers: $71A9C
Sound Effect Pointers: $78B44

Sonic 2 Beta:


Music Pointers (These add to $F0000, for 98 -> 9F): $F0000
Music Pointers (These add to $F8000): $F8000

Sonic 2 Final:


Music Pointers (These add to $F8000): $F8000
Music Pointers (These add to $F8000 and are for 98 -> 9F, excluding continue): $F802A
Continue music pointer (This adds to $F0000): $F0000
Sound Effect Pointers (These add to $F8000): $FEE91

Sonic Crackers:


Music Pointers: $0633F
Track 81: $10000
Track 82: $1088C
Track 83: $10BDA
Track 84: $11210
Track 85: $1172B
Track 86: $11B10

Sonic 3:


Music Pointers (These add to $C8000): $E761A
Music Pointers (These add to $D0000): $E762E
Music Pointers (These add to $D8000): $E7652

Sonic 3D:


Music Pointers (These add to $C0000): $D3233
Music Pointers (These add to $C8000): $D3245
Music Pointers (These add to $D0000): $D325D
Sound Effect Pointers (These add to $D8000): $D3297

Knuckles Chaotix:


Music pointers (These add to $40000): $76AE9
Music pointers (These add to $48000): $76B05
Music pointers (These add to $50000): $76B33

Sonic & Knuckles:


Music Pointers: $F793E

Specifics...
These add to $2C8000:
01 - 8000 - AIZ1
02 - 9B6D - AIZ2
03 - B0BC - HZ1
04 - C0C6 - HZ2
05 - D364 - MGZ1
06 - D97B - MGZ2
07 - E48F - CNZ1
08 - DDA9 - CNZ2

These add to $E8000:
09 - 8000 - FBZ1
0A - 8597 - FBZ2

These add to $2D0000:
0B - 86AA - IZ1
0C - 8000 - IZ2
0D - 9345 - LBZ1
0E - 8DC8 - LBZ2

These add to $E8000:
0F - 8AFF - MHZ1
10 - 9106 - MHZ2
11 - 9688 - SZ1
12 - 9CF2 - SZ2
13 - A2E5 - LRZ1
14 - ACF3 - LRZ2
15 - BE80 - SSZ
16 - C2B4 - DEZ1
17 - C79F - DEZ2
18 - CBB1 - Act 1 boss
19 - CEE1 - Robotnik boss
1A - D3DD - TDZ
1B - DCC0 - Rolling jump bonus stage
1C - E223 - Special stage
1D - EABB - Slot machine bonus stage

This adds to $2D8000:
1E - 8AE8 - Gum ball machine bonus stage

This adds to $E8000:
1F - F5A3 - Knuckles theme

These add to $2D8000:
20 - 99F7 - Azure Lake
21 - A4FD - Baloon Park
22 - B0EC - Desert Palace
23 - C324 - Chrome Gadget
24 - DA47 - Endless Mine

This adds to $E8000:
25 - F88E - Title

This adds to $2D8000:
26 - E587 - Sonic 3 credits

These add to $E0000:
27 - DD4B - Game/Time over
28 - DFA6 - Continue
29 - E3C0 - Bonus screen

These add to $E8000:
2A - FD4B - Extra life
2B - FE75 - Chaos Emerald

This adds to $E0000:
2C - E574 - Invincible

This adds to $2D8000:
2D - F5E4 - Competition menu

This adds to $E8000:
2E - CBB1 - Act 1 boss (same as 18)

These add to $E0000:
2F - E7AF - Menu
30 - F74C - Final boss

This adds to $2D8000:
31 - FABE - Sonic 3 countdown

These add $E0000:
32 - FCDE - Sonic & Knuckles outro
DC - C104 - Sonic & Knuckles credits

Ristar:


Music Pointers (32-bit): $C852A

Music Locations:
$CDBF4 - Flora 1 [shooting ristar]
$CEA0E - Scorch 1 [busy flare]
$CF6B6 - Flora 2 bgm [dancing leaves]
$D05F6 - Pre boss [concentration]
$D0774 - Sonata 1 (initial bgm) [intension]
$D0AC6 - Sonata 1 (1st metronome)
$D0E7C - Sonata 1 (2nd metronome)
$D1218 - Sonata 1 (final metronome)
$D1520 - Sonata 2 [on parade]
$D1E88 - Automaton 2 [lock up]
$D2C38 - Freon 1 [ring rink]
$D36DC - Undertow 2 [break silence]
$D4346 - Boss [crazy kings]
$D4DBE - Scorch 2 [under magma]
$D5A0A - Undertow 1 [splash down]
$D6752 - Freon 2 [ice scream]
$D732C - Ending 2 [next cruise]
$D7E4E - Sonata 1 (mini boss) [du di du da]
$D81E8 - Intro 1 [ebony force]
$D858C - Bonus [ready...GO!]
$D8D80 - Intro 2/ Title [pray pray play!]
$D97EC - Bonus (preview) [formation lap]
$D997A - Continue screen
$D9CFC - Greedy [theme of kaiser]
$DAA66 - Automaton 1 [crying world]
$DAFB2 - Ending 1 [star humming]
$DC422 - Sonata 1 (initial bgm) [intension] *MID ROUND??*
$DC69A - round clear 2 [beyond space]
$DCF66 - round clear 1 [lets go]
$DD240 - area clear [go ahead]
$DD5C8 - game over [game over .. fuu]
$DD7EC - defeated Greedy, before imploding cutscene
$DD978 - Sonata 1 (mini boss 3 note intro)
$DDA1E - "Sega" music

MJ's Moonwalker:


Music Pointers (32-bit): $600A4

Back | Printer friendly
2. Sprites and objects sound effects >>

© 2004, 2005 drx, www.hacking-cult.org. Don't copy without permission yadda yadda yadda.