Sound Hacking/Sega Consoles

From vgmrips

Sega MegaDrive/Genesis sound hacks

Simple Triggers

These are simple memory triggers. Setting the respective bytes in 68000 or Z80 RAM will cause the game to immediately play a song or sound effect.

See BlastEm's page for instructions on how to use these in that emulator.

Game Sound Driver Music Trigger + Comments
Bill's Tomato Game Krisalis/Shaun Hollingworth maincpu.w@FF900E = xxxx

0001/0002 = stop sound, 0003~00D0 = music
Note: The trigger selects the "module pattern". Thus some values can start playback mid-song.

Chuck Rock Krisalis/Shaun Hollingworth maincpu.w@FF0014 = xxxx

0001 = stop sound, 0002~0043 = music
Note: The trigger selects the "module pattern". Thus some values can start playback mid-song.

Sonic The Hedgehog SMPS 68k maincpu.b@FFF009 = xx

00/E4 = stop sound, 81~93 = music, A0~D0 = SFX, E1 = SEGA speech

Sonic The Hedgehog 2 SMPS Z80 genesis_snd_z80.b@1B88 = xx

00/FD = stop sound, 81~9F = music, A0~F3 = SFX, FA = SEGA speech

Sonic The Hedgehog 3 SMPS Z80 genesis_snd_z80.b@1C0A = xx

E2 = stop sound, 01~32 = music, 33~DB = SFX, FF = SEGA speech

Spider-Man vs. The Kingpin unknown custom play SFX: maincpu.b@FFE6EC = xx, values 00~31

pause music: genesis_snd_z80.b@000A = 00
resume music: genesis_snd_z80.b@000A = FF
silence sound: genesis_snd_z80.b@000B = FF
Music can not be triggered and requires a function call of 000DE8 or 000E0E with the song address on the stack.

Verytex Terpsichorean genesis_snd_z80.b@0107 = 0xXX; genesis_snd_z80.b@0108 = 0x02

0C = stop sound, 00~0B = music

Advanced Hacks

This section contains ROM patches for playing songs/SFX, as well as hacking information like ROM/RAM offsets and sound driver RAM layouts.

Adventures of Rocky and Bullwinkle and Friends, The

ROM patch to play a certain song at the SEGA screen
Offset ROM's Hex Replace with Description
03C29E 05 A4 00 02 ignore bad ROM checksum
04C0F7 03 xx where xx = sound ID
068B9C 6A 60 Make it freeze on the SEGA screen

The PlaySong function is located at ROM offset 05618A.

Baby's Day Out

ROM patch to play a certain song at the SEGA screen
Offset Hex bytes ASM code Description
019FC4 41F9 00FF 0408 LEA $FF0408.L, A0
019FCA 4210 CLR.B (A0)
019FCC 4A10 TST.B (A0)
019FCE 67FC BEQ $019FCC Wait for Vertical Interrupt
019FD0 4EB8 1612 JSR $001612.W Call Play Music (skipping the "stop" part)
019FD4 xxxx DC.W #id "song ID" (xxxx) parameter for PlayMusic
019FD6 60FE BRA * Freeze game
Hacking information
PlayMusic routine 001608 (stops music, waits for frame to finish, then starts music)
GemsStart routine 005CC4 (start GEMS sequence)
GemsStop routine 005D06 (stop all GEMS sequences)
GEMS command area A01B40~A01B7F

Bass Masters Classic / Bass Masters Classic: Pro Edition

For Bass Masters Classic, these codes will freeze the game and allow you to play any of the GEMS sequences in place of the title track:

15EF3C:01FC
15EF1C:00??

The Pro Edition release has a different set of patch codes:

001DF4:44FC
001E1E:70??

Bill's Tomato Game

Hacking information:

Note: Almost every value is a 2-byte word. (Big Endian)

Sound RAM:      FF9000
NTSC/PAL Mode:  FF9006/07 (01 - NTSC, enables extra delay, 00 - PAL)
NTSC Delay Cntr:FF9008/09 (counts 0..5 in NTSC mode, unused in PAL mode)
Pause Enable:   FF900A/0B (01 - pause sound driver)
PlayMusic Slot: FF900E/0F (value is 01+)
Tempo Countdown:FF9010/11
Cur. Pattern:   FF9012/13
Cur. Row:       FF9014/15
Tempo:          FF902C/2D
Playing State:  FF902E
                -> 00 - playing
                -> FF - paused
Track RAM:      FF903A (0C bytes per track, 6 tracks)
Total Frames:   FF90B0/B1
Frames in Sec.: FF90B2/B3
Total Seconds:  FF90B4/B5

