To quote Irixion: "Do not reproduce [in part or in whole] without permission of creator, or I will hunt you down, and cut your penis off." This is your only warning.
Recently, I noticed that the Sonic 2 Clone Driver is painfully outdated, even to the point of an unhealthily large chunk of the guide, that was supposed to simply detail porting it, being about bringing the old thing up to date and making it actually imitate Sonic 2's driver. So I chose to do something about it: by giving the thing an Sonic 2 Git disassembly overhaul!
Looking closer at the Sonic 2 Clone Driver, I saw that it was made with old components and older methods, so I scrapped it, and started from scratch with a fresh copy of Sonic 1's sound driver. Here is the result:
Sonic 2 Clone Driver v2
version 2.3
About
Features
Requirements
Downloads
Guides
Changelog
Credits
Original Sonic 2 Clone Driver
Varion Icaria - Puto's sound driver port
Esrael - Tweaker's sound driver port, plus fixes for Puto's port, including a fix for the Sega sound
Puto, Tweaker, StephenUK - Numerous fixes
drx - Hacking CulT's VDP calculator
JMan2050 - Jman's PCM driver
Valley Bell - $EC sound fix
Sonic 2 Clone Driver v2
Those that contributed to the sound driver disassemblies
Valley Bell - General help, fixes for some bugs. Also, inspiration
Shobiz - Ported Spin Dash rev code
Puto - Original 68k Sega sound fix
MarkeyJester - DAC fade-in fix
Cinossu - S1SMPS2ASM
Flamewing - SMPS2ASM core; pointing out S3K's additional PSG frequencies; his perfect-compression koscmp, used to compress Mega PCM
Vladikcomper - Mega PCM
Clownacy - Go read the changelog =P
Recently, I noticed that the Sonic 2 Clone Driver is painfully outdated, even to the point of an unhealthily large chunk of the guide, that was supposed to simply detail porting it, being about bringing the old thing up to date and making it actually imitate Sonic 2's driver. So I chose to do something about it: by giving the thing an Sonic 2 Git disassembly overhaul!
Looking closer at the Sonic 2 Clone Driver, I saw that it was made with old components and older methods, so I scrapped it, and started from scratch with a fresh copy of Sonic 1's sound driver. Here is the result:
Sonic 2 Clone Driver v2
version 2.3
About
Spoiler
So, what is the Sonic 2 Clone Driver v2?
This is a heavily modified version of Sonic 1's sound driver, with a greater level of compatibility with music and sounds from other Sonic titles, along with numerous bugfixes, optimisations, and added features. However, to really understand the driver, you need to understand its history, and its ties (or lack thereof) to the original Sonic 2 Clone Driver.
Both the original Sonic 2 Clone Driver and the Sonic 2 Clone Driver v2 are modified versions of Sonic 1's sound driver (modified SMPS 68k Type 1b), designed to act as total replacements of Sonic 2's sound driver (improved Z80 port of Sonic 1's driver).
At the time of the original Sonic 2 Clone Driver's creation, working with Sonic 2's driver was considered extremely difficult, compared to Sonic 1's driver. This was down to several factors, such the driver being designed for the Z80 sound coprocessor, which sported a language few were willing to learn, and many changes to the music format. Not helping matters was also the fact that the driver was largely unexplored and lacking documentation. In contrast to Sonic 1's documented, easy-to-understand driver, Sonic 2's driver just seemed unfeasible to use, even though it had additional features, such as added DAC samples and PSG envelopes. This pushed hackers away from hacking Sonic 2.
One of the earlier efforts to counter this was the porting of Sonic 1's driver to Sonic 2. While this did help to ease the addition of custom music, compatibility with Sonic 2's original music and SFX was practically non-existent. Because of this, a hybrid was made, the original Sonic 2 Clone Driver, allowing access to Sonic 2's music, SFXs and DACs, while having the ease-of-use of Sonic 1's driver.
That was the past, however. Over time, advancements in documentation and tools have made both drivers just as easy to use, and the need for such a driver has diminished. Still, people continue to use the ancient thing, despite the fact that it really wasn't a feature-complete replica of Sonic 2's driver: missing PSG envelopes, incorrect music/SFX priorities, broken speed-up tempos, broken tempos in general, there were many problems with the original Sonic 2 Clone Driver that made the hacks that used it suffer. Today, simply sticking to Sonic 2's driver would be a better choice.
Come the Sonic 2 Clone Driver v2, an attempt at making as close a mimicry of S2's driver as possible: the aforementioned errors were corrected, and many more S2 elements were crammed in, in an effort to make the drivers near indistinguishable.
The purpose of the Sonic 2 Clone Driver v2 is not the same as its predecessor: while the original was made for ease-of-use, the Sonic 2 Clone Driver v2 exists for the sake of pushing the Mega Drive's hardware to its limit, by avoiding the biggest obstacle: the Z80's limitations. Problem areas such as driver size, and poor DAC quality, can be avoided by not using a Z80-based driver such as Sonic 2's or even Sonic 3's. This allows a hack to push its sounds to the limit, without having to downgrade to the smaller feature pool of Sonic 1's original driver.
So, what isn't the Sonic 2 Clone Driver v2?
As said before, the Sonic 2 Clone Driver v2 was not created for the purpose of making the process of adding custom music easier, rather, it was created for those that wished to implement features that the Z80 would not allow, due to its limitations. One example can be seen in the hack Sonic 2 Recreation, a hack that was based on Sonic 2, but used a 68k-based driver (a heavily modified version of the original Sonic 2 Clone Driver) because a Z80-based driver would not allow all of the features needed. The Sonic 2 Clone Driver v2 features Mega PCM, a custom DAC driver only available for 68k-based sound drivers. Mega PCM allows for greater playback quality and control. This is just one of the things possible when the sound driver is not entirely based on the Z80.
Of course, 68k-based drivers have their downsides.
Sonic 1's driver operates on the 68k, the main processor of the Mega Drive. Sonic 2's driver operates on the Z80, the sound co-processor. Right off the bat, there's the obvious performance hit. It may not be much, but is it worth it? There is also the RAM requirement: Sonic 2's driver just uses the Z80's RAM, which there is plenty of. In contrast, Sonic 1's driver uses $5C0 bytes of the very RAM that has to be juggled with the level chunks, blocks, layout, decompression queues, camera RAM, and more. Again, the important question is, is that worth it? What would all that RAM and performance be going into? If your answer is 'just doing something that Sonic 2's driver can already do', then this driver is not for you.
Is your hack going to be the next Jester's Challenge? Are you doing some complicated Mega CD work that the Z80 can't handle? You need to know if your hack's goals justify the costs.
If you just want to have S3K music in your hack, go use S3K's driver (or better yet, a good version of S3K's driver), or a (modern!) music-porting tool.
That said, by using this driver, you acknowledge that if I find it being used just so you can use S3K music, I will call you out on it.
This is a heavily modified version of Sonic 1's sound driver, with a greater level of compatibility with music and sounds from other Sonic titles, along with numerous bugfixes, optimisations, and added features. However, to really understand the driver, you need to understand its history, and its ties (or lack thereof) to the original Sonic 2 Clone Driver.
Both the original Sonic 2 Clone Driver and the Sonic 2 Clone Driver v2 are modified versions of Sonic 1's sound driver (modified SMPS 68k Type 1b), designed to act as total replacements of Sonic 2's sound driver (improved Z80 port of Sonic 1's driver).
At the time of the original Sonic 2 Clone Driver's creation, working with Sonic 2's driver was considered extremely difficult, compared to Sonic 1's driver. This was down to several factors, such the driver being designed for the Z80 sound coprocessor, which sported a language few were willing to learn, and many changes to the music format. Not helping matters was also the fact that the driver was largely unexplored and lacking documentation. In contrast to Sonic 1's documented, easy-to-understand driver, Sonic 2's driver just seemed unfeasible to use, even though it had additional features, such as added DAC samples and PSG envelopes. This pushed hackers away from hacking Sonic 2.
One of the earlier efforts to counter this was the porting of Sonic 1's driver to Sonic 2. While this did help to ease the addition of custom music, compatibility with Sonic 2's original music and SFX was practically non-existent. Because of this, a hybrid was made, the original Sonic 2 Clone Driver, allowing access to Sonic 2's music, SFXs and DACs, while having the ease-of-use of Sonic 1's driver.
That was the past, however. Over time, advancements in documentation and tools have made both drivers just as easy to use, and the need for such a driver has diminished. Still, people continue to use the ancient thing, despite the fact that it really wasn't a feature-complete replica of Sonic 2's driver: missing PSG envelopes, incorrect music/SFX priorities, broken speed-up tempos, broken tempos in general, there were many problems with the original Sonic 2 Clone Driver that made the hacks that used it suffer. Today, simply sticking to Sonic 2's driver would be a better choice.
Come the Sonic 2 Clone Driver v2, an attempt at making as close a mimicry of S2's driver as possible: the aforementioned errors were corrected, and many more S2 elements were crammed in, in an effort to make the drivers near indistinguishable.
The purpose of the Sonic 2 Clone Driver v2 is not the same as its predecessor: while the original was made for ease-of-use, the Sonic 2 Clone Driver v2 exists for the sake of pushing the Mega Drive's hardware to its limit, by avoiding the biggest obstacle: the Z80's limitations. Problem areas such as driver size, and poor DAC quality, can be avoided by not using a Z80-based driver such as Sonic 2's or even Sonic 3's. This allows a hack to push its sounds to the limit, without having to downgrade to the smaller feature pool of Sonic 1's original driver.
So, what isn't the Sonic 2 Clone Driver v2?
As said before, the Sonic 2 Clone Driver v2 was not created for the purpose of making the process of adding custom music easier, rather, it was created for those that wished to implement features that the Z80 would not allow, due to its limitations. One example can be seen in the hack Sonic 2 Recreation, a hack that was based on Sonic 2, but used a 68k-based driver (a heavily modified version of the original Sonic 2 Clone Driver) because a Z80-based driver would not allow all of the features needed. The Sonic 2 Clone Driver v2 features Mega PCM, a custom DAC driver only available for 68k-based sound drivers. Mega PCM allows for greater playback quality and control. This is just one of the things possible when the sound driver is not entirely based on the Z80.
Of course, 68k-based drivers have their downsides.
Sonic 1's driver operates on the 68k, the main processor of the Mega Drive. Sonic 2's driver operates on the Z80, the sound co-processor. Right off the bat, there's the obvious performance hit. It may not be much, but is it worth it? There is also the RAM requirement: Sonic 2's driver just uses the Z80's RAM, which there is plenty of. In contrast, Sonic 1's driver uses $5C0 bytes of the very RAM that has to be juggled with the level chunks, blocks, layout, decompression queues, camera RAM, and more. Again, the important question is, is that worth it? What would all that RAM and performance be going into? If your answer is 'just doing something that Sonic 2's driver can already do', then this driver is not for you.
Is your hack going to be the next Jester's Challenge? Are you doing some complicated Mega CD work that the Z80 can't handle? You need to know if your hack's goals justify the costs.
If you just want to have S3K music in your hack, go use S3K's driver (or better yet, a good version of S3K's driver), or a (modern!) music-porting tool.
That said, by using this driver, you acknowledge that if I find it being used just so you can use S3K music, I will call you out on it.
Features
Spoiler
In its unchanged state, the sound slot allocation is a little funny. Here's the layout (Git only; in Xenowhirl's 2007 disasm, the layout is stock, unless you make the sound IDs dynamic):
$00 - Silence
$01-$1F - Music
$20-$7F - Blank
$80-$D0 - SFX
$D1-$F9 - Blank
$FA-$FF - Flags
To change this, adjust s2.constants.asm's 'idstart's and 'Mus/SndID_End's (Sonic 2 Git disassembly), or Constants.asm's 'bgm__First' and 'sfx__First' (Sonic 1 Git disassembly).
- Git disasm comments and formatting - You'll no longer be left in the dark as to what the heck you're looking at
- Git and Hivebrain labels - To do what no one else could be bothered to do, apparently. Guides are no longer a guessing game (now part of S1 Git disasm)
- Clean changes - Most of my own changes, and those from other sources, are commented, identifiable and with reasons given
- Now with more Sonic 2 - The original Sonic 2 Clone Driver didn't have these S2 features:
- Priorities
- PSGs
- The actual Sonic 2 Sega PCM
- Spin Dash support (rev increases in pitch)
- Gloop support (only plays every other time it's called)
- StopSFX sound command (used by EHZ boss' propeller)
- SFX-only priorities list
- Runs at full speed on PAL consoles ("PAL mode")
- Working speedup tempos
- More accurate tempos in general
- Song-sensitive PAL mode (S2's drowning theme plays slower on PAL)
- Priorities
- Now with more Sonic 3
- PSGs
- PSG flags (reset, rest)
- PSG frequencies
- Universal Voice Bank
- DAC samples (S3+S&K+S3D)
- Tempo algorithm
- Continuous SFX system
- PSGs
- Now with more... Crackers?! - DACs included
- Less HAX - Real support for music slots >=$E0 (now optional part of S1 Git disasm)
- More HAX - Real support for music slots <$80 (Git only)
- Absolute voice pointers - Now you can put your voices anywhere!~
- "Only limited by the RAM size" - Up to $7C DAC sample slots
- More sound queues - Less developer oversight, more music queuing (currently at 4, the same as Sonic 2)
- Optional 68k Sega chant playback - Greatly optimised, too
- Some optimisation - Should make up for the additional code
- SMPS2ASM - Edit music and sounds in ASM, and port them with ease. "Hex editor", what's that?
- Mega PCM - High-quality DPCM/PCM playback, with greater playback control
In its unchanged state, the sound slot allocation is a little funny. Here's the layout (Git only; in Xenowhirl's 2007 disasm, the layout is stock, unless you make the sound IDs dynamic):
$00 - Silence
$01-$1F - Music
$20-$7F - Blank
$80-$D0 - SFX
$D1-$F9 - Blank
$FA-$FF - Flags
To change this, adjust s2.constants.asm's 'idstart's and 'Mus/SndID_End's (Sonic 2 Git disassembly), or Constants.asm's 'bgm__First' and 'sfx__First' (Sonic 1 Git disassembly).
Requirements
Spoiler
- The following games and disassemblies are supported:
- Sonic 2 - Git disassembly, Xenowhirl's 2007 disassembly
- Sonic 1 - Git disassembly (AS branch)
- Sonic 2 - Git disassembly, Xenowhirl's 2007 disassembly
- Sound files must be in SMPS2ASM v0.2 (.asm) format; assembled (.bin) files are unsupported
- This driver is designed for use with the AS Macro Assembler
- Users of Xenowhirl's 2007 disassembly will need to update their copy of AS to get the driver to build properly
Downloads
Guides
Spoiler
Installation
Optimising VBlank Routines (in Sonic 2)
Extend + Enhance Sound Test
How to Play DPCM/PCM Samples During Gameplay
Spoiler
Sonic 2 Git disassembly
Sonic 2 Xenowhirl 2007 disassembly
Sonic 1 Git disassembly
Spoiler
SETTING UP
Disassembly files
REMOVING THE Z80 DRIVER AND REPLACING ITS FUNCTIONS
s2.asm
REMOVING Z80 DRIVER LEFTOVERS AND ADDING NEW DRIVER
s2.asm
REPLACING CONSTANTS AND ADJUSTING RAM
s2.constants.asm
Disassembly files
Spoiler
Delete both s2.sounddriver.asm and the contents of the sound folder. Following that, extract the contents of the Base files folder in the 7z file into your now-empty sound folder, and then extract the contents of the Sonic 2 files folder on top of it.
REMOVING THE Z80 DRIVER AND REPLACING ITS FUNCTIONS
s2.asm
Spoiler
Open s2.asm, and go to Snd_Driver, you'll see this:
Delete it.
Find VintRet and beneath the label, add this:
Go to loc_748 and replace the rts with this:
Go to loc_1072 and, after this...
...add this:
Now find JmpTo_SoundDriverLoad and replace it with this:
Now find PlayMusic, and replace it with this:
Below that is PlaySound. Replace it with this:
Below that is PlaySoundStereo. Replace it with this:
Delete the entirety of the original PlaySoundLocal.
Go to PauseGame and replace this...
...with this:
Now go to Pause_Resume and replace this...
...with this:
Now find Pause_SlowMo, and replace this...
...with this:
Then find SpecialStage_Unpause and replace this...
...with this:
Now find sndDriverInput and delete the entire thing. Then delete every reference to it.
Snd_Driver: save include "s2.sounddriver.asm" ; CPU Z80 restore padding off !org (Snd_Driver+Size_of_Snd_driver_guess) ; don't worry; I know what I'm doing ; loc_ED04C: Snd_Driver_End:
Delete it.
Find VintRet and beneath the label, add this:
jsr (UpdateMusic).l ; update Sonic 2 Clone Driver v2 VintRet_NoMusic:
Go to loc_748 and replace the rts with this:
addq.l #4,sp bra.w VintRet_NoMusic
Go to loc_1072 and, after this...
bsr.w Do_Updates
...add this:
jsr (UpdateMusic).l
Now find JmpTo_SoundDriverLoad and replace it with this:
; --------------------------------------------------------------------------- ; Load DAC driver (Mega PCM) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| JmpTo_SoundDriverLoad ; Misnomer SoundDriverLoad: move.w #$100,(Z80_Bus_Request).l ; stop the Z80 move.w #$100,(Z80_Reset).l ; reset the Z80 ; load Mega PCM (kosinski-compressed) lea (MegaPCM).l,a0 ; source lea (Z80_RAM).l,a1 ; destination bsr.w KosDec ; load Mega PCM's DAC table (uncompressed) lea (DAC_Table).l,a0 ; start at beginning of DAC_Table move.w #(DAC_Table_end-DAC_Table)-1,d1 ; length of table (for dbf loop) - move.b (a0)+,(a1)+ ; write a byte of table to Z80 RAM (after Mega PCM) dbf d1,- ; loop moveq #0,d1 move.w d1,(Z80_Reset).l nop nop nop nop move.w #$100,(Z80_Reset).l ; reset the Z80 move.w d1,(Z80_Bus_Request).l ; start the Z80 rts ; End of function SoundDriverLoad
Now find PlayMusic, and replace it with this:
; sub_135E: PlayMusic: tst.b (Clone_Driver_RAM+v_playsnd1).w bne.s + move.b d0,(Clone_Driver_RAM+v_playsnd1).w rts + move.b d0,(Clone_Driver_RAM+v_playsnd4).w rts ; End of function PlayMusic
Below that is PlaySound. Replace it with this:
; sub_137C: PlaySoundLocal: tst.b render_flags(a0) bpl.s + ; rts ; sub_1370: PlaySound: move.b d0,(Clone_Driver_RAM+v_playsnd2).w + rts ; End of function PlaySoundLocal
Below that is PlaySoundStereo. Replace it with this:
; sub_1376: PlaySoundStereo: move.b d0,(Clone_Driver_RAM+v_playsnd3).w rts ; End of function PlaySoundStereo ; --------------------------------------------------------------------------- ; Subroutine to play a DAC sample ; --------------------------------------------------------------------------- PlaySample: stopZ80 move.b d0,(z80_dac_sample).l startZ80 rts ; End of function PlaySample
Delete the entirety of the original PlaySoundLocal.
Go to PauseGame and replace this...
+ move.w #1,(Game_paused).w ; freeze time move.b #MusID_Pause,(Music_to_play).w ; pause music
...with this:
+ move.w #1,(Game_paused).w ; freeze time move.b #1,(Clone_Driver_RAM+f_stopmusic).w ; pause music
Now go to Pause_Resume and replace this...
Pause_Resume: move.b #MusID_Unpause,(Music_to_play).w
...with this:
Pause_Resume: move.b #$80,(Clone_Driver_RAM+f_stopmusic).w ; unpause music
Now find Pause_SlowMo, and replace this...
move.b #MusID_Unpause,(Music_to_play).w
...with this:
move.b #$80,(Clone_Driver_RAM+f_stopmusic).w ; unpause music
Then find SpecialStage_Unpause and replace this...
move.b #MusID_Unpause,(Music_to_play).w
...with this:
move.b #$80,(Clone_Driver_RAM+f_stopmusic).w ; unpause music
Now find sndDriverInput and delete the entire thing. Then delete every reference to it.
REMOVING Z80 DRIVER LEFTOVERS AND ADDING NEW DRIVER
s2.asm
Spoiler
Search for "SndDAC_Start:" and above it you'll see this:
Delete it and everything from SndDAC_Start up to (and including) Mus_Continue.
Find the label Snd_Sega and above it you'll find this:
Delete it and everything from there up to (but not including) "; end of 'ROM'". In its place, put this:
Find (the original) SoundDriverLoad and delete the entire subroutine.
Now delete everything from DecompressSoundDriver to (and including) sub_EC0DE.
Find this...
...and just delete the 'movewZ80CompSize' entry so you have this:
cnop -Size_of_DAC_samples, $8000
Delete it and everything from SndDAC_Start up to (and including) Mus_Continue.
Find the label Snd_Sega and above it you'll find this:
cnop -Size_of_SEGA_sound, $8000
Delete it and everything from there up to (but not including) "; end of 'ROM'". In its place, put this:
include "sound/Sonic 2 Clone Driver v2 - Compatibility.asm"
Find (the original) SoundDriverLoad and delete the entire subroutine.
Now delete everything from DecompressSoundDriver to (and including) sub_EC0DE.
Find this...
shared word_728C_user,Obj5F_MapUnc_7240,off_3A294,MapRUnc_Sonic,movewZ80CompSize
...and just delete the 'movewZ80CompSize' entry so you have this:
shared word_728C_user,Obj5F_MapUnc_7240,off_3A294,MapRUnc_Sonic
REPLACING CONSTANTS AND ADJUSTING RAM
s2.constants.asm
Spoiler
In s2.constants.asm, look for this...
...and replace the whole list with this:
Underneath that, replace the Sound ID list with this:
Now to add a RAM address constant.
Free up that $600 through however you choose. Then slap the label "Clone_Driver_RAM" before it. Note, however, that the Sonic 2 Clone Driver v2 only requires $3A8 bytes of RAM (unless you have the Special SFXs enabled). While we're here in RAM, some areas that were reserved for the old Z80 driver are now unused. You can delete their labels and use the RAM for something else, if you want. These values are:
The Size_of_DAC_samples, Size_of_SEGA_sound and Size_of_Snd_driver_guess constants can also be removed.
; Music IDs offset := zMasterPlaylist ptrsize := 1 idstart := $81
...and replace the whole list with this:
; Music IDs
offset := MusicIndex
ptrsize := 4
idstart := 1
; $00 is reserved for silence
MusID__First = idstart
MusID_2PResult = id(ptr_mus81) ; 01
MusID_EHZ = id(ptr_mus82) ; 02
MusID_MCZ_2P = id(ptr_mus83) ; 03
MusID_OOZ = id(ptr_mus84) ; 04
MusID_MTZ = id(ptr_mus85) ; 05
MusID_HTZ = id(ptr_mus86) ; 06
MusID_ARZ = id(ptr_mus87) ; 07
MusID_CNZ_2P = id(ptr_mus88) ; 08
MusID_CNZ = id(ptr_mus89) ; 09
MusID_DEZ = id(ptr_mus8A) ; 0A
MusID_MCZ = id(ptr_mus8B) ; 0B
MusID_EHZ_2P = id(ptr_mus8C) ; 0C
MusID_SCZ = id(ptr_mus8D) ; 0D
MusID_CPZ = id(ptr_mus8E) ; 0E
MusID_WFZ = id(ptr_mus8F) ; 0F
MusID_HPZ = id(ptr_mus90) ; 10
MusID_Options = id(ptr_mus91) ; 11
MusID_SpecStage = id(ptr_mus92) ; 12
MusID_Boss = id(ptr_mus93) ; 13
MusID_EndBoss = id(ptr_mus94) ; 14
MusID_Ending = id(ptr_mus95) ; 15
MusID_SuperSonic = id(ptr_mus96) ; 16
MusID_Invincible = id(ptr_mus97) ; 17
MusID_ExtraLife = id(ptr_mus98) ; 18
MusID_Title = id(ptr_mus99) ; 19
MusID_EndLevel = id(ptr_mus9A) ; 1A
MusID_GameOver = id(ptr_mus9B) ; 1B
MusID_Continue = id(ptr_mus9C) ; 1C
MusID_Emerald = id(ptr_mus9D) ; 1D
MusID_Credits = id(ptr_mus9E) ; 1E
MusID_Countdown = id(ptr_mus9F) ; 1F
MusID__End = id(ptr_musend) ; 20
if MOMPASS == 2
if MusID__End > SndID__First
fatal "You have too many MusPtrs. MusID__End ($\{MusID__End}) can't exceed SndID__First ($\{SndID__First})."
endif
endif
Underneath that, replace the Sound ID list with this:
; Sound IDs
offset := SoundIndex
ptrsize := 4
idstart := $80
SndID__First = idstart
SndID_Jump = id(ptr_sndA0) ; 80
SndID_Checkpoint = id(ptr_sndA1) ; 81
SndID_SpikeSwitch = id(ptr_sndA2) ; 82
SndID_Hurt = id(ptr_sndA3) ; 83
SndID_Skidding = id(ptr_sndA4) ; 84
SndID_BlockPush = id(ptr_sndA5) ; 85
SndID_HurtBySpikes = id(ptr_sndA6) ; 86
SndID_Sparkle = id(ptr_sndA7) ; 87
SndID_Beep = id(ptr_sndA8) ; 88
SndID_SSItem = id(ptr_sndA9) ; 89 ; Sonic 1 leftover
SndID_Splash = id(ptr_sndAA) ; 8A
SndID_Swish = id(ptr_sndAB) ; 8B
SndID_BossHit = id(ptr_sndAC) ; 8C
SndID_InhalingBubble = id(ptr_sndAD) ; 8D
SndID_ArrowFiring = id(ptr_sndAE) ; 8E
SndID_LavaBall = id(ptr_sndAE) ; 8E
SndID_Shield = id(ptr_sndAF) ; 8F
SndID_LaserBeam = id(ptr_sndB0) ; 90
SndID_Electric = id(ptr_sndB1) ; 91 ; Sonic 1 leftover
SndID_Drown = id(ptr_sndB2) ; 92
SndID_FireBurn = id(ptr_sndB3) ; 93
SndID_Bumper = id(ptr_sndB4) ; 94
SndID_Ring = id(ptr_sndB5) ; 95
SndID_RingRight = id(ptr_sndB5) ; 95
SndID_SpikesMove = id(ptr_sndB6) ; 96
SndID_Rumbling = id(ptr_sndB7) ; 97
SndID_Smash = id(ptr_sndB9) ; 99
SndID_SSGlass = id(ptr_sndBA) ; 9A ; Sonic 1 leftover
SndID_DoorSlam = id(ptr_sndBB) ; 9B
SndID_SpindashRelease = id(ptr_sndBC) ; 9C
SndID_Hammer = id(ptr_sndBD) ; 9D
SndID_Roll = id(ptr_sndBE) ; 9E
SndID_ContinueJingle = id(ptr_sndBF) ; 9F
SndID_CasinoBonus = id(ptr_sndC0) ; A0
SndID_Explosion = id(ptr_sndC1) ; A1
SndID_WaterWarning = id(ptr_sndC2) ; A2
SndID_EnterGiantRing = id(ptr_sndC3) ; A3 ; Sonic 1 leftover
SndID_BossExplosion = id(ptr_sndC4) ; A4
SndID_TallyEnd = id(ptr_sndC5) ; A5
SndID_RingSpill = id(ptr_sndC6) ; A6
SndID_ChainRise = id(ptr_sndC7) ; A7 ; Sonic 1 leftover
SndID_Flamethrower = id(ptr_sndC8) ; A8
SndID_Bonus = id(ptr_sndC9) ; A9 ; Sonic 1 leftover
SndID_SpecStageEntry = id(ptr_sndCA) ; AA
SndID_SlowSmash = id(ptr_sndCB) ; AB
SndID_Spring = id(ptr_sndCC) ; AC
SndID_Blip = id(ptr_sndCD) ; AD
SndID_RingLeft = id(ptr_sndCE) ; AE
SndID_Signpost = id(ptr_sndCF) ; AF
SndID_CNZBossZap = id(ptr_sndD0) ; B0
SndID_Signpost2P = id(ptr_sndD3) ; B3
SndID_OOZLidPop = id(ptr_sndD4) ; B4
SndID_SlidingSpike = id(ptr_sndD5) ; B5
SndID_CNZElevator = id(ptr_sndD6) ; B6
SndID_PlatformKnock = id(ptr_sndD7) ; B7
SndID_BonusBumper = id(ptr_sndD8) ; B8
SndID_LargeBumper = id(ptr_sndD9) ; B9
SndID_Gloop = id(ptr_sndDA) ; BA
SndID_PreArrowFiring = id(ptr_sndDB) ; BB
SndID_Fire = id(ptr_sndDC) ; BC
SndID_ArrowStick = id(ptr_sndDD) ; BD
SndID_Helicopter = id(ptr_sndDE) ; BE
SndID_SuperTransform = id(ptr_sndDF) ; BF
SndID_SpindashRev = id(ptr_sndE0) ; C0
SndID_Rumbling2 = id(ptr_sndE1) ; C1
SndID_CNZLaunch = id(ptr_sndE2) ; C2
SndID_Flipper = id(ptr_sndE3) ; C3
SndID_HTZLiftClick = id(ptr_sndE4) ; C4
SndID_Leaves = id(ptr_sndE5) ; C5
SndID_MegaMackDrop = id(ptr_sndE6) ; C6
SndID_DrawbridgeMove = id(ptr_sndE7) ; C7
SndID_QuickDoorSlam = id(ptr_sndE8) ; C8
SndID_DrawbridgeDown = id(ptr_sndE9) ; C9
SndID_LaserBurst = id(ptr_sndEA) ; CA
SndID_Scatter = id(ptr_sndEB) ; CB
SndID_LaserFloor = id(ptr_sndEB) ; CB
SndID_Teleport = id(ptr_sndEC) ; CC
SndID_Error = id(ptr_sndED) ; CD
SndID_MechaSonicBuzz = id(ptr_sndEE) ; CE
SndID_LargeLaser = id(ptr_sndEF) ; CF
SndID_OilSlide = id(ptr_sndF0) ; D0
SndID__End = id(ptr_sndend) ; D1
; Special sound IDs
offset := Sound_ExIndex
ptrsize := 4
idstart := $FA
FlgID__First = idstart
MusID_StopSFX = id(ptr_flgFA) ; FA
MusID_FadeOut = id(ptr_flgFB) ; FB
SndID_SegaSound = id(ptr_flgFC) ; FC
MusID_SpeedUp = id(ptr_flgFD) ; FD
MusID_SlowDown = id(ptr_flgFE) ; FE
MusID_Stop = id(ptr_flgFF) ; FF
FlgID__End = id(ptr_flgend) ; FF + 1 (rollover)
if MOMPASS == 2
if SndID__End > FlgID__First
fatal "You have too many SndPtrs. SndID__End ($\{SndID__End}) can't exceed FlgID__First ($\{FlgID__First})."
endif
endif
Now to add a RAM address constant.
Free up that $600 through however you choose. Then slap the label "Clone_Driver_RAM" before it. Note, however, that the Sonic 2 Clone Driver v2 only requires $3A8 bytes of RAM (unless you have the Special SFXs enabled). While we're here in RAM, some areas that were reserved for the old Z80 driver are now unused. You can delete their labels and use the RAM for something else, if you want. These values are:
- Music_to_play
- SFX_to_play
- SFX_to_play_2
- unk_FFE3
- Music_to_play_2
The Size_of_DAC_samples, Size_of_SEGA_sound and Size_of_Snd_driver_guess constants can also be removed.
Sonic 2 Xenowhirl 2007 disassembly
Spoiler
SETTING UP
Disassembly files
REMOVING THE Z80 DRIVER AND REPLACING ITS FUNCTIONS
s2.asm
REMOVING Z80 DRIVER LEFTOVERS AND ADDING NEW DRIVER
s2.asm
REPLACING CONSTANTS
s2.constants.asm
TWEAKING THE DRIVER'S SETTINGS
Sonic 2 Clone Driver v2 - Compatibility.asm
Disassembly files
Spoiler
Delete both s2.sounddriver.asm and the contents of the sound folder. Following that, extract the contents of the Base files folder in the 7z file into your now-empty sound folder, and then extract the contents of the Sonic 2 files folder on top of it.
REMOVING THE Z80 DRIVER AND REPLACING ITS FUNCTIONS
s2.asm
Spoiler
Open s2.asm, and go to Snd_Driver, you'll see this:
Delete it.
Find VintRet and beneath the label, add this:
Go to loc_748 and replace the rts with this:
Go to loc_1072 and, after this...
...add this:
Now find JmpTo_SoundDriverLoad and replace it with this:
Now find PlayMusic, and replace it with this:
Below that is PlaySound. Replace it with this:
Below that is PlaySoundStereo. Replace it with this:
Delete the entirety of the original PlaySoundLocal.
Go to PauseGame and replace this...
...with this:
Now go to loc_13F2 and replace this...
...with this:
Now find Pause_SlowMo, and replace this...
...with this:
Then find loc_541A and replace this...
...with this:
Now find sndDriverInput and delete the entire thing. Then delete every reference to it.
Snd_Driver:
if assembleZ80SoundDriver
include "s2.sounddriver.asm" ; CPU Z80
CPU 68000
padding off
listing off
supmode on
!org (Snd_Driver+Size_of_Snd_driver_guess) ; don't worry; I know what I'm doing
else
BINCLUDE "sound/Sound driver.bin"
zPalModeByte = 7
zComRange = $1B80
endif
; loc_ED04C:
Snd_Driver_End:
Delete it.
Find VintRet and beneath the label, add this:
jsr (UpdateMusic).l ; update Sonic 2 Clone Driver v2 VintRet_NoMusic:
Go to loc_748 and replace the rts with this:
addq.l #4,sp bra.w VintRet_NoMusic
Go to loc_1072 and, after this...
bsr.w DemoTime
...add this:
jsr (UpdateMusic).l
Now find JmpTo_SoundDriverLoad and replace it with this:
; --------------------------------------------------------------------------- ; Load DAC driver (Mega PCM) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| JmpTo_SoundDriverLoad ; Misnomer SoundDriverLoad: move.w #$100,(Z80_Bus_Request).l ; stop the Z80 move.w #$100,(Z80_Reset).l ; reset the Z80 ; load Mega PCM (kosinski-compressed) lea (MegaPCM).l,a0 ; source lea (Z80_RAM).l,a1 ; destination bsr.w KosDec ; load Mega PCM's DAC table (uncompressed) lea (DAC_Table).l,a0 ; start at beginning of DAC_Table move.w #(DAC_Table_end-DAC_Table)-1,d1 ; length of table (for dbf loop) - move.b (a0)+,(a1)+ ; write a byte of table to Z80 RAM (after Mega PCM) dbf d1,- ; loop moveq #0,d1 move.w d1,(Z80_Reset).l nop nop nop nop move.w #$100,(Z80_Reset).l ; reset the Z80 move.w d1,(Z80_Bus_Request).l ; start the Z80 rts ; End of function SoundDriverLoad
Now find PlayMusic, and replace it with this:
; sub_135E: PlayMusic: tst.b (Clone_Driver_RAM+v_playsnd1).w bne.s + move.b d0,(Clone_Driver_RAM+v_playsnd1).w rts + move.b d0,(Clone_Driver_RAM+v_playsnd4).w rts ; End of function PlayMusic
Below that is PlaySound. Replace it with this:
; sub_137C: PlaySoundLocal: tst.b render_flags(a0) bpl.s + ; rts ; sub_1370: PlaySound: move.b d0,(Clone_Driver_RAM+v_playsnd2).w + rts ; End of function PlaySoundLocal
Below that is PlaySoundStereo. Replace it with this:
; sub_1376: PlaySoundStereo: move.b d0,(Clone_Driver_RAM+v_playsnd3).w rts ; End of function PlaySoundStereo ; --------------------------------------------------------------------------- ; Subroutine to play a DAC sample ; --------------------------------------------------------------------------- PlaySample: stopZ80 move.b d0,(z80_dac_sample).l startZ80 rts ; End of function PlaySample
Delete the entirety of the original PlaySoundLocal.
Go to PauseGame and replace this...
+ move.w #1,(Game_paused).w ; freeze time move.b #-2,(Music_to_play).w ; pause music
...with this:
+ move.w #1,(Game_paused).w ; freeze time move.b #1,(Clone_Driver_RAM+f_stopmusic).w ; pause music
Now go to loc_13F2 and replace this...
loc_13F2: move.b #-1,(Music_to_play).w
...with this:
loc_13F2: move.b #$80,(Clone_Driver_RAM+f_stopmusic).w ; unpause music
Now find Pause_SlowMo, and replace this...
move.b #-1,(Music_to_play).w
...with this:
move.b #$80,(Clone_Driver_RAM+f_stopmusic).w ; unpause music
Then find loc_541A and replace this...
move.b #-1,(Music_to_play).w
...with this:
move.b #$80,(Clone_Driver_RAM+f_stopmusic).w ; unpause music
Now find sndDriverInput and delete the entire thing. Then delete every reference to it.
REMOVING Z80 DRIVER LEFTOVERS AND ADDING NEW DRIVER
s2.asm
Spoiler
Search for "SndDAC_Start:" and above it you'll see this:
Delete it and everything from SndDAC_Start up to (and including) Mus_Continue.
Find the label Snd_Sega and above it you'll find this:
Delete it and everything from there up to (but not including) "; end of 'ROM'". In its place, put this:
Find (the original) SoundDriverLoad and delete the entire routine. You might as well since it's gonna become unused anyway.
Now delete everything from DecompressSoundDriver to (and including) sub_EC0DE.
Find
And just delete the last entry so you have this:
; --------------------------------------------------------------------------- ; Filler (free space) ; --------------------------------------------------------------------------- ; the DAC data has to line up with the end of the bank. if assembleZ80SoundDriver ; actually it only has to fit within one bank, but we'll line it up to the end anyway ; because the padding gives the sound driver some room to grow cnop -Size_of_DAC_samples, $8000 else org $F0000-Size_of_DAC_samples ; not as much leeway here endif
Delete it and everything from SndDAC_Start up to (and including) Mus_Continue.
Find the label Snd_Sega and above it you'll find this:
; ---------------------------------------------------------------------------------- ; Filler (free space) ; ---------------------------------------------------------------------------------- ; the PCM data has to line up with the end of the bank. if assembleZ80SoundDriver cnop -Size_of_SEGA_sound, $8000 else org $F8000-Size_of_SEGA_sound ; not as much leeway here endif
Delete it and everything from there up to (but not including) "; end of 'ROM'". In its place, put this:
include "sound/Sonic 2 Clone Driver v2 - Compatibility.asm"
Find (the original) SoundDriverLoad and delete the entire routine. You might as well since it's gonna become unused anyway.
Now delete everything from DecompressSoundDriver to (and including) sub_EC0DE.
Find
shared word_728C_user,Obj5F_MapUnc_7240,off_3A294,MapRUnc_Sonic,movewZ80CompSize
And just delete the last entry so you have this:
shared word_728C_user,Obj5F_MapUnc_7240,off_3A294,MapRUnc_Sonic
REPLACING CONSTANTS
s2.constants.asm
Spoiler
Now to add a RAM address constant.
Free up that $600 through however you choose. Then slap the label "Clone_Driver_RAM" before it. Note, however, that the Sonic 2 Clone Driver v2 only requires $3A8 bytes of RAM (unless Special SFXs are enabled). While we're here in RAM, some areas that were reserved for the old Z80 driver are now unused. You can delete their labels and use the RAM for something else, if you want. These values are:
The Size_of_DAC_samples, Size_of_SEGA_sound and Size_of_Snd_driver_guess equates can also be removed.
Free up that $600 through however you choose. Then slap the label "Clone_Driver_RAM" before it. Note, however, that the Sonic 2 Clone Driver v2 only requires $3A8 bytes of RAM (unless Special SFXs are enabled). While we're here in RAM, some areas that were reserved for the old Z80 driver are now unused. You can delete their labels and use the RAM for something else, if you want. These values are:
- Music_to_play
- SFX_to_play
- SFX_to_play_2
- Music_to_play_2
The Size_of_DAC_samples, Size_of_SEGA_sound and Size_of_Snd_driver_guess equates can also be removed.
TWEAKING THE DRIVER'S SETTINGS
Sonic 2 Clone Driver v2 - Compatibility.asm
Spoiler
This does most of the work itself: open Sonic 2 Clone Driver v2 - Compatibility.asm (in the sound folder). This here, depending on what disassembly of which game you're using, changes some setting to ensure maximum compatibility. Currently, this is set up to target the Sonic 2 Git disassembly. We don't want that. At the very top of the file, as the comments should tell you, set TargetDisasm to 2.
Sonic 1 Git disassembly
Spoiler
SETTING UP
Disassembly files
REPLACING THE ORIGINAL DRIVER AND ITS FUNCTIONS
sonic.asm, sub PlaySound.asm
ADJUSTING CONSTANTS
Constants.asm
REMOVING VARIABLES
Variables.asm
TWEAKING THE DRIVER'S SETTINGS
Sonic 2 Clone Driver v2 - Compatibility.asm
NOTES
If you have the Spin Dash in your hack, you'll likely have the Spin Dash sound in there too. In Sonic 2 Clone Driver v2 - Compatibility.asm, be sure to set the SndID_Spindash equate the the value of your Spin Dash rev SFX.
Disassembly files
Spoiler
Delete both s1.sounddriver.asm and the contents of the sound folder. Following that, extract the contents of the Base files folder in the 7z file into your now-empty sound folder, and then extract the contents of the Sonic 1 files folder on top of it.
REPLACING THE ORIGINAL DRIVER AND ITS FUNCTIONS
sonic.asm, sub PlaySound.asm
Spoiler
Open sonic.asm, and find SoundDriverLoad. Replace it with this:
Open _incObj/sub PlaySound.asm, and find PlaySound. Replace it with this:
Below that is PlaySound_Special. Replace it with this:
Delete PlaySound_Unused.
Go to the end of sonic.asm, and look for this:
Replace it with this:
; --------------------------------------------------------------------------- ; Load DAC driver (Mega PCM) ; --------------------------------------------------------------------------- ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| SoundDriverLoad: ; XREF: GameClrRAM; GM_Title stopZ80 resetZ80 ; load Mega PCM (kosinski-compressed) lea (MegaPCM).l,a0 ; source lea (z80_ram).l,a1 ; destination bsr.w KosDec ; load Mega PCM's DAC table (uncompressed) lea (DAC_Table).l,a0 ; start at beginning of DAC_Table move.w #(DAC_Table_End-DAC_Table)-1,d1 ; length of table (for dbf loop) - move.b (a0)+,(a1)+ ; write a byte of table to Z80 RAM (after Mega PCM) dbf d1,- ; loop moveq #0,d1 move.w d1,(z80_reset).l nop nop nop nop resetZ80 move.w d1,(z80_bus_request).l ; start the Z80 rts ; End of function SoundDriverLoad
Open _incObj/sub PlaySound.asm, and find PlaySound. Replace it with this:
PlaySound: tst.b (v_snddriver_ram+v_playsnd1).w bne.s + move.b d0,(v_snddriver_ram+v_playsnd1).w rts + move.b d0,(v_snddriver_ram+v_playsnd4).w rts ; End of function PlaySound
Below that is PlaySound_Special. Replace it with this:
PlaySound_Special: tst.b (v_snddriver_ram+v_playsnd2).w bne.s + move.b d0,(v_snddriver_ram+v_playsnd2).w rts + move.b d0,(v_snddriver_ram+v_playsnd3).w rts ; End of function PlaySound_Special ; --------------------------------------------------------------------------- ; Subroutine to play a DAC sample ; --------------------------------------------------------------------------- PlaySample: stopZ80 waitZ80 move.b d0,(z80_dac_sample).l startZ80 rts ; End of function PlaySample
Delete PlaySound_Unused.
Go to the end of sonic.asm, and look for this:
SoundDriver: include "s1.sounddriver.asm"
Replace it with this:
SoundDriver: include "sound/Sonic 2 Clone Driver v2 - Compatibility.asm"
ADJUSTING CONSTANTS
Constants.asm
Spoiler
In Constants.asm, look for this...
Change bgm__First to $01, then, below that, change sfx__First to $80, and spec__First to 'sfx__Last+1'.
After all that should be flg__First, and the other sound commands. Replace the whole thing with this:
Now, look for this:
Delete everything from there until (but not including) this:
Next up, find this:
And delete the following:
; Background music
Change bgm__First to $01, then, below that, change sfx__First to $80, and spec__First to 'sfx__Last+1'.
After all that should be flg__First, and the other sound commands. Replace the whole thing with this:
flg__First equ $FA sfx_Fade: equ ((ptr_flgFA-Sound_ExIndex)/4)+flg__First bgm_Fade: equ ((ptr_flgFB-Sound_ExIndex)/4)+flg__First sfx_Sega: equ ((ptr_flgFC-Sound_ExIndex)/4)+flg__First bgm_Speedup: equ ((ptr_flgFD-Sound_ExIndex)/4)+flg__First bgm_Slowdown: equ ((ptr_flgFE-Sound_ExIndex)/4)+flg__First bgm_Stop: equ ((ptr_flgFF-Sound_ExIndex)/4)+flg__First flg__Last: equ ((ptr_flgend-Sound_ExIndex-4)/4)+flg__First
Now, look for this:
; Sound driver constants
Delete everything from there until (but not including) this:
; VRAM data
Next up, find this:
; Z80 addresses
And delete the following:
- z80_dac3_pitch
- z80_dac_status
- z80_dac_sample
REMOVING VARIABLES
Variables.asm
Spoiler
This driver has its own RAM map, so we need to get rid of the original one.
Open up Variables.asm, and look for this:
Delete everything from there until this:
Open up Variables.asm, and look for this:
; ================================================================================= ; From here on, until otherwise stated, all offsets are relative to v_snddriver_ram ; =================================================================================
Delete everything from there until this:
; ================================================================================= ; From here on, no longer relative to sound driver RAM ; =================================================================================
TWEAKING THE DRIVER'S SETTINGS
Sonic 2 Clone Driver v2 - Compatibility.asm
Spoiler
This does most of the work itself: open Sonic 2 Clone Driver v2 - Compatibility.asm (in the sound folder). This here, depending on what disassembly of which game you're using, changes some setting to ensure maximum compatibility. Currently, this is set up to target the Sonic 2 Git disassembly. We don't want that. At the very top of the file, as the comments should tell you, set TargetDisasm to 3.
NOTES
If you have the Spin Dash in your hack, you'll likely have the Spin Dash sound in there too. In Sonic 2 Clone Driver v2 - Compatibility.asm, be sure to set the SndID_Spindash equate the the value of your Spin Dash rev SFX.
Optimising VBlank Routines (in Sonic 2)
Spoiler
PCM playback quality is dragged down by unnecessary Z80 interruptions. Here, we'll see to removing these. Most of them are in V-Int, though there are notable instances elsewhere.
First, search for this (if you're using the Git disassembly):
Or this, if you're using the Xenowhirl disassembly:
You should find it sandwiched between a stop and a start. Delete these first two. That covers H-Int
Now, onto V-Int.
Now for the rest.
First, search for this (if you're using the Git disassembly):
dma68kToVDP Sprite_Table_2,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM
Or this, if you're using the Xenowhirl disassembly:
dma68kToVDP Sprite_Table_2,$F800,$280,VRAM
You should find it sandwiched between a stop and a start. Delete these first two. That covers H-Int
Now, onto V-Int.
- VintSub0 (if you haven't already deleted them while removing sndDriverInput)
- loc_4C4, the other at loc_54A
- Vint0_noWater
- VintSub14
- VintSub8, the other is at loc_748
- Vint10_specialStage, the other at loc_86E
- VintSubA, with the other way over above loc_9B8
- VintSub1A
- VintSubC, with the other being at loc_BD6
- VintSub18
- VintSub16
- Do_ControllerPal (sub_E98 on Xenowhirl), the other at loc_EFE
Now for the rest.
- JoypadInit
- ClearScreen
- EndingSequence
Extend + Enhance Sound Test
Spoiler
Sonic 2 Git disassembly
Sonic 2 Xenowhirl 2007 disassembly
Sonic 1 Git disassembly
Spoiler
LEVEL SELECT SOUND TEST
OPTIONS SOUND TEST
Spoiler
Go to LevSelControls_CheckLR and remove these two lines:
Then remove these three:
Then change this...
...into this:
And remove this:
bcc.s + moveq #$7F,d0
Then remove these three:
cmpi.w #$80,d0 blo.s + moveq #0,d0
Then change this...
btst #button_A,d1 beq.s + addi.b #$10,d0 andi.b #$7F,d0 +
...into this:
btst #button_A,d1
beq.s +
addi.b #$10,d0
bcc.s +
moveq #0,d0
+
And remove this:
addi.w #$80,d0
OPTIONS SOUND TEST
Spoiler
Go to OptionScreen_Controls, and change this...
...into this:
Under that, remove this:
Then go to OptionScreen_Choices, and change this...
...into:
btst #button_A,d0 beq.s + addi.b #$10,d2 cmp.b d3,d2 bls.s + moveq #0,d2 +
...into this:
cmpi.b #2,(Options_menu_box).w
bne.s +
btst #button_A,d0
beq.s +
addi.b #$10,d2
bcc.s +
moveq #0,d2
+
Under that, remove this:
addi.w #$80,d0
Then go to OptionScreen_Choices, and change this...
dc.l ($80-1)<<24
...into:
dc.l ($FF<<24)
Sonic 2 Xenowhirl 2007 disassembly
Spoiler
LEVEL SELECT SOUND TEST
OPTIONS SOUND TEST
Spoiler
Go to LevSelControls_CheckLR and remove these two lines:
Then remove these three:
Then change this...
...into this:
And remove this:
bcc.s + moveq #$7F,d0
Then remove these three:
cmpi.w #$80,d0 blo.s + moveq #0,d0
Then change this...
btst #button_A,d1 beq.s + addi.b #$10,d0 andi.b #$7F,d0 +
...into this:
btst #button_A,d1
beq.s +
addi.b #$10,d0
bcc.s +
moveq #0,d0
+
And remove this:
addi.w #$80,d0
OPTIONS SOUND TEST
Spoiler
Go to OptionScreen_Controls, and change this...
...into this:
Under that, remove this:
Then go to OptionScreen_Choices, and change this...
...into:
btst #button_A,d0 beq.s + addi.b #$10,d2 cmp.b d3,d2 bls.s + moveq #0,d2 +
...into this:
cmpi.b #2,(Options_menu_box).w
bne.s +
btst #button_A,d0
beq.s +
addi.b #$10,d2
bcc.s +
moveq #0,d2
+
Under that, remove this:
addi.w #$80,d0
Then go to OptionScreen_Choices, and change this...
dc.l ($80-1)<<24
...into:
dc.l ($FF<<24)
Sonic 1 Git disassembly
Spoiler
LEVEL SELECT SOUND TEST
Spoiler
In sonic.asm, go to LevelSelect and change this...
...into this:
Then change this...
...into this:
After that, remove this line:
Then delete these lines:
After that, go to LevSel_SndTest, and change this...
...into this:
and remove this:
And then change this...
...into this:
Now go to LevSel_DrawSnd, and remove this line:
andi.b #btnABC+btnStart,(v_jpadpress1).w ; is A, B, C, or Start pressed?
...into this:
andi.b #btnB+btnStart,(v_jpadpress1).w ; is B or Start pressed?
Then change this...
bne.s LevSel_Level_SS ; if not, go to Level/SS subroutine
...into this:
beq.s .checkB ; if so, branch andi.b #btnStart,(v_jpadpress1).w ; is start pressed? beq.s LevelSelect ; if not, branch bra.s LevSel_Level_SS ; if so, go to Level/SS subroutine .checkB: andi.b #btnB,(v_jpadpress1).w ; is B pressed? beq.s LevelSelect ; if not, branch .soundtest:
After that, remove this line:
addi.w #$80,d0
Then delete these lines:
; This is a workaround for a bug, see Sound_ChkValue for more. ; Once you've fixed the bugs there, comment these four instructions out cmpi.w #bgm__Last+1,d0 ; is sound $80-$93 being played? blo.s LevSel_PlaySnd ; if yes, branch cmpi.w #sfx__First,d0 ; is sound $94-$9F being played? blo.s LevelSelect ; if yes, branch LevSel_PlaySnd:
After that, go to LevSel_SndTest, and change this...
andi.b #btnR+btnL,d1 ; is left/right pressed?
...into this:
andi.b #btnA+btnC+btnR+btnL,d1 ; is left/right/A/C pressed?
and remove this:
bhs.s LevSel_Right moveq #$4F,d0 ; if sound test moves below 0, set to $4F
And then change this...
btst #bitR,d1 ; is right pressed? beq.s LevSel_Refresh2 ; if not, branch addq.w #1,d0 ; add 1 to sound test cmpi.w #$50,d0 blo.s LevSel_Refresh2 moveq #0,d0 ; if sound test moves above $4F, set to 0 LevSel_Refresh2:
...into this:
btst #bitR,d1 ; is right pressed? beq.s LevSel_ButtonA ; if not, branch addq.w #1,d0 ; add 1 to sound test LevSel_ButtonA: btst #bitA,d1 ; is A pressed? beq.s LevSel_ButtonC ; if not, branch addi.b #$10,d0 ; add $10 to sound test bcc.s LevSel_ButtonC ; did the addition overflow? moveq #0,d0 ; if so, set value to $00 LevSel_ButtonC: btst #bitC,d1 ; is C pressed? beq.s LevSel_Refresh2 ; if not, branch subi.b #$10,d0 ; subtract $10 from sound test bcc.s LevSel_Refresh2 cmpi.b #$F0,d0 beq.s LevSel_Refresh2 ; do not set to 0 if already at 0 moveq #0,d0 ; if the subtraction overflowed, set value to $00 LevSel_Refresh2:
Now go to LevSel_DrawSnd, and remove this line:
addi.w #$80,d0
How to Play DPCM/PCM Samples During Gameplay
Spoiler
As Mega PCM's topic will tell you, you can play DPCM/PCM samples, not as part of the music, but during gameplay. Back in the installation guide, a subroutine called 'PlaySample' was added; we'll need to be using this.
Using it is identical to using PlayMusic, and the others: simply put the ID of the sample you want to play in d0, then branch to PlaySample, like so:
Using it is identical to using PlayMusic, and the others: simply put the ID of the sample you want to play in d0, then branch to PlaySample, like so:
move.b #$80,d0 jsr (PlaySample).w
Changelog
Spoiler
31/03/2014 (dd/mm/yyyy)
v2.0 (Initial release)
01/04/2014
v2.0.1
15/04/2014
v2.1
19/04/2014
v2.1.1
20/04/2014
v2.1.2
16/06/2014
v2.1.3
29/06/2014
v2.2
01/07/2014
v2.2.1
03/07/2014
v2.2.1.1
04/07/2014
v2.2.1.2
18/07/2014
v2.2.2
14/08/2014
v2.2.2.1
11/09/2014
v2.2.3
13/09/2014
v2.2.3.1
06/10/2014
v2.2.4
15/10/2014
v2.2.4.1
17/10/2014
v2.2.4.1b
27/12/2014
v2.2.5
21/02/2015
v2.2.5.1
03/03/2015
v2.2.5.2
09/03/2015
v2.2.6
09/07/2015
v2.3
v2.0 (Initial release)
- Ported to AS
- Replaced local labels with unique labels
- Added Hivebrain labels
- Added Mega PCM
- Applied 'Optimising Z80 Stops' guide
- Added SMPS2ASM
- Added S2 priorities
- Added S2 DACs
- Added S2 PSGs
- Added Spin Dash support
- Added Gloop support
- Fixed bug causing sounds with an index entry of >=$40 to crash
- Fixed v_playsnd3 to be fully usable
- Replaced S1's music with the original Clone Driver's music
- Replaced S1's sound effects with S2's sound effects
- Relocated Silence value to $00
- Extended starting sound slot from $81 to $01
- Relocated MusicIndex to above music 'BINCLUDE's
- Removed special SFX-related code
- Relocated sound commands from $E0-$E4 to $F9-$FD
01/04/2014
v2.0.1
- Removed unused SoundIndex entry
- Removed redundant Sega PCM alignment
- Fixed sound priority
- Used constants to make sound group changing more accessible
- Reworded >=$E0 sound bug explanation
15/04/2014
v2.1
- Relocated sound commands from $F9-$FD to $FB-$FF
- Fixed priorities list not including the sound commands ($FB-$FF)
- Adapted Sonic 2's feature of having the priorities system only apply to SFXs
- Added Sound Flag $FA, StopSFX, now back from Sonic 2, and fully functional
- Added S3+ PSG instruments
- Added S3+ DAC samples
- Added S3+ Universal Voice Bank
- Modified _smps2asm_inc.asm to have an option for the Clone Driver v2, 'SonicDriverVer = 0'
- Removed remainder of the Special SFXs ($D0-$DF), freeing up $60 bytes of RAM
- Rearranged data and indexes:
- Data (UniVoiceBank, PSG, Music, SFX) at bottom
- Indexes (PSG, Music, SFX) at top
- Data (UniVoiceBank, PSG, Music, SFX) at bottom
- Music and SFXs use absolute (longword) pointers for their Voices, this is to allow UniVoiceBank support
- Removed all 'Go_Index' nonsense, references are now direct
- Made Sega PCM ID dynamic
- Added Flag IDs
19/04/2014
v2.1.1
- Compressed Mega PCM Z80 code, DAC tables are still uncompressed though
- Readded Mega PCM .wav compatibility
- Matched S2 DAC pitches to those in S2's driver, but they're still inaccurate, the snare seems to be BETWEEN 3 and 4
- Added Crackers DACs
- Fixed SMPS2ASM's dLowerEchoedClapHit entry
20/04/2014
v2.1.2
- Relocated coordination flags from $E0+ to $FE+, as a result, there are now free DAC slots and a total of $7C DAC slots
- Corrected S3/K/3D DAC order
- Named all S3/K/3D/C DACs
- Removed cfStopSpecialFM4
16/06/2014
v2.1.3
- Removed more Special SFX remnants, namely v_special_voice_ptr
- Freed up a tiny amount of RAM by turning some byte-sized flags to bit-size. They are grouped under the RAM address 'misc_flags'. Flags include:
- v_gloop_toggle
- Spindash_LastSound_Flag
- v_ring_speaker
- f_updating_dac
- f_fadein_flag
- v_gloop_toggle
- f_updating_dac and f_fadein_flag been changed to a bit, so their 'On' state isn't defined by being set to $80, but to 1
- Removed f_fastmusic entirely, it's not even used in this version of the Community disasm. It's just v_1up_ram_copy's copy of f_speedup
- Fixed typo in instruction under PSFX_NotSpinDashRev label
- Rearranged RAM variables to group all unused RAM in one area ($19-$39)
- Split music and sound 'include's from main asm file, allowing users to update their s1.sounddriver.asm without overwriting their custom music and sound 'include's
- Done the above to the music and SFX pointers, also. Said pointers have also been moved to above their respective 'include's, for sake the of ease when updating
- Added missing equate under Sound_PlaySpecial
- Modified installation guide to feature a full-speed PAL audio fix, straight from MJ's Moonwalker
29/06/2014
v2.2
- Rearranged indexes and data again, now they are all located after the driver's code
- Reformatted PSGDoVolFX
- Ported three new PSG flags, two are used by S3K's PSGs, the final is unused, but added for the sake of completion
- Now using stock S3K PSGs instead of converted-to-S1 equivalents
- Ported S1 & S2 PSGs
- Added missing 'even' after the Universal Voice Bank
- Optimised the unused coordination flags' code
- Optimised some code under Sound_Play
- Corrected some comments
- Ported S3K's TempoWait, allowing full access to S3K-style tempos
- Added S2 speedup tempos, converted to S3K tempos
- Replaced the Original Clone Driver's modified S2 music with stock S2 music
01/07/2014
v2.2.1
- Removed 68k-freeze code in PlaySega, it has negative effects in Sonic 2
- Added coordination flag cfSilenceStopTrack
- Added coordination flag cfPlayDACSample
- Added coordination flag cfPlaySound
- Added coordination flag cfSetKey
- Added coordination flag cfSetVolume
- Added FMSilenceChannel
- Removed two unused coordination flags
- Redone PAL mode
- Replicated S2's ability to force PAL slowness on certain songs
03/07/2014
v2.2.1.1
- Optimised PAL mode
- Ported S2's PAL timer system
- Made PAL_Audio_CountDown part of the Clone Driver's RAM
04/07/2014
v2.2.1.2
- Removed some 'jsr's that interfered with the Stack
18/07/2014
v2.2.2
- Added fourth sound queue
- Replaced all 'jsr's with 'bsr.w's, and 'jmp's with 'bra.w's
- Made small optimisations under PBGM_BGMLoadMusic, PSGUpdate_NoteGoing, SetVoice_SendTL, UnpausedAllFM, FadeIn_FadedDone, FM_UpdateFreq
- Renamed Snd_FadeOutSFX and Snd_FadeOutSFX2
- Changed bcc into bhs under PSFX_TimerActive
- Optimised some of the Spin Dash rev code
- Optimised waitYM macro (nothing uses d2 afterwards, and bit instructions can affect memory)
- Restored cfUnused1 (cfSetCommunication)
- Removed Size_of_SegaPCM macro (unused leftover from 2.0 :P)
- Fixed error made while removing Special SFX code under FadeOut_TrackPSG
- Fixed (my) error in the smpsStopSpecial macro
- Optimised some code around PSFX_SFXInitPSG (code was made less efficient back when I was trying to fix the $40+ index bug)
- Fixed Sound_PlaySpecial (it didn't support absolute voice pointers, and also has the $40+ index bug)
14/08/2014
v2.2.2.1
- Made slight optimisation around the branch to TempoWait by removing the branch altogether :P
- Optimised some lsl into add
- Optimised some clr.l into move.l
- Optimised some branches from .w to .s
- Made a bunch of bsr.w into bsr.s
- Fixed (my) error in _smps2asm_inc.asm that caused missing coordination flags to not be detected
11/09/2014
v2.2.3
- Added S3K's additional PSG frequencies
- Added S3K's continuous SFX system
- Split sound priorities and speedup tempos from main asm into s1.sounddriver.other.asm
- Improved guide to update driver on H_Int when available
13/09/2014
v2.2.3.1
- Moved troublesome PSG frequency
- Reverted PSGPitchConvert to an earlier, more readable state
06/10/2014
v2.2.4
- Fixed FM6 fade-in
- Modified cfFadeToPrevious to work on FM and PSG tracks
- Optimised some locrets (recycling!)
- Annotated Vladikcomper's modified WriteFMI(I)
- Removed a startZ80 that I missed back in v2.0
- Renamed several constants to be more S1-like
- Restored original local labels (With tweaks for compatibility)
- Optimised lea Clone_Driver_RAM into .w
- Optimised 68k version of PlaySega
- Ported S3K's NoteFill
- Optimised some 'bsr & bra' into 'pea & bra'
- Further optimised the waitYM macro by using tst.b instead of btst
- Optimised all btst #7 to tst
- Even further optimised waitYM by moving ym2612_a0 to a register
- Updated channel RAM addresses description
- Optimised NoteFillUpdate
15/10/2014
v2.2.4.1
- Optimised WriteFMI(I) with a nice trick I picked up from Ristar's driver
- Optimised some writes to psg_input
- Optimised all adda.x #x,aN to lea x(aN),aN
- Optimised FM and PSG's .gotduration by replacing them with SetDuration_pea
- Added a nop to WaitYM to avoid missed writes
- Optimised PSG flags by reordering their checks in order of most-to-least common
- Replaced a 'branch to rts' with an rts
- Restored the music and SFXs to their 'as-of-2011' state. They shouldn't be modified in the first place
- Added to _smps2asm_inc.asm to fix DAC typo
17/10/2014
v2.2.4.1b
- Added several toggles to allow for Sonic 1 support
27/12/2014
v2.2.5
- Updated to latest Git (fixing a newly-pointed-out bug along the way)
- Merged all compatibility layers into s1.sounddriver.compatibility.asm
- Moved v2.2.4.1b's toggles to s1.sounddriver.compatibility.asm
- Reverted some dangerous 'moveq's to 'move.b's
- Optimised a branch under PSGUpdateVolFX
- Optimised a branch under VolEnv_Reset
- Removed a branch under VolEnv_Off by moving it above the branch's target
- Size-optimised MegaPCM, reducing the uncompressed binary's size from 210h to 1E5h
- Added another nop instruction to waitYM (the beginning of S2's title screen theme plays a goofy note in Regen with just the one)
- Optimised FMSetFreq by making it write directly from FM_Notes to zTrackFreq
- Replaced the 'clr.b's under bgmnot1up with a faster moveq/move.b combination
- Removed the redundant 'clr.b v_sndprio'
- Optimised Sound_PlayBGM and Sound_PlaySpecial by making them write their voice pointers directly to v_voice_ptr/v_special_voice_ptr (old leftover from v2.1's longword voice pointer hack)
- Optimised SpeedUpMusic, SpeedUpMusic_1up, SlowDownMusic and SlowDownMusic_1up with some register usage
- Optimised some zTrackVolume(a5) usage under DoFadeOut
- Optimised .bgm_psgloadloop by using an addq to skip the 'redundant' byte
- Optimised Sound_ChkValue by removing the redundant check for Sound Commands
- bsr -> bra in .specfmdone
- Renamed all s1.sounddriver files and moved them to the sound folder
- Changed which v_sndprio clear is used in Sound_PlayBGM (Sonic 2 uses the last one)
- Added new waitYMspec macro that uses parameter as target for tst
- Used above modification to optimise WriteFMI
- Optimised cfSetPSGNoise with better register use
- Rearranged files at end of driver (Mega PCM, PSGs, music, sounds, others) to put many within 'SoundIndex(pc)' range
- Fixed oversight in cfNoteFillS3K (d1 isn't loaded if tempo divider = 1), increasing compatibility with S3K music
- Added two missing S1 equates
- Excluded nops from waitYM loop
- Used more appropriate locret under FMNoteOn
- Added S3K tweak to cfSetPSGTone and cfSetVoice
21/02/2015
v2.2.5.1
- Updated SMPS2ASM
03/03/2015
v2.2.5.2
- Added waitZ80 macro, for S1 compatibility
- Added cfSendFMI
- Replaced cfOpF9 with above
- Added cfChanFMCommand
- Added some flag documentation from S3K and flamewing's driver
- Better-formatted Sonic 2 Clone Driver v2 - Compatibility.asm
- Relocated DAC ID equates from _smps2asm_inc.asm to Sonic 2 Clone Driver v2 - Compatibility.asm
- Made said IDs dynamic, in the same way as the music and SFXs
- Corrected IDs to account for absent dHipHopHitKick3
- Added id function to Sonic 2 Clone Driver v2 - Compatibility.asm
09/03/2015
v2.2.6
- Sonic 2-ifications
- Added to FMUpdateTrack and PSGUpdateTrack the way S2's driver does
- Made TrackSetRest no longer continue to FinishTrackUpdate
- Fixed modulation on rests by adding a check to DoModulation (noticeable at start of ARZ's theme after it's looped)
- Relocated a check in FMPrepareNote to occur a little earlier
- Changed a reference to a locret in Sound_PlayBGM with one to .bgm_loadMusic, which should make it so that the extra life music can interrupt itself
- Made .bgmnot1up clear v_fadeout_counter
- .bmg_fmloadloop and .bgm_psgloadloop now set the 'track at rest' bit, avoiding hanging notes (noticable at start of DEZ's theme)
- Optimised .silencefm6 using some S2 logic
- Sound_PlaySFX no longer checks v_fadeout_counter
- FadeOutMusic no longer calls FadeOutSFX
- SpeedUpMusic and SlowDownMusic no longer set v_main_tempo_timeout
- PSGSetVolume now corrects values that are >=$10
- PSGSetFreq and .restpsg don't continue to FinishTrackUpdate
- An 'add' in PSGSendVolume is replaced with an 'ori'
- cfPanningAMSFMS has an additional check
- Added a (commented out) call to FadeOutSFX in Sound_PlayBGM
- Added to FMUpdateTrack and PSGUpdateTrack the way S2's driver does
- .nospeedshoes no longer sets v_main_tempo_timeout to the header tempo. This is to avoid unintended tempo overflow on the first frame of playback, delaying the song by a frame. This also helps to prevent hanging notes (noticable at start of DEZ's theme)
- Removed useless 'even' from under FMDACInitBytes
- Removed last '0's from FMDACInitBytes and PSGInitBytes (were actually 'even's)
09/07/2015
v2.3
- Made FadeOutSFX use d6 instead of d7, so that it doesn't conflict with Sound_PlayBGM
- Optimised PSG envelopes with more efficient use of flags
- Made previous version's bugs toggleable with Fix_DriverBugs
- Added Valley Bell's Sega chant pan fix
- Added Valley Bell's 0 FM track fix
- Added Valley Bell's cfFadeInToPrevious PSG noise type fix
- Added a (commented out) call to FadeOutSpecSFX in Sound_PlayBGM
- Un-commented-out the calls under Sound_PlayBGM
- S2-ified FadeOutSFX
- Corrected StopSoundAndMusic comment
- Improved cfFadeInToPrevious FM6 fix
- Reduced RAM usage by employing a trick from S&K's driver: the SFX/special SFX share RAM with the 1up music backup
- Switched to using 'STRUCT' to define track RAM
- Defined driver RAM with phase/ds.b combo
- Split v_1up_ram_copy into v_1up_ram_copy and v_1up_variables (variables now go after tracks)
- As part of the SFX/track backup share, the playback control bytes of all tracks are separately backed-up
- Made Sound_PlayBGM's extra life code clear the special SFX tracks' 'is playing' bit
- Special SFX code above FMDACInitBytes now uses tst.b instead of tst.w
- Moved v_special_voice_ptr back next to v_voice_ptr (RAM is dynamic now, so it can go here without wasting any RAM if unused)
- Made continuous SFX RAM toggleable
- Reduced zTrack size to $2E by changing LoopCounters from 4 bytes to 2 bytes, as S&K's driver has it
- Reduced zTrack size to $2C with some track-specific RAM usage
- FinishTrackUpdate no longer clears VolFlutter on non-PSG tracks
- Removed now-useless label (loc_721B6)
Credits
Original Sonic 2 Clone Driver
Varion Icaria - Puto's sound driver port
Esrael - Tweaker's sound driver port, plus fixes for Puto's port, including a fix for the Sega sound
Puto, Tweaker, StephenUK - Numerous fixes
drx - Hacking CulT's VDP calculator
JMan2050 - Jman's PCM driver
Valley Bell - $EC sound fix
Sonic 2 Clone Driver v2
Those that contributed to the sound driver disassemblies
Valley Bell - General help, fixes for some bugs. Also, inspiration
Shobiz - Ported Spin Dash rev code
Puto - Original 68k Sega sound fix
MarkeyJester - DAC fade-in fix
Cinossu - S1SMPS2ASM
Flamewing - SMPS2ASM core; pointing out S3K's additional PSG frequencies; his perfect-compression koscmp, used to compress Mega PCM
Vladikcomper - Mega PCM
Clownacy - Go read the changelog =P
This post has been edited by Clownacy: 09 July 2015 - 07:11 AM


05