How to extend the sound ID range in Sonic 2's sound driver

Discussion in 'Engineering & Reverse Engineering' started by Clownacy, Nov 19, 2014.

  1. Clownacy

    Clownacy

    Mania bad Tech Member
    803
    37
    28
    Want some more sound IDs? The current Git disasm is set up to allow this with ease, but it isn't really complete.

    If you want an additional $80 sound IDs available to you, you can change the idstart values of the music IDs and the sound IDs. For example, change the music IDs', value to $01. You can build the ROM, and nothing will seem wrong.

    But this isn't the cleanest of ways, as you need to leave sound $80 blank. Not doing so will lead to situations like this: set Music IDs' value to $70, and access the options menu in the built ROM. The menu's music will not play.

    But why does this happen? Because that music's ID is now $80. The cause of this problem is that that particular slot is reserved for the silence sound. Here, we'll be making things a bit neater, and move the silence value to $00. Allowing you access to many more IDs, without special case code for one certain ID.



    Relocating the silence value
    Open s2.sounddriver.asm, and go to zUpdateEverything. There, you'll find this:

    Code (ASM):
    1.     ; Apparently if this is 80h, it does not play anything new,
    2.     ; otherwise it cues up the next play (flag from 68K for new item)
    3.     ld  a,  (zQueueToPlay)
    4.     cp  80h
    5.     call    nz,zPlaySoundByIndex    ; If not 80h, we need to play something new!

    As you can tell by the comments, you need to change the cp's value from 80h to 0. But wait! It's better to use an 'or a', which does the same thing, but is faster and smaller. Doing that will give you this:

    Code (ASM):
    1.     ; Apparently if this is 00h, it does not play anything new,
    2.     ; otherwise it cues up the next play (flag from 68K for new item)
    3.     ld  a,  (zQueueToPlay)
    4.     or  a
    5.     call    nz,zPlaySoundByIndex    ; If not 00h, we need to play something new!

    Next up, zCycleQueue. Here, we face the same problem: a 'cp 80h'. Again, change it to an 'or a'.


    zPlaySoundByIndex. This one's interesting. Here, you can see how, if sound 00h were to be played, the driver would reset itself. This is likely part of its initialisation process, where, initially, sound 00h would technically be queued. We'll have to remove this, but this shouldn't be an issue, as the same reset code is branched to at the Z80's Entry Point. This check is just a leftover from the original Sonic 1 driver, and is now redundant.

    Just remove everything until 'ld (ix+8),80h'. Also, change the '80h' in this instruction to '0'. However, if you don't intend for your music IDs to start at 01h, the ID immediately after the silence value, then you'll want to keep the 'cp MusID__First' and 'ret c' instructions, in order to prevent crashes when invalid sounds are played.


    zPlaySegaSound. This features a little optimisation we'll have to deal with: instead of a straightforward 'cp 80h', 80h is moved to a register, and that register is used instead. Understandable, since a low cycle count is a necessity for PCM streaming. In fact, a 'cp r' is just as small and just as fast as an 'or a'.

    There are two instances of 'ld c,80h', the second one is what we're looking for. Again, you could just move 0 to the register, but while we can't optimise the loop itself, we can slightly optimise the code that sets up the loop. So, remove this instruction. Inside the loop, you'll find 'cp c'. Change this to 'or a'.


    zClearTrackPlaybackMem. Here, zQueueToPlay is set to 80h. We don't want that, so change 'ld a,80h' into 'xor a'. Again, instead of 'ld a,0', we're using a smaller and faster way of doing the same thing. Do this at zInitMusicPlayback, also.


    That's all for s2.sounddriver.asm. Now, onto s2.asm.

    Got to sndDriverInput, and find 'cmpi.b #$80,8(a1)'. Change it to 'tst.b 8(a1)'.


    And with that, you're done. As you've seen earlier, even before making the silence sound occupy it, sound 00h was unusable, so in merging the two, we've also freed up a sound ID. Bonus! Now you're free to move your sound IDs to occupy the >80h range of slots, and you don't have to worry about sound 80h, so you can have a song or an SFX occupy it with no ill effects!


    But we're not done yet. If you're going to extend your sound IDs into the >80h range, then you'll likely want your sound tests to cover that range, too.



    Extending the sound tests
    We'll start with the level select's sound test. Go to LevSelControls_CheckLR and remove these two lines:

    Code (ASM):
    1.     bcc.s   +
    2.     moveq   #$7F,d0

    Then remove these three:

    Code (ASM):
    1.     cmpi.w  #$80,d0
    2.     blo.s   +
    3.     moveq   #0,d0

    Then change this...

    Code (ASM):
    1.     btst    #button_A,d1
    2.     beq.s   +
    3.     addi.b  #$10,d0
    4.     andi.b  #$7F,d0
    5.  
    6. +

    ...into this:

    Code (ASM):
    1.     btst    #button_A,d1
    2.         beq.s   +
    3.         addi.b  #$10,d0
    4.         bcc.s   +
    5.         moveq   #0,d0
    6.  
    7. +

    And remove this:

    Code (ASM):
    1.     addi.w  #$80,d0

    That's that sound test done. Onto the options menu's sound test.

    Go to OptionScreen_Controls, and change this...

    Code (ASM):
    1.     btst    #button_A,d0
    2.     beq.s   +
    3.     addi.b  #$10,d2
    4.     cmp.b   d3,d2
    5.     bls.s   +
    6.     moveq   #0,d2
    7.  
    8. +

    ...into this:

    Code (ASM):
    1.     cmpi.b  #2,(Options_menu_box).w
    2.     bne.s   +   ; rts
    3.     btst    #button_A,d0
    4.         beq.s   +
    5.         addi.b  #$10,d2
    6.         bcc.s   +
    7.         moveq   #0,d2
    8.  
    9. +

    Under that, remove this:

    Code (ASM):
    1.     addi.w  #$80,d0

    Then go to OptionScreen_Choices, and change this...

    Code (ASM):
    1.     dc.l ($80-1)<<24

    ...into:

    Code (ASM):
    1.     dc.l $FF<<24


    Conclusion
    With that, we've removed the obstacle of the silence value's placement, freed up a sound ID, optimised the driver's code a little (in both size and speed), and extended the sound tests. All that's left to do is lift the '20h music files per bank' cap.