Sound Driver Init routine: 0F91AA
Sound Driver Update routine: 0F928A


Track RAM
---------
00/01 - some Tick Counter
02/03 - Ticks until next event
04 - Event Type??
05 - Event Data
06 - ??
07-0B - unused (00)

Bugs Bunny in Double Trouble

The Options menu uses the demo timer, similar to #The Death and Return of Superman. The way to eliminate the timer isn't known yet, but you can extend it.

68000 RAM address 0xFA76 extends the timer when set to a large number below hexadecimal 80/decimal 128. (Set to those numbers, it makes the demo start at once.) At 0x7F, it lasts a little longer than two loops' worth of some of the longer songs, like BULLYBUG.

To work in Blastem, it must be specified as a byte:

set [$FFFA76].b $7F

Song pointers are known from the sound test of the hidden cheat menu, and by observing 68000 RAM address 0x0416. It contains the currently playing song/sfx, but isn't a trigger: setting the number directly doesn't change it.

The sound slots in the cheat menu stop at 76 (0x59). Although it plays music at high enough numbers, they sound different from the options menu's music test.

Known song pointers in Double Trouble
Hex number Description
00 Title Screen
02 CAMEOS
03 LEVCOMP
04 LEVFAIL
05 BUGSPACE
06 BULLYBUG
07 BONUSLEV
08 GAMECOMP
0B MRVANGRY
0C BUGSCONT
0D INVULNER
0E running
0F boom
10 stopped running
11 running alt?
12 whiff
13 lion
14 thump?
15-29
2A pause
2B
2C cage
2D-31
32 menu sound
37 nyah nyah nyah-nyah nyah
38 took hit
39-3A
3B ARENABUG
3C BUGHAUNT
3D DUCKRABB
3E ARABIAN
3F KNIGHTY
40-59

ClayFighter

ROM patches to play GEMS sequence data on the Interplay logo:

offset  hex bytes       description
000B36  4475            ;freezes game on Interplay logo
000B2C  00xx            ;plays music or sound effect

The Death and Return of Superman

This game has a timer used for every screen, which will force the game to either start the demo (on the title screen), or boot you out of the options menu. This patch will disable the timer, allowing the sound test to be used properly.

