Actions

SCHG How-to

Difference between revisions of "Fix the SEGA Sound"

From Sonic Retro

(Migrating final source code line)
(Completely revamped the fix because I'm tired of having people ask me why the old one didn't work on asm68k)
Line 1: Line 1:
 
Let's fix a problem that causes a great deal of pain to anyone adding code to Sonic 1: The SEGA sound.  
 
Let's fix a problem that causes a great deal of pain to anyone adding code to Sonic 1: The SEGA sound.  
  
Thanks to Esrael, we can now fix it properly, without having it garbled every time a line of code is added behind it.
+
So go to Sound_E1, and replace this:
 
+
<asm>Sound_E1: ; XREF: Sound_ExIndex
So go to SoundDriverLoad, and after this line:
+
move.b #$88,($A01FFF).l
 
+
move.w #0,($A11100).l ; start the Z80
<asm> bsr.w KosDec ; decompress</asm>
+
move.w #$11,d1
 
+
loc_71FC0:
Add this:
+
move.w #-1,d0
 
+
loc_71FC4:
<asm> move.b #(SegaPCM/$10000),$A00019.l</asm>
 
 
 
Similarly, go to where SegaPCM is, and right before that, add the following line:
 
 
 
<asm> cnop -$6978,$10000</asm>
 
 
 
And before the "even", add this:
 
 
 
<asm>EndSegaPCM:</asm>
 
 
 
So the final result should look like this:
 
 
 
<asm> cnop -$6978,$10000
 
SegaPCM: incbin sound\segapcm.bin
 
EndSegaPCM: even</asm>
 
 
 
 
 
 
 
And the SoundDriverLoad routine should look like this:
 
 
 
<asm>SoundDriverLoad: ; XREF: GameClrRAM; TitleScreen
 
 
nop
 
nop
move.w #$100,($A11100).l ; stop the Z80
+
dbf d0,loc_71FC4
move.w #$100,($A11200).l ; reset the Z80
+
dbf d1,loc_71FC0
lea (Kos_Z80).l,a0 ; load sound driver
+
addq.w #4,sp
lea ($A00000).l,a1
+
rts</asm>
bsr.w KosDec ; decompress
 
move.b #(SegaPCM/$10000),$A00019.l
 
move.w #0,($A11200).l
 
nop
 
nop
 
nop
 
nop
 
move.w #$100,($A11200).l ; reset the Z80
 
move.w #0,($A11100).l ; start the Z80
 
rts </asm>
 
 
 
Finally, the compile time calculation that's done at Kos_Z80 is stupid,
 
as it relies on the SegaPCM being at the end of the ROM, which isn't the case anymore. <br>
 
So go to Kos_Z80, and replace all instances of EndOfRom with EndSegaPCM. The end result will then be this:
 
 
 
<asm>Kos_Z80: incbin sound\z80_1.bin
 
dc.w ((SegaPCM&$FF)<<8)+((SegaPCM&$FF00)>>8)
 
dc.b $21
 
dc.w (((EndSegaPCM-SegaPCM)&$FF)<<8)+(((EndSegaPCM-SegaPCM)&$FF00)>>8)
 
incbin sound\z80_2.bin
 
even</asm>
 
  
 +
with this:
 +
<asm>Sound_E1:                  ; XREF: Sound_ExIndex
 +
          lea    (SegaPCM).l,a2            ; Load the SEGA PCM sample into a2. It's important that we use a2 since a0 and a1 are going to be used up ahead when reading the joypad ports
 +
          move.l    #$6978,d3            ; Load the size of the SEGA PCM sample into d3
 +
          move.b    #$2A,($A04000).l        ; $A04000 = $2A -> Write to DAC channel     
 +
PlayPCM_Loop:     
 +
          move.b    (a2)+,($A04001).l        ; Write the PCM data (contained in a2) to $A04001 (YM2612 register D0)
 +
          move.w    #$14,d0                  ; Write the pitch ($14 in this case) to d0
 +
          dbf    d0,*                  ; Decrement d0; jump to itself if not 0. (for pitch control, avoids playing the sample too fast) 
 +
          sub.l    #1,d3                ; Subtract 1 from the PCM sample size
 +
          beq.s    return_PlayPCM            ; If d3 = 0, we finished playing the PCM sample, so stop playing, leave this loop, and unfreeze the 68K
 +
          lea    ($FFFFF604).w,a0        ; address where JoyPad states are written
 +
          lea    ($A10003).l,a1            ; address where JoyPad states are read from
 +
          jsr    (Joypad_Read).w            ; Read only the first joypad port. It's important that we do NOT do the two ports, we don't have the cycles for that
 +
          btst    #7,($FFFFF604).w        ; Check for Start button
 +
          bne.s    return_PlayPCM            ; If start is pressed, stop playing, leave this loop, and unfreeze the 68K
 +
          bra.s    PlayPCM_Loop            ; Otherwise, continue playing PCM sample
 +
return_PlayPCM:
 +
          addq.w    #4,sp
 +
          rts</asm>
 
[[Category:SCHG How-tos]]
 
[[Category:SCHG How-tos]]

Revision as of 07:40, 16 February 2008

Let's fix a problem that causes a great deal of pain to anyone adding code to Sonic 1: The SEGA sound.

So go to Sound_E1, and replace this: <asm>Sound_E1: ; XREF: Sound_ExIndex move.b #$88,($A01FFF).l move.w #0,($A11100).l ; start the Z80 move.w #$11,d1 loc_71FC0: move.w #-1,d0 loc_71FC4: nop dbf d0,loc_71FC4 dbf d1,loc_71FC0 addq.w #4,sp rts</asm>

with this: <asm>Sound_E1:  ; XREF: Sound_ExIndex

         lea     (SegaPCM).l,a2             ; Load the SEGA PCM sample into a2. It's important that we use a2 since a0 and a1 are going to be used up ahead when reading the joypad ports
         move.l     #$6978,d3             ; Load the size of the SEGA PCM sample into d3
         move.b     #$2A,($A04000).l        ; $A04000 = $2A -> Write to DAC channel      

PlayPCM_Loop:

         move.b     (a2)+,($A04001).l         ; Write the PCM data (contained in a2) to $A04001 (YM2612 register D0)
         move.w     #$14,d0                  ; Write the pitch ($14 in this case) to d0
         dbf     d0,*                  ; Decrement d0; jump to itself if not 0. (for pitch control, avoids playing the sample too fast)  
         sub.l     #1,d3                ; Subtract 1 from the PCM sample size
         beq.s     return_PlayPCM             ; If d3 = 0, we finished playing the PCM sample, so stop playing, leave this loop, and unfreeze the 68K
         lea     ($FFFFF604).w,a0         ; address where JoyPad states are written
         lea     ($A10003).l,a1             ; address where JoyPad states are read from
         jsr     (Joypad_Read).w             ; Read only the first joypad port. It's important that we do NOT do the two ports, we don't have the cycles for that
         btst     #7,($FFFFF604).w        ; Check for Start button
         bne.s     return_PlayPCM             ; If start is pressed, stop playing, leave this loop, and unfreeze the 68K
         bra.s     PlayPCM_Loop             ; Otherwise, continue playing PCM sample

return_PlayPCM:

         addq.w     #4,sp
         rts</asm>