003FD6  536D -> 382D  ; disable timer
012BDF  32 -> 00 ; skip the copyright screen (which can't be skipped otherwise)

Doom

Use these ROM patch codes to access the GEMS sequences used in the game.

0013B8:00BC
0013B0:00??

The above code freezes the game; the question marks are where the song/SFX IDs go.

Dragon's Lair: The Adventure Continues

0003B6:70xx replaces the song that plays during the attract mode, with xx being a song ID. 00 is silence. 0003BE:60FE causes the game to freeze just before the title screen, allowing the song to play uninterrupted.

Most SFX are PCM samples and are played with a different routine.

Dynamite Headdy (April beta)

Song ROM Hex Address Listed At
Beat It 061ACE Unreferenced
Unused Track 062334 Unreferenced
Escape Hero (Section B) 064270 Unreferenced
Escape Hero (Short Version) 064EC6 Unreferenced

Foreman for Real

The word at $1D185A is the song ID of the title screen track, which plays in an uninterrupted loop indefinitely throughout the attract mode (without any sound effects). $0081 is the title screen song itself.

Head-On Soccer

Apply the code 01390C:60FE, which will cause the title screen to freeze on a white screen.

Change the two bytes at $008926 to change which song is played at that point. By default it is 0001, for the title screen music.

The Lost World: Jurassic Park

Apply the following codes:

  • 3FA118:4E75: bypass the region check
  • 0003BC:4E71 and 0003BE:4E71: bypass the checksum check
  • 3B75BC:4E71: disable the options screen idle timer

After that, 3B7728:70xx changes the song played when switching the Music option to On, with xx being the song ID. 00 is silence (and is what is played when you switch Music back to Off). Codes from 0A on seem to be invalid and do nothing, though the game plays 0A at some point (ROM $3B9914; could this be a bug? feel free to try yourself and correct me). Other sounds are played by other routines.

Mario Lemieux Hockey

FF9458   offset to Track RAM for current song
   Note: Each song has its own (!) track RAM.
FFD406   decompressed song data

sound calls:
022086   Sound Driver Update
022452   play title music
022512   stop music
022536   play menu music
022548   play ??
0225F2   play fight music
022604   play ??
022698   play shoot out music
0226F8   play ??

It's worth mentioning that the sound system in this game is a total mess. Each song is in a separate "sound bank" and each sound bank has its own work RAM. The pointer stored at FF9458 in 68k RAM tells the sound driver, which part of the sound bank RAM it has to update. This also has the interesting effect, that the menu SFX stop working when you play e.g. the title theme on the menu screen. In order to play a song, the game calls one of the "play XX" routines, which has all hardcoded offsets for track RAM and song data.

sound test patch:
000498   4EB9 -> 601A            skip title screen
0004CE   4EB9 0002 2452 -> 4EB9 0002 2512   don't play music at SEGA screen
000556   6600 -> 6000            cut SEGA logo short
0009A8   4EB9 0002 2536 -> 4EB9 00xx xxxx   insert address of "play XX" routine at xx

Math Blaster: Episode 1

To choose a song to play, write its ID to the word at $FF0EAC. I (andlabs) think that this will be picked up during the next vertical blank? unless the code to start song playback is buried deep within the plumbing of the code.

For something more practical for ripping: the word at $00000632 is the ID of the song played on the title screen. Change the byte at $00068A to $60 to stop the demo from starting (causing the game to wait for you to press start on the title screen forever and preventing any sound effects from playing). Don't press start, as the process of loading the main menu pauses the sound temporarily.

ID $0005 is the title screen song. ID $0004 is silence, and is explicitly played on the Sega screen.

Mickey's Ultimate Challenge

007A57      song ID for title screen (default: 09h)


This code allows the game stay on the title screen forever (overwrite existing bytes):

offset      byte code   ASM code            comment
------      ---------   --------            -------
007B8C      4EB8 05A6   JSR     $0005A6.w   ; wait for VSync
007B90      60FA        BRA.S   *-4         ; and do that forever

Additional patches for quick screen fading (i.e. less annoyance when booting the ROM)

00712A      6A00 -> 6000    ; SEGA screen
00786C      6A00 -> 6000    ; Copyright screen
007926      6A00 -> 6000    ; Hi Tech Expressions screen
007A02      6A00 -> 6000    ; Designer Software screen

Newman/Haas IndyCar featuring Nigel Mansell

ROM patch to play a song on the title screen:

offset  hex bytes       ASM code        description
1C8C72  4E71            NOP             ; skip SEGA screen
1CA4B6  4E71            NOP             ; skip license screen
1C8A8E  4E71            NOP             ; skip Aklaim screen
1C018E  303C 00xx       MOVE.W  #xx, D0 ; set song ID to play (0..5)
1C01A0  60FE            BRA     *       ; freeze game after starting the song (to prevent screen changes etc.)

General ROM locations:

StopMusic:		070000
PlayMusic:		070004 (Register D0 = sound ID)
UpdateMusic:		070008
LoadZ80Driver:		07000C
SilencePSG:		070014
UpdateSFX:		07001C
StopSFX:		070028
DoCarEngineSFX:		070030
Music Pointer Lists:	07173C (20h bytes per song, 6 songs)
Sound RAM:		FF8400

Sound IDs:

00 - Main Theme
01 - Racing BGM
02 - Qualified
03 - Hard Luck
04 - Race Results
05 - Ending

Top Gear 2

ROM patch code 0251EA:00?? allows you to access any song in the game. The "??" is the ID for each song.

01 - Title screen (Used)
02 - Canterbury Plains
03 - Ayers Rock
04 - Unused Jingle?
05 - Title Screen (Unused)
06 - Auckland

True Lies

ROM patches:

disable fade in:
00BAD7: 08 -> FF        ; set fade in speed from "slow" to "fast"

modify title screen song:
000871: 13 -> ##        ; set song playing on title screen (possible song IDs are 00~19)

prevent title screen timeout:
17C1DD: 01 -> 00        ; prevent countdown on title screen

skip various screens (replacing JSR instruciton with NOPs):
01225C: 4EB9 0000 0700 -> 4E71 4E71 4E71        ; skip SEGA screen
000C9C: 4EB9 0000 A3E2 -> 4E71 4E71 4E71        ; skip Copyright screen
000CA2: 4EB9 0000 A30C -> 4E71 4E71 4E71        ; skip Aklaim screen
000CA8: 4EB9 0000 A06E -> 4E71 4E71 4E71        ; skip Beam Software screen

Note: The music seems to lag a bit when loading the title screen the first time. There is no lag when the music restarts when exiting the options screen.

Hacking information:

Sound Driver Functions
----------------------
Update Sound:           0134BC
Load Z80 Driver:        013AB4
Play SFX:               0136E2
                                reg D0: ID (00 = play SFX, 08 = stop music?, 80 = fade music)
                                reg D1: SFX channel? / destination volume (00 = min, FF = max)
                                reg D2: SFX ID / fade speed (00 = slow, FF = fast)
Play Music 1:           01385C
                                reg D0: song ID
                                reg D1: ??
                                reg D2: ??
                                reg D3: ??
Play Music 2:           013942 (song ID is read from 68k RAM F6BC)
Music Pointer List:     197718
Main Music List:        001868 (1Ah entries, 2 bytes each, all are multiples of 2, used with 19699A)
Some Music List:        19699A (0Dh entries, 2 bytes each)
Bank Pointer List?:     1969B4

Game Sound APIs
---------------
PlayBGM:                001792
                                reg D0: song ID (00h~19h)
SetBank?:               00BA28
                                reg D0: bank ID (00h~19h)
                                sets RAM FB21 and RAM FB25
PlayBGM_A:              00BA42
                                -> 01385C, reg D0 = RAM FB21, reg D1 = RAM FB25, reg D2 = 1, reg D3 = 0
PlayBGM_B:              00BA70
                                -> 01385C, reg D0 = 0, reg D1 = RAM FB25, reg D2 = 1, reg D3 = 0
StartLevelBGM:          00BA90
                                -> 01385C, reg D0 = 0, reg D1 = word from (19699A+18) -> value 0, reg D2 = 1, reg D3 = 0
Fade Out Music:         00BAB8
                                -> 0136E2, reg D0 = 80, reg D1 = 00, reg D2 = 8
Fade In Music:          00BACC
                                -> 0136E2, reg D0 = 80, reg D1 = RAM FB29, reg D2 = 8
                                Note: The sound driver defaults to volume 0, so this call is *REQUIRED* after starting a BGM.
PlaySFX:                00BAE4
                                -> 0136E2, reg D0 = 4, reg D1 = RAM FB15, reg D2 = 0
                                -> 0136E2, reg D0 = 2, reg D1 = [parameter reg D1], reg D2 = 0
                                -> 0136E2, reg D0 = 0, reg D1 = 6, reg D2 = [from tables pointed to from 1969E8]
???:                    00BB40
                                -> 0136E2, reg D0 = 4, reg D1 = ??, reg D2 = 0
                                -> 00BAE4
                                -> 0136E2, reg D0 = 4, reg D1 = RAM FB15, reg D2 = 0
???:                    00BB82
                                -> 0136E2, reg D0 = 4, reg D1 = [parameter reg D1], reg D2 = 0
                                -> 00BAE4
                                -> 0136E2, reg D0 = 4, reg D1 = RAM FB15, reg D2 = 0

Ultraman

sound driver calls:
038000 - Sound Driver Update [no parameters]
038004 - Stop All Sound [no parameters]
038008 - Play PCM SFX [register D0 = SFX ID]
03800C - Play Sound [register D0 = sound ID, register D1 = number of channels]
038010 - ?? (unused?)
038014 - ?? (unused?)
038018 - Fade Out [register D0 = fade speed?]
03801C - Load Z80 Driver [no parameters]
038020 - ?? [register D0 = some ID]
038024 - ?? [register D0 = some ID]

General Music List:   007172 (2 bytes for entry, list contains 14h entries = 28h bytes total)
    for each entry: 1 byte - ID [reg D0], 1 byte - channel count [reg D1]
Level BGM List:      007178 (part of the General Music List)

The sound driver has a huge pointer list 039D88. These are pointers to "track headers". In order to load a song, it specifies the ID of the first track header (register D0) and the number of channels/track headers (register D1) to be loaded. Then it calls "PlaySound". So if it loads "reg D0 = 45h, reg D1 = 3", it loads the track headers for with IDs 45h, 46h and 47h. The list contains SFX as well as songs and the game code has the "first track ID" and "channel count" values hardcoded.

playing the "Stage Select" music is done using the following code:
006C7C   70 4F      MOVEQ   #$4F, D0   ; reg D0: sound ID
006C7E   72 06      MOVEQ   #$06, D1   ; reg D1: channel count
006C80   4EB9 0003 800C   JSR   $03800C      ; call PlaySound

a search pattern for "Play Sound" routine:
70## 72## 4EB9 0003 800C


You can make a simple "sound test" patch by modifying the ROM this way:
000328   4E71 -> 6048      skip checksum check
000430   4EB9 0000 -> 4EF8 21C0   skip to "stage 1" screen [we use it for playing songs]
006C7C   704F -> 70xx      set xx = sound ID
006C7E   7206 -> 72xx      set xx = channel count