don't click here

Dual PCM

Discussion in 'Engineering & Reverse Engineering' started by MarkeyJester, Nov 27, 2016.

  1. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,192
    404
    63
    Japan
    IF YOU WANT TO GET THE MOST OUT OF THE DRIVER I AM ABOUT TO RELEASE HERE, THEN PLEASE READ THIS ENTIRE POST BEFORE USING/RESPONDING. ANYONE WHO RESPONDS BECAUSE THEY DIDN'T READ, I SHALL NOT RESPOND TO.

    [​IMG]

    What is it?

    Dual PCM is a Z80 sound driver for the SEGA Mega Drive, it can play any two PCM samples, of any size, at any single time, through the DAC channel. It comes complete with Jester Stream Technologyâ„¢ allowing it to play the samples at the least damaging quality possible.

    Here is a test ROM of Sonic 1, with Dual PCM, Download.

    This one has a few edits to the original songs, Green Hill Zone has a set of piano chords during the chorus, as does Labyrinth Zone, Scrap Brain Zone has it's Timpani drums seperated onto the second channel, and Spring Yard Zone and Invincible have a PCM bass guitar now. This is just an example of what you can do with this driver.

    Requirements:

    Dual PCM simply requires the 68k (Main CPU) to give it the sample information in order for it to play the sample(s), Dual PCM also requires the 68k to tell it when it's about to request VDP DMA transfers, and when it's finished.

    If you intend on playing FM/PSG sounds, this MUST be handled by the 68k, so if you have a sound driver that plays back tracker data (for example SMPS), then it must be a 68k variant, Dual PCM operates on its own and requires all of the Z80's resources. It is a puppet, and the 68k is the puppeteer.

    Installation

    Please use this as a "guide" and nothing more, it doesn't have to be used with 68k SMPS, it can be used with any 68k code that can operate it properly.

    This guide below will simply assume you're using Sonic 1 and its 68k SMPS variant, I'll be using the 2005 Hivebrain disassembly (known as "Sonic 1 (Split and Text by Hivebrain) (ASM68K)" on this page), nothing against other disassembly variants, I just know this one best.

    You must handle the splitting and normal setup of the disassembly yourself, however, I will place a download link to a disassembly of the changes below made already, for your conveniece.

    Step 01 - Replacing the Z80 driver

    Sonic 1 has a Z80 DPCM playback driver, we must first rip this out, and then replace it with the new driver.

    >> 1. Inside the "sound" folder, you'll have "z80_1.bin" and "z80_2.bin", you won't need these, so delete them.
    >> 2. Next, open up "sonic1.asm", and find this:

    Code (Text):
    1. Kos_Z80:    incbin  sound\z80_1.bin
    2.         dc.w ((SegaPCM&$FF)<<8)+((SegaPCM&$FF00)>>8)
    3.         dc.b $21
    4.         dc.w (((EndOfRom-SegaPCM)&$FF)<<8)+(((EndOfRom-SegaPCM)&$FF00)>>8)
    5.         incbin  sound\z80_2.bin
    6.         even
    Replace it with:

    Code (Text):
    1. Z80ROM:     incbin  "Dual PCM\Z80.bin"
    2. Z80ROM_End: even
    >> 3. Find this:

    Code (Text):
    1. SoundDriverLoad:            ; XREF: GameClrRAM; TitleScreen
    2.         nop
    3.         move.w  #$100,($A11100).l ; stop the Z80
    4.         move.w  #$100,($A11200).l ; reset the Z80
    5.         lea (Kos_Z80).l,a0  ; load sound driver
    6.         lea ($A00000).l,a1
    7.         bsr.w   KosDec      ; decompress
    8.         move.w  #0,($A11200).l
    9.         nop
    10.         nop
    11.         nop
    12.         nop
    13.         move.w  #$100,($A11200).l ; reset the Z80
    14.         move.w  #0,($A11100).l  ; start the Z80
    15.         rts
    16. ; End of function SoundDriverLoad

    Replace it with:

    Code (Text):
    1. SoundDriverLoad:
    2.         lea (Z80ROM).l,a0               ; load Z80 ROM data
    3.         lea ($A00000).l,a1              ; load Z80 RAM space address
    4.         move.w  #(Z80ROM_End-Z80ROM)-$01,d1     ; set repeat times
    5.         move.w  #$0100,($A11100).l          ; request Z80 stop (ON)
    6.         move.w  #$0100,($A11200).l          ; request Z80 reset (OFF)
    7.         btst.b  #$00,($A11100).l            ; has the Z80 stopped yet?
    8.         bne.s   *-$08                   ; if not, branch
    9.  
    10. SM_LoadZ80:
    11.         move.b  (a0)+,(a1)+             ; dump Z80 data to Z80 space
    12.         dbf d1,SM_LoadZ80               ; repeat til done
    13.         lea (StopSample).l,a0           ; load stop/mute sample address
    14.         lea ($A00000+MuteSample).l,a1       ; load Z80 RAM space where the pointer is to be stored
    15.         move.b  (a0)+,(a1)+             ; copy pointer over into Z80
    16.         move.b  (a0)+,(a1)+             ; ''
    17.         move.b  (a0)+,(a1)+             ; ''
    18.         move.w  #$0000,($A11200).l          ; request Z80 reset (ON)
    19.         moveq   #$7F,d1                 ; set repeat times
    20.         dbf d1,*                    ; there's no way of checking for reset, so a manual delay is necessary
    21.         move.w  #$0000,($A11100).l          ; request Z80 stop (OFF)
    22.         move.w  #$0100,($A11200).l          ; request Z80 reset (OFF)
    23.         rts                     ; return
    >> 4. Make a new folder at the root of your disassembly, and name it "Dual PCM":

    [​IMG]

    >> 5. Download this new Z80 sound driver source code, and place it in the "Dual PCM" folder.

    Step 02 - Replacing the assembly tools

    We need an assembler for the Z80, as well as some tools to help assemble/convert the new driver

    >> 1. Delete "build.bat", "ASM68K.EXE", "fixheadr.exe", and "rompad.exe".

    >> 2. Download this folder of tools and extract it at the root of your disassembly:

    Download (32-Bit)
    Download (64-Bit)

    [​IMG]

    >> 3. Download this new batch file and place it at the root of your disassembly:

    [​IMG]

    Step 03 - Editing the 68k Sound Driver

    The sound driver is still handling the old Z80 driver, as well as only handling one DAC channel, and a few unoptimal things (this one is quite lengthy...)

    >> 1. Find:

    Code (Text):
    1. sub_71B4C:              ; XREF: loc_B10; PalToCRAM
    2.         move.w  #$100,($A11100).l ; stop the Z80
    3.         nop
    4.         nop
    5.         nop
    6.  
    7. loc_71B5A:
    8.         btst    #0,($A11100).l
    9.         bne.s   loc_71B5A
    10.  
    11.         btst    #7,($A01FFD).l
    12.         beq.s   loc_71B82
    13.         move.w  #0,($A11100).l  ; start the Z80
    14.         nop
    15.         nop
    16.         nop
    17.         nop
    18.         nop
    19.         bra.s   sub_71B4C
    20. ; ===========================================================================
    21.  
    22. loc_71B82:
    23.         lea ($FFF000).l,a6
    And replace with:

    Code (Text):
    1. YM_Access_WaitRead:
    2.         StartZ80                    ; EXT: request Z80 stop off (allow it to continue)
    3.         rept    $10                 ; EXT: delay for a long enough time to allow the...
    4.         nop                     ; EXT: '' ...68k pointer to be saved correctly.
    5.         endr                        ; EXT: ''
    6.  
    7. sub_71B4C: 
    8.         lea ($FFF000).l,a6
    9.  
    10.         lea ($A00000+YM_Access).l,a0        ; EXT: load access address in Z80
    11.         move.l  #$A00000,d0             ; EXT: prepare Z80 RAM address in d0 (i.e. start of Cue list address)
    12.         StopZ80                     ; EXT: request Z80 stop on
    13.         tst.b   (a0)+                   ; EXT: is the Z80 accessing the 68k pointer?
    14.         bne.s   YM_Access_WaitRead          ; EXT: if so, branch and wait for it to finish...
    15.         move.b  (a0)+,d1                ; EXT: load lower byte of pointer
    16.         move.b  (a0)+,d0                ; EXT: load upper byte of pointer
    17.         StartZ80                    ; EXT: request Z80 stop off
    18.         lsl.w   #$08,d0                 ; EXT: shift upper byte up
    19.         move.b  d1,d0                   ; EXT: put lower byte with it
    20.         move.l  d0,$10(a6)              ; EXT: store the cue address
    >> 2. Find:

    Code (Text):
    1. loc_71BC8:
    2.         lea $40(a6),a5
    3.         tst.b   (a5)
    4.         bpl.s   loc_71BD4
    5.         jsr sub_71C4E(pc)
    6.  
    7. loc_71BD4:
    And replace with:

    Code (Text):
    1. loc_71BC8:
    2.         lea $40-$30(a6),a5          ; MJ: making correction for flow below
    3.         moveq   #2-1,d7             ; MJ: set number of PCM channels to run
    4.         move.b  #$80-1,$08(a6)          ; MJ: reset as PCM channel
    5.  
    6. SD_NextPCM:
    7.         addq.b  #$01,$08(a6)            ; MJ: advance PCM channel ID
    8.         lea $30(a5),a5          ; MJ: advance to next channel
    9.         tst.b   (a5)
    10.         bpl.s   loc_71BD4
    11.         jsr sub_71C4E(pc)
    12.  
    13. loc_71BD4:
    14.         dbf d7,SD_NextPCM           ; MJ: repeat for number of PCM channels available
    >> 3. Goto "loc_71C44:" and replace this:

    Code (Text):
    1.         move.w  #0,($A11100).l  ; start the Z80
    With this:

    Code (Text):
    1.         bra.s   YM_Access_TestWrite         ; EXT: jump into the access loop
    2.  
    3. YM_Access_WaitWrite:
    4.         StartZ80                    ; EXT: request Z80 stop off (allow it to continue)
    5.         rept    $10                 ; EXT: delay for a long enough time to let the Z80...
    6.         nop                     ; EXT: '' ...finish writing the 68k pointer, so it doesn't...
    7.         endr                        ; EXT: '' ...clash with 68k's pointer writing.
    8.  
    9. YM_Access_TestWrite:
    10.         lea ($A00000+YM_Access).l,a0        ; EXT: load access address in Z80
    11.         lea $13(a6),a1              ; EXT: load the 68k's pointer finish location
    12.         StopZ80                     ; EXT: request Z80 stop on
    13.         tst.b   (a0)+                   ; EXT: is the Z80 accessing the 68k pointer?
    14.         bne.s   YM_Access_WaitWrite         ; EXT: if so, branch and wait for it to finish...
    15.         move.b  (a1),(a0)+              ; EXT: save lower byte of pointer
    16.         move.b  -(a1),(a0)              ; EXT: save upper byte of pointer
    17.         StartZ80                    ; EXT: request Z80 stop off
    Code (Text):
    1.         move.w  #0,($A11100).l  ; start the Z80
    >> 4. Goto "sub_71C4E:" and replace this:

    Code (Text):
    1. sub_71C4E:              ; XREF: sub_71B4C
    2.         subq.b  #1,$E(a5)
    3.         bne.s   locret_71CAA
    4.         move.b  #$80,8(a6)
    5.         movea.l 4(a5),a4
    With this:

    Code (Text):
    1. sub_71C4E:              ; XREF: sub_71B4C
    2.         subq.b  #1,$E(a5)
    3.         bne.w   locret_71CAA
    4.         movea.l 4(a5),a4
    (Note the branch size change)

    >> 5. Find this:

    Code (Text):
    1. loc_71C88:
    2.         move.l  a4,4(a5)
    3.         btst    #2,(a5)
    4.         bne.s   locret_71CAA
    5.         moveq   #0,d0
    6.         move.b  $10(a5),d0
    7.         cmpi.b  #$80,d0
    8.         beq.s   locret_71CAA
    9.         btst    #3,d0
    10.         bne.s   loc_71CAC
    11.         move.b  d0,($A01FFF).l
    12.  
    13. locret_71CAA:
    14.         rts
    15. ; ===========================================================================
    16.  
    17. loc_71CAC:
    18.         subi.b  #$88,d0
    19.         move.b  byte_71CC4(pc,d0.w),d0
    20.         move.b  d0,($A000EA).l
    21.         move.b  #$83,($A01FFF).l
    22.         rts
    23. ; End of function sub_71C4E
    24.  
    25. ; ===========================================================================
    26. byte_71CC4: dc.b $12, $15, $1C, $1D, $FF, $FF
    27.  
    28. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    29.  
    And replace with:

    Code (Text):
    1. loc_71C88:
    2.         move.l  a4,4(a5)
    3.         btst    #2,(a5)
    4.         bne.s   locret_71CAA
    5.         moveq   #0,d0
    6.         move.b  $10(a5),d0
    7.         subi.b  #$80,d0                 ; MJ: minus 80
    8.         add.w   d0,d0                   ; MJ: multiply by 4 (long-word size)
    9.         add.w   d0,d0                   ; MJ: ''
    10.         movem.l a0/a1,-(sp)             ; MJ: store register data
    11.         lea (SampleList).l,a0           ; MJ: load sample list
    12.         move.l  (a0,d0.w),a0                ; MJ: load correct sample z80 pointer address
    13.  
    14.         cmpi.b  #$80,$08(a6)                ; MJ: is this PCM 1?
    15.         bne.s   WritePCM2               ; MJ: if not, branch for PCM 2 writing
    16.  
    17.     ; --- Writing to PCM 1 ---
    18.  
    19.         StopZ80
    20.         lea ($A00000+PCM1_Sample).l,a1          ; MJ: load PCM 1 slot address
    21.         move.b  (a0)+,(a1)+                 ; MJ: set address of sample
    22.         move.b  (a0)+,(a1)+                 ; MJ: ''
    23.         move.b  (a0)+,(a1)+                 ; MJ: ''
    24.         move.b  #(CUPCM1_NewSample&$FF),($A00000+CU_Stack).l    ; MJ: set routine to run
    25.         move.b  #(CUPCM1_NewSample>>$08),($A00000+CU_Stack+1).l ; MJ: ''
    26.         move.b  #%11001001,($A00000+CUPCM1_RET).l       ; MJ: change "NOP" to "RET"
    27.         StartZ80
    28.  
    29.         movem.l (sp)+,a0/a1             ; MJ: restore register data
    30.  
    31. locret_71CAA:
    32.         rts                     ; MJ: return
    33.  
    34.     ; --- Writing to PCM 2 ---
    35.  
    36. WritePCM2:
    37.         StopZ80
    38.         lea ($A00000+PCM2_Sample).l,a1          ; MJ: load PCM 2 slot address
    39.         move.b  (a0)+,(a1)+                 ; MJ: ''
    40.         move.b  (a0)+,(a1)+                 ; MJ: ''
    41.         move.b  (a0)+,(a1)+                 ; MJ: ''
    42.         move.b  #%00101000,($A00000+CUPCM2_RET).l       ; change "JR NZ" to "JR Z"
    43.         StartZ80
    44.  
    45.         movem.l (sp)+,a0/a1             ; MJ: restore register data
    46.         rts                     ; MJ: return
    47.  
    48. ; ===========================================================================
    >> 6. Find this:

    Code (Text):
    1. loc_71E94:              ; XREF: loc_71E50
    2.         clr.b   3(a6)
    3.         moveq   #$30,d3
    4.         lea $40(a6),a5
    5.         moveq   #6,d4
    6.  
    7. loc_71EA0:
    8.         btst    #7,(a5)
    9.         beq.s   loc_71EB8
    10.         btst    #2,(a5)
    11.         bne.s   loc_71EB8
    12.         move.b  #-$4C,d0
    13.         move.b  $A(a5),d1
    14.         jsr sub_72722(pc)
    15.  
    16. loc_71EB8:
    17.         adda.w  d3,a5
    18.         dbf d4,loc_71EA0
    19.  
    20.         lea $220(a6),a5
    21.         moveq   #2,d4
    22.  
    23. loc_71EC4:
    24.         btst    #7,(a5)
    25.         beq.s   loc_71EDC
    26.         btst    #2,(a5)
    27.         bne.s   loc_71EDC
    28.         move.b  #-$4C,d0
    29.         move.b  $A(a5),d1
    30.         jsr sub_72722(pc)
    31.  
    32. loc_71EDC:
    33.         adda.w  d3,a5
    34.         dbf d4,loc_71EC4
    35.  
    36.         lea $340(a6),a5
    37.         btst    #7,(a5)
    38.         beq.s   loc_71EFE
    39.         btst    #2,(a5)
    40.         bne.s   loc_71EFE
    41.         move.b  #-$4C,d0
    42.         move.b  $A(a5),d1
    43.         jsr sub_72722(pc)
    44.  
    45. loc_71EFE:
    46.         bra.w   loc_71C44
    And replace with:

    Code (Text):
    1. loc_71E94:              ; XREF: loc_71E50
    2.         clr.b   3(a6)
    3.         moveq   #$30,d3
    4.         lea $40(a6),a5
    5.         moveq   #7,d4                   ; MJ: number of YM2612 based channels
    6.  
    7. loc_71EA0:
    8.         btst    #7,(a5)
    9.         beq.s   loc_71EB8
    10.         btst    #2,(a5)
    11.         bne.s   loc_71EB8
    12.         move.b  #-$4C,d0
    13.         move.b  $A(a5),d1
    14.         jsr sub_72722(pc)
    15.  
    16. loc_71EB8:
    17.         adda.w  d3,a5
    18.         dbf d4,loc_71EA0
    19.  
    20.         lea $250(a6),a5             ; MJ: new SFX location
    21.         moveq   #2,d4
    22.  
    23. loc_71EC4:
    24.         btst    #7,(a5)
    25.         beq.s   loc_71EDC
    26.         btst    #2,(a5)
    27.         bne.s   loc_71EDC
    28.         move.b  #-$4C,d0
    29.         move.b  $A(a5),d1
    30.         jsr sub_72722(pc)
    31.  
    32. loc_71EDC:
    33.         adda.w  d3,a5
    34.         dbf d4,loc_71EC4
    35.  
    36.         lea $370(a6),a5             ; MJ: new SFX location
    37.         btst    #7,(a5)
    38.         beq.s   loc_71EFE
    39.         btst    #2,(a5)
    40.         bne.s   loc_71EFE
    41.         move.b  #-$4C,d0
    42.         move.b  $A(a5),d1
    43.         jsr sub_72722(pc)
    44.  
    45. loc_71EFE:
    46.         bra.w   loc_71C44
    >> 7. Find this:

    Code (Text):
    1. ; ===========================================================================
    2. ; ---------------------------------------------------------------------------
    3. ; Play "Say-gaa" PCM sound
    4. ; ---------------------------------------------------------------------------
    5.  
    6. Sound_E1:               ; XREF: Sound_ExIndex
    7.         move.b  #$88,($A01FFF).l
    8.         move.w  #0,($A11100).l  ; start the Z80
    9.         move.w  #$11,d1
    10.  
    11. loc_71FC0:
    12.         move.w  #-1,d0
    13.  
    14. loc_71FC4:
    15.         nop
    16.         dbf d0,loc_71FC4
    17.  
    18.         dbf d1,loc_71FC0
    19.  
    20.         addq.w  #4,sp
    21.         rts
    22. ; ===========================================================================
    And replace with::

    Code (Text):
    1. ; ===========================================================================
    2. ; ---------------------------------------------------------------------------
    3. ; Play "Say-gaa" PCM sound
    4. ; ---------------------------------------------------------------------------
    5.  
    6. Sound_E1:
    7.         StopZ80                     ; MJ: request Z80 stop "ON"
    8.         lea (SegaPCM).l,a2              ; MJ: load sample address
    9.         lea ($A04000).l,a3              ; MJ: load YM2612 port
    10.         move.b  #$2A,(a3)+              ; MJ: set YM2612 address to the PCM data port
    11.         move.l  #(SegaPCM_End-SegaPCM)-$01,d4       ; MJ: prepare size
    12.         move.w  d4,d3                   ; MJ: get lower word size
    13.         swap    d4                  ; MJ: get upper word size
    14.  
    15. PlayPCM_Loop:
    16.         move.b  (a2)+,(a3)              ; MJ: save sample data to port
    17.         moveq   #$2B,d0                 ; MJ: set delay time
    18.         dbf d0,*                    ; MJ: delay...
    19.         dbf d3,PlayPCM_Loop             ; MJ: repeat til done
    20.         dbf d4,PlayPCM_Loop             ; MJ: ''
    21.         move.b  #$80,(a3)               ; MJ: save mute data to port
    22.         addq.w  #$04,sp                 ; MJ: skip return address
    23.         subq.w  #$01,a3                 ; MJ: move back to address port
    24.         tst.b   (a3)                    ; MJ: is the YM2612 busy?
    25.         bmi.s   *-$02                   ; MJ: if so, branch and recheck
    26.         move.b  #$2A,(a3)               ; MJ: write address (set it back to DAC port for the Z80)
    27.         StartZ80                    ; MJ: request Z80 stop "OFF"
    28.         rts                     ; MJ: return
    29.  
    30. ; ===========================================================================
    >> 8. Find all of this:

    Code (Text):
    1. ; ===========================================================================
    2. ; ---------------------------------------------------------------------------
    3. ; Play music track $81-$9F
    4. ; ---------------------------------------------------------------------------
    5.  
    6. Sound_81to9F:               ; XREF: Sound_ChkValue
    7.         cmpi.b  #$88,d7     ; is "extra life" music played?
    8.         bne.s   loc_72024   ; if not, branch
    9.         tst.b   $27(a6)
    10.         bne.w   loc_721B6
    11.         lea $40(a6),a5
    12.         moveq   #9,d0
    13.  
    14. loc_71FE6:
    15.         bclr    #2,(a5)
    16.         adda.w  #$30,a5
    17.         dbf d0,loc_71FE6
    18.  
    19.         lea $220(a6),a5
    20.         moveq   #5,d0
    21.  
    22. loc_71FF8:
    23.         bclr    #7,(a5)
    24.         adda.w  #$30,a5
    25.         dbf d0,loc_71FF8
    26.         clr.b   0(a6)
    27.         movea.l a6,a0
    28.         lea $3A0(a6),a1
    29.         move.w  #$87,d0
    30.  
    31. loc_72012:
    32.         move.l  (a0)+,(a1)+
    33.         dbf d0,loc_72012
    34.  
    35.         move.b  #$80,$27(a6)
    36.         clr.b   0(a6)
    37.         bra.s   loc_7202C
    38. ; ===========================================================================
    39.  
    40. loc_72024:
    41.         clr.b   $27(a6)
    42.         clr.b   $26(a6)
    43.  
    44. loc_7202C:
    45.         jsr sub_725CA(pc)
    46.         movea.l (off_719A0).l,a4
    47.         subi.b  #$81,d7
    48.         move.b  (a4,d7.w),$29(a6)
    49.         movea.l (Go_MusicIndex).l,a4
    50.         lsl.w   #2,d7
    51.         movea.l (a4,d7.w),a4
    52.         moveq   #0,d0
    53.         move.w  (a4),d0
    54.         add.l   a4,d0
    55.         move.l  d0,$18(a6)
    56.         move.b  5(a4),d0
    57.         move.b  d0,$28(a6)
    58.         tst.b   $2A(a6)
    59.         beq.s   loc_72068
    60.         move.b  $29(a6),d0
    61.  
    62. loc_72068:
    63.         move.b  d0,2(a6)
    64.         move.b  d0,1(a6)
    65.         moveq   #0,d1
    66.         movea.l a4,a3
    67.         addq.w  #6,a4
    68.         moveq   #0,d7
    69.         move.b  2(a3),d7
    70.         beq.w   loc_72114
    71.         subq.b  #1,d7
    72.         move.b  #-$40,d1
    73.         move.b  4(a3),d4
    74.         moveq   #$30,d6
    75.         move.b  #1,d5
    76.         lea $40(a6),a1
    77.         lea byte_721BA(pc),a2
    78.  
    79. loc_72098:
    80.         bset    #7,(a1)
    81.         move.b  (a2)+,1(a1)
    82.         move.b  d4,2(a1)
    83.         move.b  d6,$D(a1)
    84.         move.b  d1,$A(a1)
    85.         move.b  d5,$E(a1)
    86.         moveq   #0,d0
    87.         move.w  (a4)+,d0
    88.         add.l   a3,d0
    89.         move.l  d0,4(a1)
    90.         move.w  (a4)+,8(a1)
    91.         adda.w  d6,a1
    92.         dbf d7,loc_72098
    93.         cmpi.b  #7,2(a3)
    94.         bne.s   loc_720D8
    95.         moveq   #$2B,d0
    96.         moveq   #0,d1
    97.         jsr sub_7272E(pc)
    98.         bra.w   loc_72114
    99. ; ===========================================================================
    100.  
    101. loc_720D8:
    102.         moveq   #$28,d0
    103.         moveq   #6,d1
    104.         jsr sub_7272E(pc)
    105.         move.b  #$42,d0
    106.         moveq   #$7F,d1
    107.         jsr sub_72764(pc)
    108.         move.b  #$4A,d0
    109.         moveq   #$7F,d1
    110.         jsr sub_72764(pc)
    111.         move.b  #$46,d0
    112.         moveq   #$7F,d1
    113.         jsr sub_72764(pc)
    114.         move.b  #$4E,d0
    115.         moveq   #$7F,d1
    116.         jsr sub_72764(pc)
    117.         move.b  #-$4A,d0
    118.         move.b  #-$40,d1
    119.         jsr sub_72764(pc)
    120.  
    121. loc_72114:
    122.         moveq   #0,d7
    123.         move.b  3(a3),d7
    124.         beq.s   loc_72154
    125.         subq.b  #1,d7
    126.         lea $190(a6),a1
    127.         lea byte_721C2(pc),a2
    128.  
    129. loc_72126:
    130.         bset    #7,(a1)
    131.         move.b  (a2)+,1(a1)
    132.         move.b  d4,2(a1)
    133.         move.b  d6,$D(a1)
    134.         move.b  d5,$E(a1)
    135.         moveq   #0,d0
    136.         move.w  (a4)+,d0
    137.         add.l   a3,d0
    138.         move.l  d0,4(a1)
    139.         move.w  (a4)+,8(a1)
    140.         move.b  (a4)+,d0
    141.         move.b  (a4)+,$B(a1)
    142.         adda.w  d6,a1
    143.         dbf d7,loc_72126
    144.  
    145. loc_72154:
    146.         lea $220(a6),a1
    147.         moveq   #5,d7
    148.  
    149. loc_7215A:
    150.         tst.b   (a1)
    151.         bpl.w   loc_7217C
    152.         moveq   #0,d0
    153.         move.b  1(a1),d0
    154.         bmi.s   loc_7216E
    155.         subq.b  #2,d0
    156.         lsl.b   #2,d0
    157.         bra.s   loc_72170
    158. ; ===========================================================================
    159.  
    160. loc_7216E:
    161.         lsr.b   #3,d0
    162.  
    163. loc_72170:
    164.         lea dword_722CC(pc),a0
    165.         movea.l (a0,d0.w),a0
    166.         bset    #2,(a0)
    167.  
    168. loc_7217C:
    169.         adda.w  d6,a1
    170.         dbf d7,loc_7215A
    171.  
    172.         tst.w   $340(a6)
    173.         bpl.s   loc_7218E
    174.         bset    #2,$100(a6)
    175.  
    176. loc_7218E:
    177.         tst.w   $370(a6)
    178.         bpl.s   loc_7219A
    179.         bset    #2,$1F0(a6)
    180.  
    181. loc_7219A:
    182.         lea $70(a6),a5
    183.         moveq   #5,d4
    184.  
    185. loc_721A0:
    186.         jsr sub_726FE(pc)
    187.         adda.w  d6,a5
    188.         dbf d4,loc_721A0
    189.         moveq   #2,d4
    190.  
    191. loc_721AC:
    192.         jsr sub_729A0(pc)
    193.         adda.w  d6,a5
    194.         dbf d4,loc_721AC
    195.  
    196. loc_721B6:
    197.         addq.w  #4,sp
    198.         rts
    199. ; ===========================================================================
    200. byte_721BA: dc.b 6, 0, 1, 2, 4, 5, 6, 0
    201.         even
    202. byte_721C2: dc.b $80, $A0, $C0, 0
    203.         even
    204. ; ===========================================================================
    205. ; ---------------------------------------------------------------------------
    206. ; Play normal sound effect
    207. ; ---------------------------------------------------------------------------
    208.  
    209. Sound_A0toCF:               ; XREF: Sound_ChkValue
    210.         tst.b   $27(a6)
    211.         bne.w   loc_722C6
    212.         tst.b   4(a6)
    213.         bne.w   loc_722C6
    214.         tst.b   $24(a6)
    215.         bne.w   loc_722C6
    216.         cmpi.b  #$B5,d7     ; is ring sound effect played?
    217.         bne.s   Sound_notB5 ; if not, branch
    218.         tst.b   $2B(a6)
    219.         bne.s   loc_721EE
    220.         move.b  #$CE,d7     ; play ring sound in left speaker
    221.  
    222. loc_721EE:
    223.         bchg    #0,$2B(a6)  ; change speaker
    224.  
    225. Sound_notB5:
    226.         cmpi.b  #$A7,d7     ; is "pushing" sound played?
    227.         bne.s   Sound_notA7 ; if not, branch
    228.         tst.b   $2C(a6)
    229.         bne.w   locret_722C4
    230.         move.b  #$80,$2C(a6)
    231.  
    232. Sound_notA7:
    233.         movea.l (Go_SoundIndex).l,a0
    234.         subi.b  #$A0,d7
    235.         lsl.w   #2,d7
    236.         movea.l (a0,d7.w),a3
    237.         movea.l a3,a1
    238.         moveq   #0,d1
    239.         move.w  (a1)+,d1
    240.         add.l   a3,d1
    241.         move.b  (a1)+,d5
    242.         move.b  (a1)+,d7
    243.         subq.b  #1,d7
    244.         moveq   #$30,d6
    245.  
    246. loc_72228:
    247.         moveq   #0,d3
    248.         move.b  1(a1),d3
    249.         move.b  d3,d4
    250.         bmi.s   loc_72244
    251.         subq.w  #2,d3
    252.         lsl.w   #2,d3
    253.         lea dword_722CC(pc),a5
    254.         movea.l (a5,d3.w),a5
    255.         bset    #2,(a5)
    256.         bra.s   loc_7226E
    257. ; ===========================================================================
    258.  
    259. loc_72244:
    260.         lsr.w   #3,d3
    261.         lea dword_722CC(pc),a5
    262.         movea.l (a5,d3.w),a5
    263.         bset    #2,(a5)
    264.         cmpi.b  #$C0,d4
    265.         bne.s   loc_7226E
    266.         move.b  d4,d0
    267.         ori.b   #$1F,d0
    268.         move.b  d0,($C00011).l
    269.         bchg    #5,d0
    270.         move.b  d0,($C00011).l
    271.  
    272. loc_7226E:
    273.         movea.l dword_722EC(pc,d3.w),a5
    274.         movea.l a5,a2
    275.         moveq   #$B,d0
    276.  
    277. loc_72276:
    278.         clr.l   (a2)+
    279.         dbf d0,loc_72276
    280.  
    281.         move.w  (a1)+,(a5)
    282.         move.b  d5,2(a5)
    283.         moveq   #0,d0
    284.         move.w  (a1)+,d0
    285.         add.l   a3,d0
    286.         move.l  d0,4(a5)
    287.         move.w  (a1)+,8(a5)
    288.         move.b  #1,$E(a5)
    289.         move.b  d6,$D(a5)
    290.         tst.b   d4
    291.         bmi.s   loc_722A8
    292.         move.b  #$C0,$A(a5)
    293.         move.l  d1,$20(a5)
    294.  
    295. loc_722A8:
    296.         dbf d7,loc_72228
    297.  
    298.         tst.b   $250(a6)
    299.         bpl.s   loc_722B8
    300.         bset    #2,$340(a6)
    301.  
    302. loc_722B8:
    303.         tst.b   $310(a6)
    304.         bpl.s   locret_722C4
    305.         bset    #2,$370(a6)
    306.  
    307. locret_722C4:
    308.         rts
    309. ; ===========================================================================
    310.  
    311. loc_722C6:
    312.         clr.b   0(a6)
    313.         rts
    314. ; ===========================================================================
    315. dword_722CC:    dc.l $FFF0D0
    316.         dc.l 0
    317.         dc.l $FFF100
    318.         dc.l $FFF130
    319.         dc.l $FFF190
    320.         dc.l $FFF1C0
    321.         dc.l $FFF1F0
    322.         dc.l $FFF1F0
    323. dword_722EC:    dc.l $FFF220
    324.         dc.l 0
    325.         dc.l $FFF250
    326.         dc.l $FFF280
    327.         dc.l $FFF2B0
    328.         dc.l $FFF2E0
    329.         dc.l $FFF310
    330.         dc.l $FFF310
    331. ; ===========================================================================
    332. ; ---------------------------------------------------------------------------
    333. ; Play GHZ waterfall sound
    334. ; ---------------------------------------------------------------------------
    335.  
    336. Sound_D0toDF:               ; XREF: Sound_ChkValue
    337.         tst.b   $27(a6)
    338.         bne.w   locret_723C6
    339.         tst.b   4(a6)
    340.         bne.w   locret_723C6
    341.         tst.b   $24(a6)
    342.         bne.w   locret_723C6
    343.         movea.l (Go_SoundD0).l,a0
    344.         subi.b  #$D0,d7
    345.         lsl.w   #2,d7
    346.         movea.l (a0,d7.w),a3
    347.         movea.l a3,a1
    348.         moveq   #0,d0
    349.         move.w  (a1)+,d0
    350.         add.l   a3,d0
    351.         move.l  d0,$20(a6)
    352.         move.b  (a1)+,d5
    353.         move.b  (a1)+,d7
    354.         subq.b  #1,d7
    355.         moveq   #$30,d6
    356.  
    357. loc_72348:
    358.         move.b  1(a1),d4
    359.         bmi.s   loc_7235A
    360.         bset    #2,$100(a6)
    361.         lea $340(a6),a5
    362.         bra.s   loc_72364
    363. ; ===========================================================================
    364.  
    365. loc_7235A:
    366.         bset    #2,$1F0(a6)
    367.         lea $370(a6),a5
    368.  
    369. loc_72364:
    370.         movea.l a5,a2
    371.         moveq   #$B,d0
    372.  
    373. loc_72368:
    374.         clr.l   (a2)+
    375.         dbf d0,loc_72368
    376.  
    377.         move.w  (a1)+,(a5)
    378.         move.b  d5,2(a5)
    379.         moveq   #0,d0
    380.         move.w  (a1)+,d0
    381.         add.l   a3,d0
    382.         move.l  d0,4(a5)
    383.         move.w  (a1)+,8(a5)
    384.         move.b  #1,$E(a5)
    385.         move.b  d6,$D(a5)
    386.         tst.b   d4
    387.         bmi.s   loc_72396
    388.         move.b  #$C0,$A(a5)
    389.  
    390. loc_72396:
    391.         dbf d7,loc_72348
    392.  
    393.         tst.b   $250(a6)
    394.         bpl.s   loc_723A6
    395.         bset    #2,$340(a6)
    396.  
    397. loc_723A6:
    398.         tst.b   $310(a6)
    399.         bpl.s   locret_723C6
    400.         bset    #2,$370(a6)
    401.         ori.b   #$1F,d4
    402.         move.b  d4,($C00011).l
    403.         bchg    #5,d4
    404.         move.b  d4,($C00011).l
    405.  
    406. locret_723C6:
    407.         rts
    408. ; End of function Sound_ChkValue
    409.  
    410. ; ===========================================================================
    411.         dc.l $FFF100
    412.         dc.l $FFF1F0
    413.         dc.l $FFF250
    414.         dc.l $FFF310
    415.         dc.l $FFF340
    416.         dc.l $FFF370
    417.  
    418. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    419.  
    420.  
    421. Snd_FadeOut1:               ; XREF: Sound_E0
    422.         clr.b   0(a6)
    423.         lea $220(a6),a5
    424.         moveq   #5,d7
    425.  
    426. loc_723EA:
    427.         tst.b   (a5)
    428.         bpl.w   loc_72472
    429.         bclr    #7,(a5)
    430.         moveq   #0,d3
    431.         move.b  1(a5),d3
    432.         bmi.s   loc_7243C
    433.         jsr sub_726FE(pc)
    434.         cmpi.b  #4,d3
    435.         bne.s   loc_72416
    436.         tst.b   $340(a6)
    437.         bpl.s   loc_72416
    438.         lea $340(a6),a5
    439.         movea.l $20(a6),a1
    440.         bra.s   loc_72428
    441. ; ===========================================================================
    442.  
    443. loc_72416:
    444.         subq.b  #2,d3
    445.         lsl.b   #2,d3
    446.         lea dword_722CC(pc),a0
    447.         movea.l a5,a3
    448.         movea.l (a0,d3.w),a5
    449.         movea.l $18(a6),a1
    450.  
    451. loc_72428:
    452.         bclr    #2,(a5)
    453.         bset    #1,(a5)
    454.         move.b  $B(a5),d0
    455.         jsr sub_72C4E(pc)
    456.         movea.l a3,a5
    457.         bra.s   loc_72472
    458. ; ===========================================================================
    459.  
    460. loc_7243C:
    461.         jsr sub_729A0(pc)
    462.         lea $370(a6),a0
    463.         cmpi.b  #$E0,d3
    464.         beq.s   loc_7245A
    465.         cmpi.b  #$C0,d3
    466.         beq.s   loc_7245A
    467.         lsr.b   #3,d3
    468.         lea dword_722CC(pc),a0
    469.         movea.l (a0,d3.w),a0
    470.  
    471. loc_7245A:
    472.         bclr    #2,(a0)
    473.         bset    #1,(a0)
    474.         cmpi.b  #$E0,1(a0)
    475.         bne.s   loc_72472
    476.         move.b  $1F(a0),($C00011).l
    477.  
    478. loc_72472:
    479.         adda.w  #$30,a5
    480.         dbf d7,loc_723EA
    481.  
    482.         rts
    483. ; End of function Snd_FadeOut1
    484.  
    485.  
    486. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    487.  
    488.  
    489. Snd_FadeOut2:               ; XREF: Sound_E0
    490.         lea $340(a6),a5
    491.         tst.b   (a5)
    492.         bpl.s   loc_724AE
    493.         bclr    #7,(a5)
    494.         btst    #2,(a5)
    495.         bne.s   loc_724AE
    496.         jsr loc_7270A(pc)
    497.         lea $100(a6),a5
    498.         bclr    #2,(a5)
    499.         bset    #1,(a5)
    500.         tst.b   (a5)
    501.         bpl.s   loc_724AE
    502.         movea.l $18(a6),a1
    503.         move.b  $B(a5),d0
    504.         jsr sub_72C4E(pc)
    505.  
    506. loc_724AE:
    507.         lea $370(a6),a5
    508.         tst.b   (a5)
    509.         bpl.s   locret_724E4
    510.         bclr    #7,(a5)
    511.         btst    #2,(a5)
    512.         bne.s   locret_724E4
    513.         jsr loc_729A6(pc)
    514.         lea $1F0(a6),a5
    515.         bclr    #2,(a5)
    516.         bset    #1,(a5)
    517.         tst.b   (a5)
    518.         bpl.s   locret_724E4
    519.         cmpi.b  #-$20,1(a5)
    520.         bne.s   locret_724E4
    521.         move.b  $1F(a5),($C00011).l
    522.  
    523. locret_724E4:
    524.         rts
    525. ; End of function Snd_FadeOut2
    526.  
    527. ; ===========================================================================
    528. ; ---------------------------------------------------------------------------
    529. ; Fade out music
    530. ; ---------------------------------------------------------------------------
    531.  
    532. Sound_E0:               ; XREF: Sound_ExIndex
    533.         jsr Snd_FadeOut1(pc)
    534.         jsr Snd_FadeOut2(pc)
    535.         move.b  #3,6(a6)
    536.         move.b  #$28,4(a6)
    537.         clr.b   $40(a6)
    538.         clr.b   $2A(a6)
    539.         rts
    540.  
    541. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    542.  
    543.  
    544. sub_72504:              ; XREF: sub_71B4C
    545.         move.b  6(a6),d0
    546.         beq.s   loc_72510
    547.         subq.b  #1,6(a6)
    548.         rts
    549. ; ===========================================================================
    550.  
    551. loc_72510:
    552.         subq.b  #1,4(a6)
    553.         beq.w   Sound_E4
    554.         move.b  #3,6(a6)
    555.         lea $70(a6),a5
    556.         moveq   #5,d7
    557.  
    558. loc_72524:
    559.         tst.b   (a5)
    560.         bpl.s   loc_72538
    561.         addq.b  #1,9(a5)
    562.         bpl.s   loc_72534
    563.         bclr    #7,(a5)
    564.         bra.s   loc_72538
    565. ; ===========================================================================
    566.  
    567. loc_72534:
    568.         jsr sub_72CB4(pc)
    569.  
    570. loc_72538:
    571.         adda.w  #$30,a5
    572.         dbf d7,loc_72524
    573.  
    574.         moveq   #2,d7
    575.  
    576. loc_72542:
    577.         tst.b   (a5)
    578.         bpl.s   loc_72560
    579.         addq.b  #1,9(a5)
    580.         cmpi.b  #$10,9(a5)
    581.         bcs.s   loc_72558
    582.         bclr    #7,(a5)
    583.         bra.s   loc_72560
    584. ; ===========================================================================
    585.  
    586. loc_72558:
    587.         move.b  9(a5),d6
    588.         jsr sub_7296A(pc)
    589.  
    590. loc_72560:
    591.         adda.w  #$30,a5
    592.         dbf d7,loc_72542
    593.  
    594.         rts
    595. ; End of function sub_72504
    596.  
    597.  
    598. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    599.  
    600.  
    601. sub_7256A:              ; XREF: Sound_E4; sub_725CA
    602.         moveq   #2,d3
    603.         moveq   #$28,d0
    604.  
    605. loc_7256E:
    606.         move.b  d3,d1
    607.         jsr sub_7272E(pc)
    608.         addq.b  #4,d1
    609.         jsr sub_7272E(pc)
    610.         dbf d3,loc_7256E
    611.  
    612.         moveq   #$40,d0
    613.         moveq   #$7F,d1
    614.         moveq   #2,d4
    615.  
    616. loc_72584:
    617.         moveq   #3,d3
    618.  
    619. loc_72586:
    620.         jsr sub_7272E(pc)
    621.         jsr sub_72764(pc)
    622.         addq.w  #4,d0
    623.         dbf d3,loc_72586
    624.  
    625.         subi.b  #$F,d0
    626.         dbf d4,loc_72584
    627.  
    628.         rts
    629. ; End of function sub_7256A
    630.  
    631. ; ===========================================================================
    632. ; ---------------------------------------------------------------------------
    633. ; Stop music
    634. ; ---------------------------------------------------------------------------
    635.  
    636. Sound_E4:               ; XREF: Sound_ChkValue; Sound_ExIndex; sub_72504
    637.         moveq   #$2B,d0
    638.         move.b  #$80,d1
    639.         jsr sub_7272E(pc)
    640.         moveq   #$27,d0
    641.         moveq   #0,d1
    642.         jsr sub_7272E(pc)
    643.         movea.l a6,a0
    644.         move.w  #$E3,d0
    645.  
    646. loc_725B6:
    647.         clr.l   (a0)+
    648.         dbf d0,loc_725B6
    649.  
    650.         move.b  #$80,9(a6)  ; set music to $80 (silence)
    651.         jsr sub_7256A(pc)
    652.         bra.w   sub_729B6
    653.  
    654. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    655.  
    656.  
    657. sub_725CA:              ; XREF: Sound_ChkValue
    658.         movea.l a6,a0
    659.         move.b  0(a6),d1
    660.         move.b  $27(a6),d2
    661.         move.b  $2A(a6),d3
    662.         move.b  $26(a6),d4
    663.         move.w  $A(a6),d5
    664.         move.w  #$87,d0
    665.  
    666. loc_725E4:
    667.         clr.l   (a0)+
    668.         dbf d0,loc_725E4
    669.  
    670.         move.b  d1,0(a6)
    671.         move.b  d2,$27(a6)
    672.         move.b  d3,$2A(a6)
    673.         move.b  d4,$26(a6)
    674.         move.w  d5,$A(a6)
    675.         move.b  #$80,9(a6)
    676.         jsr sub_7256A(pc)
    677.         bra.w   sub_729B6
    678. ; End of function sub_725CA
    679.  
    680.  
    681. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    682.  
    683.  
    684. sub_7260C:              ; XREF: sub_71B4C
    685.         move.b  2(a6),1(a6)
    686.         lea $4E(a6),a0
    687.         moveq   #$30,d0
    688.         moveq   #9,d1
    689.  
    690. loc_7261A:
    691.         addq.b  #1,(a0)
    692.         adda.w  d0,a0
    693.         dbf d1,loc_7261A
    694.  
    695.         rts
    696. ; End of function sub_7260C
    697.  
    698. ; ===========================================================================
    699. ; ---------------------------------------------------------------------------
    700. ; Speed up music
    701. ; ---------------------------------------------------------------------------
    702.  
    703. Sound_E2:               ; XREF: Sound_ExIndex
    704.         tst.b   $27(a6)
    705.         bne.s   loc_7263E
    706.         move.b  $29(a6),2(a6)
    707.         move.b  $29(a6),1(a6)
    708.         move.b  #$80,$2A(a6)
    709.         rts
    710. ; ===========================================================================
    711.  
    712. loc_7263E:
    713.         move.b  $3C9(a6),$3A2(a6)
    714.         move.b  $3C9(a6),$3A1(a6)
    715.         move.b  #$80,$3CA(a6)
    716.         rts
    717. ; ===========================================================================
    718. ; ---------------------------------------------------------------------------
    719. ; Change music back to normal speed
    720. ; ---------------------------------------------------------------------------
    721.  
    722. Sound_E3:               ; XREF: Sound_ExIndex
    723.         tst.b   $27(a6)
    724.         bne.s   loc_7266A
    725.         move.b  $28(a6),2(a6)
    726.         move.b  $28(a6),1(a6)
    727.         clr.b   $2A(a6)
    728.         rts
    729. ; ===========================================================================
    730.  
    731. loc_7266A:
    732.         move.b  $3C8(a6),$3A2(a6)
    733.         move.b  $3C8(a6),$3A1(a6)
    734.         clr.b   $3CA(a6)
    735.         rts
    736.  
    737. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    738.  
    739.  
    740. sub_7267C:              ; XREF: sub_71B4C
    741.         tst.b   $25(a6)
    742.         beq.s   loc_72688
    743.         subq.b  #1,$25(a6)
    744.         rts
    745. ; ===========================================================================
    746.  
    747. loc_72688:
    748.         tst.b   $26(a6)
    749.         beq.s   loc_726D6
    750.         subq.b  #1,$26(a6)
    751.         move.b  #2,$25(a6)
    752.         lea $70(a6),a5
    753.         moveq   #5,d7
    754.  
    755. loc_7269E:
    756.         tst.b   (a5)
    757.         bpl.s   loc_726AA
    758.         subq.b  #1,9(a5)
    759.         jsr sub_72CB4(pc)
    760.  
    761. loc_726AA:
    762.         adda.w  #$30,a5
    763.         dbf d7,loc_7269E
    764.         moveq   #2,d7
    765.  
    766. loc_726B4:
    767.         tst.b   (a5)
    768.         bpl.s   loc_726CC
    769.         subq.b  #1,9(a5)
    770.         move.b  9(a5),d6
    771.         cmpi.b  #$10,d6
    772.         bcs.s   loc_726C8
    773.         moveq   #$F,d6
    774.  
    775. loc_726C8:
    776.         jsr sub_7296A(pc)
    777.  
    778. loc_726CC:
    779.         adda.w  #$30,a5
    780.         dbf d7,loc_726B4
    781.         rts
    782. ; ===========================================================================
    783.  
    784. loc_726D6:
    785.         bclr    #2,$40(a6)
    786.         clr.b   $24(a6)
    787.         rts
    788. ; End of function sub_7267C
    789.  
    790. ; ===========================================================================
    791.  
    792. loc_726E2:              ; XREF: sub_71CCA
    793.         btst    #1,(a5)
    794.         bne.s   locret_726FC
    795.         btst    #2,(a5)
    796.         bne.s   locret_726FC
    797.         moveq   #$28,d0
    798.         move.b  1(a5),d1
    799.         ori.b   #-$10,d1
    800.         bra.w   sub_7272E
    801. ; ===========================================================================
    802.  
    803. locret_726FC:
    804.         rts
    805.  
    806. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    807.  
    808.  
    809. sub_726FE:              ; XREF: sub_71CEC; sub_71D9E; Sound_ChkValue; Snd_FadeOut1
    810.         btst    #4,(a5)
    811.         bne.s   locret_72714
    812.         btst    #2,(a5)
    813.         bne.s   locret_72714
    814.  
    815. loc_7270A:              ; XREF: Snd_FadeOut2
    816.         moveq   #$28,d0
    817.         move.b  1(a5),d1
    818.         bra.w   sub_7272E
    819. ; ===========================================================================
    820.  
    821. locret_72714:
    822.         rts
    823. ; End of function sub_726FE
    824.  
    825. ; ===========================================================================
    826.  
    827. loc_72716:              ; XREF: sub_72A5A
    828.         btst    #2,(a5)
    829.         bne.s   locret_72720
    830.         bra.w   sub_72722
    831. ; ===========================================================================
    832.  
    833. locret_72720:
    834.         rts
    And replace it all with:

    Code (Text):
    1. ; ===========================================================================
    2. ; ---------------------------------------------------------------------------
    3. ; Play music track $81-$9F
    4. ; ---------------------------------------------------------------------------
    5.  
    6. Sound_81to9F:               ; XREF: Sound_ChkValue
    7.  
    8.  
    9.         StopZ80
    10.         lea (StopSample).l,a0               ; MJ: load stop sample address
    11.         lea ($A00000+PCM1_Sample).l,a1          ; MJ: load PCM 1 slot address
    12.         move.b  (a0)+,(a1)+                 ; MJ: set address of sample
    13.         move.b  (a0)+,(a1)+                 ; MJ: ''
    14.         move.b  (a0)+,(a1)+                 ; MJ: ''
    15.         move.b  #(CUPCM1_NewSample&$FF),($A00000+CU_Stack).l    ; MJ: set routine to run
    16.         move.b  #(CUPCM1_NewSample>>$08),($A00000+CU_Stack+1).l ; MJ: ''
    17.         move.b  #%11001001,($A00000+CUPCM1_RET).l       ; MJ: change "NOP" to "RET"
    18.         lea (StopSample).l,a0               ; MJ: load stop sample address
    19.         lea ($A00000+PCM2_Sample).l,a1          ; MJ: load PCM 2 slot address
    20.         move.b  (a0)+,(a1)+                 ; MJ: ''
    21.         move.b  (a0)+,(a1)+                 ; MJ: ''
    22.         move.b  (a0)+,(a1)+                 ; MJ: ''
    23.         move.b  #%00101000,($A00000+CUPCM2_RET).l       ; MJ: change "JR NZ" to "JR Z"
    24.         StartZ80
    25.  
    26.  
    27.  
    28.         cmpi.b  #$88,d7     ; is "extra life" music played?
    29.         bne.s   loc_72024   ; if not, branch
    30.         tst.b   $27(a6)
    31.         bne.w   loc_721B6
    32.         lea $40(a6),a5
    33.         moveq   #10,d0                  ; MJ: number of channels in total
    34.  
    35. loc_71FE6:
    36.         bclr    #2,(a5)
    37.         adda.w  #$30,a5
    38.         dbf d0,loc_71FE6
    39.  
    40.         lea $250(a6),a5             ; MJ: new SFX location
    41.         moveq   #5,d0
    42.  
    43. loc_71FF8:
    44.         bclr    #7,(a5)
    45.         adda.w  #$30,a5
    46.         dbf d0,loc_71FF8
    47.         clr.b   0(a6)
    48.         movea.l a6,a0
    49.         lea $3D0(a6),a1             ; MJ: new SFX location
    50.         move.w  #$87,d0
    51.  
    52. loc_72012:
    53.         move.l  (a0)+,(a1)+
    54.         dbf d0,loc_72012
    55.  
    56.         move.b  #$80,$27(a6)
    57.         clr.b   0(a6)
    58.         bra.s   loc_7202C
    59. ; ===========================================================================
    60.  
    61. loc_72024:
    62.         clr.b   $27(a6)
    63.         clr.b   $26(a6)
    64.  
    65. loc_7202C:
    66.         jsr sub_725CA(pc)
    67.         movea.l (off_719A0).l,a4
    68.         subi.b  #$81,d7
    69.         move.b  (a4,d7.w),$29(a6)
    70.         movea.l (Go_MusicIndex).l,a4
    71.         lsl.w   #2,d7
    72.         movea.l (a4,d7.w),a4
    73.         moveq   #0,d0
    74.         move.w  (a4),d0
    75.         add.l   a4,d0
    76.         move.l  d0,$18(a6)
    77.         move.b  5(a4),d0
    78.         move.b  d0,$28(a6)
    79.         tst.b   $2A(a6)
    80.         beq.s   loc_72068
    81.         move.b  $29(a6),d0
    82.  
    83. loc_72068:
    84.         move.b  d0,2(a6)
    85.         move.b  d0,1(a6)
    86.         moveq   #0,d1
    87.         movea.l a4,a3
    88.         addq.w  #6,a4
    89.         moveq   #0,d7
    90.         move.b  2(a3),d7
    91.         beq.w   loc_72114
    92.         subq.b  #1,d7
    93.         move.b  #-$40,d1
    94.         move.b  4(a3),d4
    95.         moveq   #$30,d6
    96.         move.b  #1,d5
    97.         lea $40(a6),a1
    98.         lea byte_721BA(pc),a2
    99.  
    100. loc_72098:
    101.         bset    #7,(a1)
    102.         move.b  (a2)+,1(a1)
    103.         move.b  d4,2(a1)
    104.         move.b  d6,$D(a1)
    105.         move.b  d1,$A(a1)
    106.         move.b  d5,$E(a1)
    107.         moveq   #0,d0
    108.         move.w  d0,$10(a1)              ; MJ: clear FM's frequency (ensures no frequency writing)
    109.         move.w  (a4)+,d0
    110.         add.l   a3,d0
    111.         move.l  d0,4(a1)
    112.         move.w  (a4)+,8(a1)
    113.         adda.w  d6,a1
    114.         dbf d7,loc_72098
    115.         moveq   #$2B,d0                 ; MJ: set YM2612 address to DAC/FM6 switch
    116.         move.b  #%10000000,d1               ; MJ: set to turn DAC on
    117.         cmpi.b  #8,2(a3)                ; MJ: changed to 8 (8 = 6FM channels, no DAC)
    118.         bne.s   loc_720D8
    119.     ;   moveq   #$2B,d0                 ; MJ: removed...
    120.         moveq   #0,d1
    121.         jsr sub_7272E(pc)
    122.         bra.w   loc_72114
    123. ; ===========================================================================
    124.  
    125. loc_720D8:
    126.         jsr sub_7272E(pc)               ; MJ: added... (turn DAC on)
    127.         moveq   #$28,d0
    128.         moveq   #6,d1
    129.         jsr sub_7272E(pc)
    130.         move.b  #$42,d0
    131.         moveq   #$7F,d1
    132.         jsr sub_72764(pc)
    133.         move.b  #$4A,d0
    134.         moveq   #$7F,d1
    135.         jsr sub_72764(pc)
    136.         move.b  #$46,d0
    137.         moveq   #$7F,d1
    138.         jsr sub_72764(pc)
    139.         move.b  #$4E,d0
    140.         moveq   #$7F,d1
    141.         jsr sub_72764(pc)
    142.         move.b  #-$4A,d0
    143.         move.b  #-$40,d1
    144.         jsr sub_72764(pc)
    145.  
    146. loc_72114:
    147.         moveq   #$02,d5                 ; EXT: set PSG to delay for 1 extra frame (This is to match the PSG with the FM/DAC which is delayed a frame by the Z80)
    148.         moveq   #0,d7
    149.         move.b  3(a3),d7
    150.         beq.s   loc_72154
    151.         subq.b  #1,d7
    152.         lea $1C0(a6),a1             ; MJ: new BGM/SFX location
    153.         lea byte_721C2(pc),a2
    154.  
    155. loc_72126:
    156.         bset    #7,(a1)
    157.         move.b  (a2)+,1(a1)
    158.         move.b  d4,2(a1)
    159.         move.b  d6,$D(a1)
    160.         move.b  d5,$E(a1)
    161.         move.w  #$FFFF,$10(a1)              ; MJ: clear PSG's frequency (ensures no frequency writing)
    162.         move.b  #$01,$12(a1)                ; MJ: set key release rate to 1
    163.         moveq   #0,d0
    164.         move.w  (a4)+,d0
    165.         add.l   a3,d0
    166.         move.l  d0,4(a1)
    167.         move.w  (a4)+,8(a1)
    168.         move.b  (a4)+,d0
    169.         move.b  (a4)+,$B(a1)
    170.         adda.w  d6,a1
    171.         dbf d7,loc_72126
    172.  
    173. loc_72154:
    174.         lea $250(a6),a1             ; MJ: new SFX location
    175.         moveq   #5,d7
    176.  
    177. loc_7215A:
    178.         tst.b   (a1)
    179.         bpl.w   loc_7217C
    180.         moveq   #0,d0
    181.         move.b  1(a1),d0
    182.         bmi.s   loc_7216E
    183.         subq.b  #2,d0
    184.         lsl.b   #2,d0
    185.         bra.s   loc_72170
    186. ; ===========================================================================
    187.  
    188. loc_7216E:
    189.         lsr.b   #3,d0
    190.  
    191. loc_72170:
    192.         lea dword_722CC(pc),a0
    193.         movea.l (a0,d0.w),a0
    194.         bset    #2,(a0)
    195.  
    196. loc_7217C:
    197.         adda.w  d6,a1
    198.         dbf d7,loc_7215A
    199.  
    200.         tst.w   $370(a6)                ; MJ: new SFX location
    201.         bpl.s   loc_7218E
    202.         bset    #2,$130(a6)             ; MJ: new BGM location
    203.  
    204. loc_7218E:
    205.         tst.w   $3A0(a6)                ; MJ: new SFX location
    206.         bpl.s   loc_7219A
    207.         bset    #2,$220(a6)             ; MJ: new BGM location
    208.  
    209.  
    210. loc_7219A:
    211.         lea $A0(a6),a5              ; MJ: new FM location
    212.         moveq   #5,d4
    213.  
    214. loc_721A0:
    215.         jsr sub_726FE(pc)
    216.         adda.w  d6,a5
    217.         dbf d4,loc_721A0
    218.         moveq   #2,d4
    219.  
    220. loc_721AC:
    221.         jsr sub_729A0(pc)
    222.         adda.w  d6,a5
    223.         dbf d4,loc_721AC
    224.  
    225. loc_721B6:
    226.         addq.w  #4,sp
    227.         rts
    228. ; ===========================================================================
    229. byte_721BA: dc.b 6, 6, 0, 1, 2, 4, 5, 6, 0          ; MJ: extra 6 (for PCM 2)
    230.         even
    231. byte_721C2: dc.b $80, $A0, $C0, 0
    232.         even
    233. ; ===========================================================================
    234. ; ---------------------------------------------------------------------------
    235. ; Play normal sound effect
    236. ; ---------------------------------------------------------------------------
    237.  
    238. Sound_A0toCF:               ; XREF: Sound_ChkValue
    239.         tst.b   $27(a6)
    240.         bne.w   loc_722C6
    241.         tst.b   4(a6)
    242.         bne.w   loc_722C6
    243.         tst.b   $24(a6)
    244.         bne.w   loc_722C6
    245.         cmpi.b  #$B5,d7     ; is ring sound effect played?
    246.         bne.s   Sound_notB5 ; if not, branch
    247.         tst.b   $2B(a6)
    248.         bne.s   loc_721EE
    249.         move.b  #$CE,d7     ; play ring sound in left speaker
    250.  
    251. loc_721EE:
    252.         bchg    #0,$2B(a6)  ; change speaker
    253.  
    254. Sound_notB5:
    255.         cmpi.b  #$A7,d7     ; is "pushing" sound played?
    256.         bne.s   Sound_notA7 ; if not, branch
    257.         tst.b   $2C(a6)
    258.         bne.w   locret_722C4
    259.         move.b  #$80,$2C(a6)
    260.  
    261. Sound_notA7:
    262.         movea.l (Go_SoundIndex).l,a0
    263.         subi.b  #$A0,d7
    264.         lsl.w   #2,d7
    265.         movea.l (a0,d7.w),a3
    266.         movea.l a3,a1
    267.         moveq   #0,d1
    268.         move.w  (a1)+,d1
    269.         add.l   a3,d1
    270.         move.b  (a1)+,d5
    271.         move.b  (a1)+,d7
    272.         subq.b  #1,d7
    273.         moveq   #$30,d6
    274.  
    275. loc_72228:
    276.         moveq   #0,d3
    277.         move.b  1(a1),d3
    278.         moveq   #$02,d2                 ; EXT: set PSG to delay for 1 extra frame (This is to match the PSG with the FM/DAC which is delayed a frame by the Z80)
    279.         move.b  d3,d4
    280.         bmi.s   loc_72244
    281.         move.b  #$01,d2                 ; EXT: set DAC/FM to delay for 0 frames like normal (these have an auto delay of 1 frame in the Z80)
    282.         subq.w  #2,d3
    283.         lsl.w   #2,d3
    284.         lea dword_722CC(pc),a5
    285.         movea.l (a5,d3.w),a5
    286.         bset    #2,(a5)
    287.         bra.s   loc_7226E
    288. ; ===========================================================================
    289.  
    290. loc_72244:
    291.         lsr.w   #3,d3
    292.         lea dword_722CC(pc),a5
    293.         movea.l (a5,d3.w),a5
    294.         bset    #2,(a5)
    295.         cmpi.b  #$C0,d4
    296.         bne.s   loc_7226E
    297.         move.b  d4,d0
    298.         ori.b   #$1F,d0
    299.         move.b  d0,($C00011).l
    300.         bchg    #5,d0
    301.         move.b  d0,($C00011).l
    302.  
    303. loc_7226E:
    304.         movea.l dword_722EC(pc,d3.w),a5
    305.         movea.l a5,a2
    306.         moveq   #$B,d0
    307.  
    308. loc_72276:
    309.         clr.l   (a2)+
    310.         dbf d0,loc_72276
    311.  
    312.         move.w  (a1)+,(a5)
    313.         move.b  d5,2(a5)
    314.         moveq   #0,d0
    315.         move.w  (a1)+,d0
    316.         add.l   a3,d0
    317.         move.l  d0,4(a5)
    318.         move.w  (a1)+,8(a5)
    319.         move.b  d2,$E(a5)               ; EXT: moving d2 contents (1 for FM/4 for PSG)
    320.         move.b  d6,$D(a5)
    321.         tst.b   d4
    322.         bmi.s   loc_722A8
    323.         move.b  #$C0,$A(a5)
    324.         move.l  d1,$20(a5)
    325.  
    326. loc_722A8:
    327.         dbf d7,loc_72228
    328.  
    329.         tst.b   $280(a6)                ; MJ: new SFX location
    330.         bpl.s   loc_722B8
    331.         bset    #2,$370(a6)             ; MJ: new SFX location
    332.  
    333. loc_722B8:
    334.         tst.b   $340(a6)                ; MJ: new SFX location
    335.         bpl.s   locret_722C4
    336.         bset    #2,$3A0(a6)             ; MJ: new SFX location
    337.  
    338. locret_722C4:
    339.         rts
    340. ; ===========================================================================
    341.  
    342. loc_722C6:
    343.         clr.b   0(a6)
    344.         rts
    345. ; ===========================================================================
    346. dword_722CC:    dc.l $FFF0D0+$30                ; MJ: new locations (see all +$30)
    347.         dc.l 0
    348.         dc.l $FFF100+$30
    349.         dc.l $FFF130+$30
    350.         dc.l $FFF190+$30
    351.         dc.l $FFF1C0+$30
    352.         dc.l $FFF1F0+$30
    353.         dc.l $FFF1F0+$30
    354. dword_722EC:    dc.l $FFF220+$30
    355.         dc.l 0
    356.         dc.l $FFF250+$30
    357.         dc.l $FFF280+$30
    358.         dc.l $FFF2B0+$30
    359.         dc.l $FFF2E0+$30
    360.         dc.l $FFF310+$30
    361.         dc.l $FFF310+$30
    362. ; ===========================================================================
    363. ; ---------------------------------------------------------------------------
    364. ; Play GHZ waterfall sound
    365. ; ---------------------------------------------------------------------------
    366.  
    367. Sound_D0toDF:               ; XREF: Sound_ChkValue
    368.         tst.b   $27(a6)
    369.         bne.w   locret_723C6
    370.         tst.b   4(a6)
    371.         bne.w   locret_723C6
    372.         tst.b   $24(a6)
    373.         bne.w   locret_723C6
    374.         movea.l (Go_SoundD0).l,a0
    375.         subi.b  #$D0,d7
    376.         lsl.w   #2,d7
    377.         movea.l (a0,d7.w),a3
    378.         movea.l a3,a1
    379.         moveq   #0,d0
    380.         move.w  (a1)+,d0
    381.         add.l   a3,d0
    382.         move.l  d0,$20(a6)
    383.         move.b  (a1)+,d5
    384.         move.b  (a1)+,d7
    385.         subq.b  #1,d7
    386.         moveq   #$30,d6
    387.  
    388. loc_72348:
    389.         move.b  1(a1),d4
    390.         bmi.s   loc_7235A
    391.         bset    #2,$130(a6)             ; MJ: new BGM location
    392.         lea $370(a6),a5             ; MJ: new SFX location
    393.         bra.s   loc_72364
    394. ; ===========================================================================
    395.  
    396. loc_7235A:
    397.         bset    #2,$220(a6)             ; MJ: new BGM location
    398.         lea $3A0(a6),a5             ; MJ: new SFX location
    399.  
    400. loc_72364:
    401.         movea.l a5,a2
    402.         moveq   #$B,d0
    403.  
    404. loc_72368:
    405.         clr.l   (a2)+
    406.         dbf d0,loc_72368
    407.  
    408.         move.w  (a1)+,(a5)
    409.         move.b  d5,2(a5)
    410.         moveq   #0,d0
    411.         move.w  (a1)+,d0
    412.         add.l   a3,d0
    413.         move.l  d0,4(a5)
    414.         move.w  (a1)+,8(a5)
    415.         move.b  #1,$E(a5)
    416.         move.b  d6,$D(a5)
    417.         tst.b   d4
    418.         bmi.s   loc_72396
    419.         move.b  #$C0,$A(a5)
    420.  
    421. loc_72396:
    422.         dbf d7,loc_72348
    423.  
    424.         tst.b   $280(a6)                ; MJ: new SFX location
    425.         bpl.s   loc_723A6
    426.         bset    #2,$370(a6)             ; MJ: new SFX location
    427.  
    428. loc_723A6:
    429.         tst.b   $340(a6)                ; MJ: new SFX location
    430.         bpl.s   locret_723C6
    431.         bset    #2,$3A0(a6)             ; MJ: new SFX location
    432.         ori.b   #$1F,d4
    433.         move.b  d4,($C00011).l
    434.         bchg    #5,d4
    435.         move.b  d4,($C00011).l
    436.  
    437. locret_723C6:
    438.         rts
    439. ; End of function Sound_ChkValue
    440.  
    441. ; ===========================================================================
    442.         dc.l $FFF100+$30                ; MJ: new channel locations (see +$30)
    443.         dc.l $FFF1F0+$30
    444.         dc.l $FFF250+$30
    445.         dc.l $FFF310+$30
    446.         dc.l $FFF340+$30
    447.         dc.l $FFF370+$30
    448.  
    449. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    450.  
    451.  
    452. Snd_FadeOut1:               ; XREF: Sound_E0
    453.         clr.b   0(a6)
    454.         lea $250(a6),a5             ; MJ: new SFX location
    455.         moveq   #5,d7
    456.  
    457. loc_723EA:
    458.         tst.b   (a5)
    459.         bpl.w   loc_72472
    460.         bclr    #7,(a5)
    461.         moveq   #0,d3
    462.         move.b  1(a5),d3
    463.         bmi.s   loc_7243C
    464.         jsr sub_726FE(pc)
    465.         cmpi.b  #4,d3
    466.         bne.s   loc_72416
    467.         tst.b   $370(a6)                ; MJ: new SFX location
    468.         bpl.s   loc_72416
    469.         lea $370(a6),a5             ; MJ: new SFX location
    470.         movea.l $20(a6),a1
    471.         bra.s   loc_72428
    472. ; ===========================================================================
    473.  
    474. loc_72416:
    475.         subq.b  #2,d3
    476.         lsl.b   #2,d3
    477.         lea dword_722CC(pc),a0
    478.         movea.l a5,a3
    479.         movea.l (a0,d3.w),a5
    480.         movea.l $18(a6),a1
    481.  
    482. loc_72428:
    483.         bclr    #2,(a5)
    484.         bset    #1,(a5)
    485.         move.b  $B(a5),d0
    486.         jsr sub_72C4E(pc)
    487.         movea.l a3,a5
    488.         bra.s   loc_72472
    489. ; ===========================================================================
    490.  
    491. loc_7243C:
    492.         jsr sub_729A0(pc)
    493.         lea $3A0(a6),a0             ; MJ: new SFX location
    494.         cmpi.b  #$E0,d3
    495.         beq.s   loc_7245A
    496.         cmpi.b  #$C0,d3
    497.         beq.s   loc_7245A
    498.         lsr.b   #3,d3
    499.         lea dword_722CC(pc),a0
    500.         movea.l (a0,d3.w),a0
    501.  
    502. loc_7245A:
    503.         bclr    #2,(a0)
    504.         bset    #1,(a0)
    505.         cmpi.b  #$E0,1(a0)
    506.         bne.s   loc_72472
    507.         move.b  $1F(a0),($C00011).l
    508.  
    509. loc_72472:
    510.         adda.w  #$30,a5
    511.         dbf d7,loc_723EA
    512.  
    513.         rts
    514. ; End of function Snd_FadeOut1
    515.  
    516.  
    517. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    518.  
    519.  
    520. Snd_FadeOut2:               ; XREF: Sound_E0
    521.         lea $370(a6),a5             ; MJ: new SFX location
    522.         tst.b   (a5)
    523.         bpl.s   loc_724AE
    524.         bclr    #7,(a5)
    525.         btst    #2,(a5)
    526.         bne.s   loc_724AE
    527.         jsr loc_7270A(pc)
    528.         lea $130(a6),a5             ; MJ: new BGM location
    529.         bclr    #2,(a5)
    530.         bset    #1,(a5)
    531.         tst.b   (a5)
    532.         bpl.s   loc_724AE
    533.         movea.l $18(a6),a1
    534.         move.b  $B(a5),d0
    535.         jsr sub_72C4E(pc)
    536.  
    537. loc_724AE:
    538.         lea $3A0(a6),a5             ; MJ: new SFX location
    539.         tst.b   (a5)
    540.         bpl.s   locret_724E4
    541.         bclr    #7,(a5)
    542.         btst    #2,(a5)
    543.         bne.s   locret_724E4
    544.         jsr loc_729A6(pc)
    545.         lea $220(a6),a5             ; MJ: new BGM location
    546.         bclr    #2,(a5)
    547.         bset    #1,(a5)
    548.         tst.b   (a5)
    549.         bpl.s   locret_724E4
    550.         cmpi.b  #-$20,1(a5)
    551.         bne.s   locret_724E4
    552.         move.b  $1F(a5),($C00011).l
    553.  
    554. locret_724E4:
    555.         rts
    556. ; End of function Snd_FadeOut2
    557.  
    558. ; ===========================================================================
    559. ; ---------------------------------------------------------------------------
    560. ; Fade out music
    561. ; ---------------------------------------------------------------------------
    562.  
    563. Sound_E0:               ; XREF: Sound_ExIndex
    564.         jsr Snd_FadeOut1(pc)
    565.         jsr Snd_FadeOut2(pc)
    566.         move.b  #3,6(a6)
    567.         move.b  #$28,4(a6)
    568.         clr.b   $40(a6)
    569.         clr.b   $70(a6)                 ; MJ: stop PCM 2 as well
    570.         clr.b   $2A(a6)
    571.         rts
    572.  
    573. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    574.  
    575.  
    576. sub_72504:              ; XREF: sub_71B4C
    577.         move.b  6(a6),d0
    578.         beq.s   loc_72510
    579.         subq.b  #1,6(a6)
    580.         rts
    581. ; ===========================================================================
    582.  
    583. loc_72510:
    584.         subq.b  #1,4(a6)
    585.         beq.w   Sound_E4
    586.         move.b  #3,6(a6)
    587.         lea $A0(a6),a5              ; MJ: new FM location
    588.         moveq   #5,d7
    589.  
    590. loc_72524:
    591.         tst.b   (a5)
    592.         bpl.s   loc_72538
    593.         addq.b  #1,9(a5)
    594.         bpl.s   loc_72534
    595.         bclr    #7,(a5)
    596.         bra.s   loc_72538
    597. ; ===========================================================================
    598.  
    599. loc_72534:
    600.         jsr sub_72CB4(pc)
    601.  
    602. loc_72538:
    603.         adda.w  #$30,a5
    604.         dbf d7,loc_72524
    605.  
    606.         moveq   #2,d7
    607.  
    608. loc_72542:
    609.         tst.b   (a5)
    610.         bpl.s   loc_72560
    611.         addq.b  #1,9(a5)
    612.         cmpi.b  #$10,9(a5)
    613.         bcs.s   loc_72558
    614.         bclr    #7,(a5)
    615.         bra.s   loc_72560
    616. ; ===========================================================================
    617.  
    618. loc_72558:
    619.         move.b  9(a5),d6
    620.         jsr sub_7296A(pc)
    621.  
    622. loc_72560:
    623.         adda.w  #$30,a5
    624.         dbf d7,loc_72542
    625.  
    626.         rts
    627. ; End of function sub_72504
    628.  
    629.  
    630. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    631.  
    632.  
    633. sub_7256A:              ; XREF: Sound_E4; sub_725CA
    634.         moveq   #2,d3
    635.         moveq   #$28,d0
    636.  
    637. loc_7256E:
    638.         move.b  d3,d1
    639.         jsr sub_7272E(pc)
    640.         addq.b  #4,d1
    641.         jsr sub_7272E(pc)
    642.         dbf d3,loc_7256E
    643.  
    644.         moveq   #$40,d0
    645.         moveq   #$7F,d1
    646.         moveq   #2,d4
    647.  
    648. loc_72584:
    649.         moveq   #3,d3
    650.  
    651. loc_72586:
    652.         jsr sub_7272E(pc)
    653.         jsr sub_72764(pc)
    654.         addq.w  #4,d0
    655.         dbf d3,loc_72586
    656.  
    657.         subi.b  #$F,d0
    658.         dbf d4,loc_72584
    659.  
    660.         rts
    661. ; End of function sub_7256A
    662.  
    663. ; ===========================================================================
    664. ; ---------------------------------------------------------------------------
    665. ; Stop music
    666. ; ---------------------------------------------------------------------------
    667.  
    668. Sound_E4:
    669.         StopZ80
    670.         lea (StopSample).l,a0               ; EXT: load stop sample address
    671.         lea ($A00000+PCM1_Sample).l,a1          ; EXT: load PCM 1 slot address
    672.         move.b  (a0)+,(a1)+                 ; EXT: set address of sample
    673.         move.b  (a0)+,(a1)+                 ; EXT: ''
    674.         move.b  (a0)+,(a1)+                 ; EXT: ''
    675.         move.b  #(CUPCM1_NewSample&$FF),($A00000+CU_Stack).l    ; EXT: set routine to run
    676.         move.b  #(CUPCM1_NewSample>>$08),($A00000+CU_Stack+1).l ; EXT: ''
    677.         move.b  #%11001001,($A00000+CUPCM1_RET).l       ; EXT: change "NOP" to "RET"
    678.         lea (StopSample).l,a0               ; EXT: load stop sample address
    679.         lea ($A00000+PCM2_Sample).l,a1          ; EXT: load PCM 2 slot address
    680.         move.b  (a0)+,(a1)+                 ; EXT: ''
    681.         move.b  (a0)+,(a1)+                 ; EXT: ''
    682.         move.b  (a0)+,(a1)+                 ; EXT: ''
    683.         move.b  #%00101000,($A00000+CUPCM2_RET).l       ; EXT: change "JR NZ" to "JR Z"
    684.         StartZ80
    685.  
    686.         moveq   #$2B,d0
    687.         move.b  #$80,d1
    688.         jsr sub_7272E(pc)
    689.         moveq   #$27,d0
    690.         moveq   #0,d1
    691.         jsr sub_7272E(pc)
    692.         movea.l a6,a0
    693.         move.l  $10(a6),d6                  ; EXT: store YM Cue list pointer
    694.         move.w  #$EF,d0                     ; MJ: new size of data to clear
    695.  
    696. loc_725B6:
    697.         clr.l   (a0)+
    698.         dbf d0,loc_725B6
    699.  
    700.         move.l  d6,$10(a6)                  ; EXT: restore YM Cue list pointer
    701.         move.b  #$80,9(a6)  ; set music to $80 (silence)
    702.         jsr sub_7256A(pc)
    703.         bra.w   sub_729B6
    704.  
    705. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    706.  
    707.  
    708. sub_725CA:              ; XREF: Sound_ChkValue
    709.         movea.l a6,a0
    710.         move.b  0(a6),d1
    711.         move.b  $27(a6),d2
    712.         move.b  $2A(a6),d3
    713.         move.b  $26(a6),d4
    714.         move.w  $A(a6),d5
    715.         move.l  $10(a6),d6                  ; EXT: store YM Cue list pointer
    716.         move.w  #$93,d0                     ; MJ: new size
    717.  
    718. loc_725E4:
    719.         clr.l   (a0)+
    720.         dbf d0,loc_725E4
    721.  
    722.         move.b  d1,0(a6)
    723.         move.b  d2,$27(a6)
    724.         move.b  d3,$2A(a6)
    725.         move.b  d4,$26(a6)
    726.         move.w  d5,$A(a6)
    727.         move.l  d6,$10(a6)                  ; EXT: restore YM Cue list pointer
    728.         move.b  #$80,9(a6)
    729.         jsr sub_7256A(pc)
    730.         bra.w   sub_729B6
    731. ; End of function sub_725CA
    732.  
    733.  
    734. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    735.  
    736.  
    737. sub_7260C:              ; XREF: sub_71B4C
    738.         move.b  2(a6),1(a6)
    739.         lea $4E(a6),a0
    740.         moveq   #$30,d0
    741.         moveq   #10,d1              ; MJ: new number of channels
    742.  
    743. loc_7261A:
    744.         addq.b  #1,(a0)
    745.         adda.w  d0,a0
    746.         dbf d1,loc_7261A
    747.  
    748.         rts
    749. ; End of function sub_7260C
    750.  
    751. ; ===========================================================================
    752. ; ---------------------------------------------------------------------------
    753. ; Speed up music
    754. ; ---------------------------------------------------------------------------
    755.  
    756. Sound_E2:               ; XREF: Sound_ExIndex
    757.         tst.b   $27(a6)
    758.         bne.s   loc_7263E
    759.         move.b  $29(a6),2(a6)
    760.         move.b  $29(a6),1(a6)
    761.         move.b  #$80,$2A(a6)
    762.         rts
    763. ; ===========================================================================
    764.  
    765. loc_7263E:
    766.         move.b  $3F9(a6),$3D2(a6)           ; MJ: new location
    767.         move.b  $3F9(a6),$3D1(a6)           ; MJ: new location
    768.         move.b  #$80,$3FA(a6)
    769.         rts
    770. ; ===========================================================================
    771. ; ---------------------------------------------------------------------------
    772. ; Change music back to normal speed
    773. ; ---------------------------------------------------------------------------
    774.  
    775. Sound_E3:               ; XREF: Sound_ExIndex
    776.         tst.b   $27(a6)
    777.         bne.s   loc_7266A
    778.         move.b  $28(a6),2(a6)
    779.         move.b  $28(a6),1(a6)
    780.         clr.b   $2A(a6)
    781.         rts
    782. ; ===========================================================================
    783.  
    784. loc_7266A:
    785.         move.b  $3F8(a6),$3D2(a6)
    786.         move.b  $3F8(a6),$3D1(a6)
    787.         clr.b   $3FA(a6)
    788.         rts
    789.  
    790. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    791.  
    792.  
    793. sub_7267C:              ; XREF: sub_71B4C
    794.         tst.b   $25(a6)
    795.         beq.s   loc_72688
    796.         subq.b  #1,$25(a6)
    797.         rts
    798. ; ===========================================================================
    799.  
    800. loc_72688:
    801.         tst.b   $26(a6)
    802.         beq.s   loc_726D6
    803.         subq.b  #1,$26(a6)
    804.         move.b  #2,$25(a6)
    805.         lea $A0(a6),a5              ; MJ: new SFX location
    806.         moveq   #5,d7
    807.  
    808. loc_7269E:
    809.         tst.b   (a5)
    810.         bpl.s   loc_726AA
    811.         subq.b  #1,9(a5)
    812.         jsr sub_72CB4(pc)
    813.  
    814. loc_726AA:
    815.         adda.w  #$30,a5
    816.         dbf d7,loc_7269E
    817.         moveq   #2,d7
    818.  
    819. loc_726B4:
    820.         tst.b   (a5)
    821.         bpl.s   loc_726CC
    822.         subq.b  #1,9(a5)
    823.         move.b  9(a5),d6
    824.         cmpi.b  #$10,d6
    825.         bcs.s   loc_726C8
    826.         moveq   #$F,d6
    827.  
    828. loc_726C8:
    829.         jsr sub_7296A(pc)
    830.  
    831. loc_726CC:
    832.         adda.w  #$30,a5
    833.         dbf d7,loc_726B4
    834.         rts
    835. ; ===========================================================================
    836.  
    837. loc_726D6:
    838.         bclr    #2,$40(a6)
    839.         bclr    #2,$70(a6)              ; MJ: do PCM 2 as well...
    840.         clr.b   $24(a6)
    841.         rts
    842. ; End of function sub_7267C
    843.  
    844. ; ===========================================================================
    845.  
    846. loc_726E2:              ; XREF: sub_71CCA
    847.         btst    #1,(a5)
    848.         bne.s   locret_726FC
    849.         btst    #2,(a5)
    850.         bne.s   locret_726FC
    851.         moveq   #$28,d0
    852.         move.b  1(a5),d1
    853.         ori.b   #-$10,d1
    854.         bra.w   sub_7272E
    855. ; ===========================================================================
    856.  
    857. locret_726FC:
    858.         rts
    859.  
    860. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    861.  
    862.  
    863. sub_726FE:              ; XREF: sub_71CEC; sub_71D9E; Sound_ChkValue; Snd_FadeOut1
    864.         btst    #4,(a5)
    865.         bne.s   locret_72714
    866.         btst    #2,(a5)
    867.         bne.s   locret_72714
    868.  
    869. loc_7270A:              ; XREF: Snd_FadeOut2
    870.         moveq   #$28,d0
    871.         move.b  1(a5),d1
    872.         bra.w   sub_7272E
    873. ; ===========================================================================
    874.  
    875. locret_72714:
    876.         rts
    877. ; End of function sub_726FE
    878.  
    879. ; ===========================================================================
    880.  
    881. loc_72716:              ; XREF: sub_72A5A
    882.         btst    #2,(a5)
    883.         bne.s   locret_72720
    884.         bra.w   sub_72722
    885. ; ===========================================================================
    886.  
    887. locret_72720:
    888.         rts
    >> 9. Next the YM2612 writing subroutine, find this:

    Code (Text):
    1. sub_72722:              ; XREF: sub_71E18; sub_72C4E; sub_72CB4
    2.         btst    #2,1(a5)
    3.         bne.s   loc_7275A
    4.         add.b   1(a5),d0
    5. ; End of function sub_72722
    6.  
    7.  
    8. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    9.  
    10.  
    11. sub_7272E:              ; XREF: loc_71E6A
    12.         move.b  ($A04000).l,d2
    13.         btst    #7,d2
    14.         bne.s   sub_7272E
    15.         move.b  d0,($A04000).l
    16.         nop
    17.         nop
    18.         nop
    19.  
    20. loc_72746:
    21.         move.b  ($A04000).l,d2
    22.         btst    #7,d2
    23.         bne.s   loc_72746
    24.  
    25.         move.b  d1,($A04001).l
    26.         rts
    27. ; End of function sub_7272E
    28.  
    29. ; ===========================================================================
    30.  
    31. loc_7275A:              ; XREF: sub_72722
    32.         move.b  1(a5),d2
    33.         bclr    #2,d2
    34.         add.b   d2,d0
    35.  
    36. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    37.  
    38.  
    39. sub_72764:              ; XREF: loc_71E6A; Sound_ChkValue; sub_7256A; sub_72764
    40.         move.b  ($A04000).l,d2
    41.         btst    #7,d2
    42.         bne.s   sub_72764
    43.         move.b  d0,($A04002).l
    44.         nop
    45.         nop
    46.         nop
    47.  
    48. loc_7277C:
    49.         move.b  ($A04000).l,d2
    50.         btst    #7,d2
    51.         bne.s   loc_7277C
    52.  
    53.         move.b  d1,($A04003).l
    54.         rts
    55. ; End of function sub_72764
    And replace it with this newer, more optimised version (this should help reduce the Z80 waiting time):

    Code (Text):
    1. sub_72722:              ; XREF: sub_71E18; sub_72C4E; sub_72CB4
    2.         btst    #2,1(a5)
    3.         bne.s   loc_7275A
    4.         add.b   1(a5),d0
    5. ; End of function sub_72722
    6.  
    7.  
    8. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    9.  
    10. sub_7272E:
    11.         movem.l d2/a0,-(sp)             ; EXT: store register data
    12.         movea.l $10(a6),a0              ; EXT: load Cue pointer
    13.         addq.w  #$01,a0                 ; EXT: skip $40
    14.         move.b  #$00,d2                 ; EXT: prepare d2 for YM2612 port address ($4000 - $4001)
    15.         StopZ80                     ; EXT: request Z80 stop "ON"
    16.         move.b  d2,(a0)+                ; EXT: write YM2612 port address
    17.         move.b  d1,(a0)+                ; EXT: write YM2612 data
    18.         move.b  d0,(a0)+                ; EXT: write YM2612 address
    19.         StartZ80                    ; EXT: request Z80 stop "OFF"
    20.         move.w  a0,d2                   ; EXT: load Cue pointer
    21.         andi.w  #$0FFF,d2               ; EXT: wrap it
    22.         ori.w   #$1000,d2               ; EXT: ''
    23.         move.w  d2,$12(a6)              ; EXT: update it
    24.         movem.l (sp)+,d2/a0             ; EXT: restore register data
    25.         rts                     ; EXT: return
    26.  
    27. ; ===========================================================================
    28.  
    29. loc_7275A:              ; XREF: sub_72722
    30.         move.b  1(a5),d2
    31.         bclr    #2,d2
    32.         add.b   d2,d0
    33.  
    34. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    35.  
    36.  
    37. sub_72764:
    38.         movem.l d2/a0,-(sp)             ; EXT: store register data
    39.         movea.l $10(a6),a0              ; EXT: load Cue pointer
    40.         addq.w  #$01,a0                 ; EXT: skip $40
    41.         move.b  #$02,d2                 ; EXT: prepare d2 for YM2612 port address ($4002 - $4003)
    42.         StopZ80                     ; EXT: request Z80 stop "ON"
    43.         move.b  d2,(a0)+                ; EXT: write YM2612 port address
    44.         move.b  d1,(a0)+                ; EXT: write YM2612 data
    45.         move.b  d0,(a0)+                ; EXT: write YM2612 address
    46.         StartZ80                    ; EXT: request Z80 stop "OFF"
    47.         move.w  a0,d2                   ; EXT: load Cue pointer
    48.         andi.w  #$0FFF,d2               ; EXT: wrap it
    49.         ori.w   #$1000,d2               ; EXT: ''
    50.         move.w  d2,$12(a6)              ; EXT: update it
    51.         movem.l (sp)+,d2/a0             ; EXT: restore register data
    52.         rts                     ; EXT: return
    >> 10. Find this:

    Code (Text):
    1. loc_72B14:              ; XREF: loc_72A64
    2.         movea.l a6,a0
    3.         lea $3A0(a6),a1
    4.         move.w  #$87,d0
    5.  
    6. loc_72B1E:
    7.         move.l  (a1)+,(a0)+
    8.         dbf d0,loc_72B1E
    9.  
    10.         bset    #2,$40(a6)
    11.         movea.l a5,a3
    12.         move.b  #$28,d6
    13.         sub.b   $26(a6),d6
    14.         moveq   #5,d7
    15.         lea $70(a6),a5
    And replace with:

    Code (Text):
    1. loc_72B14:              ; XREF: loc_72A64
    2.         movea.l a6,a0
    3.         lea $3D0(a6),a1             ; MJ: new SFX location
    4.         move.w  #$93,d0                 ; MJ: new size to store
    5.  
    6. loc_72B1E:
    7.         move.l  (a1)+,(a0)+
    8.         dbf d0,loc_72B1E
    9.  
    10.         bset    #2,$40(a6)
    11.         bset    #2,$70(a6)              ; MJ: enable PCM 2
    12.         movea.l a5,a3
    13.         move.b  #$28,d6
    14.         sub.b   $26(a6),d6
    15.         moveq   #5,d7
    16.         lea $A0(a6),a5              ; MJ: new FM location
    >> 11. Goto "loc_72B78:" and delete this line:

    Code (Text):
    1.         move.w  #0,($A11100).l
    >> 12. Find this:

    Code (Text):
    1. loc_72BD0:              ; XREF: loc_72A64
    2.         lea $40(a6),a0
    3.         move.b  (a4)+,d0
    4.         moveq   #$30,d1
    5.         moveq   #9,d2
    6.  
    7. loc_72BDA:
    8.         move.b  d0,2(a0)
    9.         adda.w  d1,a0
    10.         dbf d2,loc_72BDA
    11.  
    12.         rts
    13. ; ===========================================================================
    14.  
    15. loc_72BE6:              ; XREF: loc_72A64
    16.         move.b  (a4)+,d0
    17.         add.b   d0,9(a5)
    18.         rts
    19. ; ===========================================================================
    20.  
    21. loc_72BEE:              ; XREF: loc_72A64
    22.         clr.b   $2C(a6)
    23.         rts
    24. ; ===========================================================================
    25.  
    26. loc_72BF4:              ; XREF: loc_72A64
    27.         bclr    #7,(a5)
    28.         bclr    #4,(a5)
    29.         jsr sub_726FE(pc)
    30.         tst.b   $250(a6)
    31.         bmi.s   loc_72C22
    32.         movea.l a5,a3
    33.         lea $100(a6),a5
    34.         movea.l $18(a6),a1
    35.         bclr    #2,(a5)
    36.         bset    #1,(a5)
    37.         move.b  $B(a5),d0
    38.         jsr sub_72C4E(pc)
    39.         movea.l a3,a5
    40.  
    41. loc_72C22:
    42.         addq.w  #8,sp
    43.         rts
    And replace with:

    Code (Text):
    1. loc_72BD0:              ; XREF: loc_72A64
    2.         lea $40(a6),a0
    3.         move.b  (a4)+,d0
    4.         moveq   #$30,d1
    5.         moveq   #10,d2              ; MJ: extra channel
    6.  
    7. loc_72BDA:
    8.         move.b  d0,2(a0)
    9.         adda.w  d1,a0
    10.         dbf d2,loc_72BDA
    11.  
    12.         rts
    13. ; ===========================================================================
    14.  
    15. loc_72BE6:              ; XREF: loc_72A64
    16.         move.b  (a4)+,d0
    17.         add.b   d0,9(a5)
    18.         rts
    19. ; ===========================================================================
    20.  
    21. loc_72BEE:              ; XREF: loc_72A64
    22.         clr.b   $2C(a6)
    23.         rts
    24. ; ===========================================================================
    25.  
    26. loc_72BF4:              ; XREF: loc_72A64
    27.         bclr    #7,(a5)
    28.         bclr    #4,(a5)
    29.         jsr sub_726FE(pc)
    30.         tst.b   $280(a6)                ; MJ: new SFX location
    31.         bmi.s   loc_72C22
    32.         movea.l a5,a3
    33.         lea $130(a6),a5             ; MJ: new BGM location
    34.         movea.l $18(a6),a1
    35.         bclr    #2,(a5)
    36.         bset    #1,(a5)
    37.         move.b  $B(a5),d0
    38.         jsr sub_72C4E(pc)
    39.         movea.l a3,a5
    40.  
    41. loc_72C22:
    42.         addq.w  #8,sp
    43.         rts
    >> 13. Find this:

    Code (Text):
    1. loc_72D78:
    2.         tst.b   $E(a6)
    3.         bpl.w   loc_72E02
    4.         clr.b   0(a6)
    5.         moveq   #0,d0
    6.         move.b  1(a5),d0
    7.         bmi.s   loc_72DCC
    8.         lea dword_722CC(pc),a0
    9.         movea.l a5,a3
    10.         cmpi.b  #4,d0
    11.         bne.s   loc_72DA8
    12.         tst.b   $340(a6)
    13.         bpl.s   loc_72DA8
    14.         lea $340(a6),a5
    15.         movea.l $20(a6),a1
    16.         bra.s   loc_72DB8
    17. ; ===========================================================================
    18.  
    19. loc_72DA8:
    20.         subq.b  #2,d0
    21.         lsl.b   #2,d0
    22.         movea.l (a0,d0.w),a5
    23.         tst.b   (a5)
    24.         bpl.s   loc_72DC8
    25.         movea.l $18(a6),a1
    26.  
    27. loc_72DB8:
    28.         bclr    #2,(a5)
    29.         bset    #1,(a5)
    30.         move.b  $B(a5),d0
    31.         jsr sub_72C4E(pc)
    32.  
    33. loc_72DC8:
    34.         movea.l a3,a5
    35.         bra.s   loc_72E02
    36. ; ===========================================================================
    37.  
    38. loc_72DCC:
    39.         lea $370(a6),a0
    40.         tst.b   (a0)
    41.         bpl.s   loc_72DE0
    42.         cmpi.b  #$E0,d0
    43.         beq.s   loc_72DEA
    44.         cmpi.b  #$C0,d0
    45.         beq.s   loc_72DEA
    46.  
    47. loc_72DE0:
    48.         lea dword_722CC(pc),a0
    49.         lsr.b   #3,d0
    50.         movea.l (a0,d0.w),a0
    51.  
    52. loc_72DEA:
    53.         bclr    #2,(a0)
    54.         bset    #1,(a0)
    55.         cmpi.b  #$E0,1(a0)
    56.         bne.s   loc_72E02
    57.         move.b  $1F(a0),($C00011).l
    58.  
    59. loc_72E02:
    60.         addq.w  #8,sp
    61.         rts
    62. ; ===========================================================================
    63.  
    64. loc_72E06:              ; XREF: loc_72A64
    65.         move.b  #$E0,1(a5)
    66.         move.b  (a4)+,$1F(a5)
    67.         btst    #2,(a5)
    68.         bne.s   locret_72E1E
    69.         move.b  -1(a4),($C00011).l
    70.  
    71. locret_72E1E:
    72.         rts
    And replace with:

    Code (Text):
    1. loc_72D78:
    2.         tst.b   $E(a6)
    3.         bpl.w   loc_72E02
    4.         clr.b   0(a6)
    5.         moveq   #0,d0
    6.         move.b  1(a5),d0
    7.         bmi.s   loc_72DCC
    8.         lea dword_722CC(pc),a0
    9.         movea.l a5,a3
    10.         cmpi.b  #4,d0
    11.         bne.s   loc_72DA8
    12.         tst.b   $370(a6)                ; MJ: new SFX location
    13.         bpl.s   loc_72DA8
    14.         lea $370(a6),a5             ; MJ: new SFX location
    15.         movea.l $20(a6),a1
    16.         bra.s   loc_72DB8
    17. ; ===========================================================================
    18.  
    19. loc_72DA8:
    20.         subq.b  #2,d0
    21.         lsl.b   #2,d0
    22.         movea.l (a0,d0.w),a5
    23.         tst.b   (a5)
    24.         bpl.s   loc_72DC8
    25.         movea.l $18(a6),a1
    26.  
    27. loc_72DB8:
    28.         bclr    #2,(a5)
    29.         bset    #1,(a5)
    30.         move.b  $B(a5),d0
    31.         jsr sub_72C4E(pc)
    32.  
    33. loc_72DC8:
    34.         movea.l a3,a5
    35.         bra.s   loc_72E02
    36. ; ===========================================================================
    37.  
    38. loc_72DCC:
    39.         lea $3A0(a6),a0             ; MJ: new SFX location
    40.         tst.b   (a0)
    41.         bpl.s   loc_72DE0
    42.         cmpi.b  #$E0,d0
    43.         beq.s   loc_72DEA
    44.         cmpi.b  #$C0,d0
    45.         beq.s   loc_72DEA
    46.  
    47. loc_72DE0:
    48.         lea dword_722CC(pc),a0
    49.         lsr.b   #3,d0
    50.         movea.l (a0,d0.w),a0
    51.  
    52. loc_72DEA:
    53.         bclr    #2,(a0)
    54.         bset    #1,(a0)
    55.         cmpi.b  #$E0,1(a0)
    56.         bne.s   loc_72E02
    57.         move.b  $1F(a0),($C00011).l
    58.  
    59. loc_72E02:
    60.         addq.w  #4,sp                   ; MJ: changed to 4 (go back, but not out of sound driver)
    61.         tst.b   $08(a6)                 ; MJ: is this a PCM channel?
    62.         bne.s   FlagF2_NoWaitFrame          ; MJ: if so, branch
    63.         addq.w  #4,sp                   ; MJ: go back outside the sound driver like normal
    64.  
    65. FlagF2_NoWaitFrame:
    66.         rts
    67. ; ===========================================================================
    68.  
    69. loc_72E06:              ; XREF: loc_72A64
    70.         move.b  #$E0,1(a5)
    71.         move.b  (a4)+,$1F(a5)
    72.         btst    #2,(a5)
    73.         bne.s   locret_72E1E
    74.         move.b  -1(a4),d0               ; MJ: reload F3 setting to d0
    75.         move.b  d0,($C00011).l              ; MJ: save F3 setting (should be EX (PSG 4) related)
    76.         andi.b  #%00000011,d0               ; MJ: get only frequency mode bits
    77.         cmpi.b  #%00000011,d0               ; MJ: has it been set to use PSG 3's frequency?
    78.         bne.s   locret_72E1E                ; MJ: if not, branch
    79.         move.b  #%11011111,($C00011).l          ; MJ: mute PSG 3's volume
    80.  
    81. locret_72E1E:
    82.         rts
    >> 14. Find this:

    Code (Text):
    1. SegaPCM:    incbin  sound\segapcm.bin
    2.         even
    And replace with:

    Code (Text):
    1. SegaPCM:    incbin  sound\segapcm.wav,$3A
    2. SegaPCM_End:    even

    Step 04 - Some new files

    Some macro/Sample files to be added and included.

    >> 1. Open up "sonic1.asm", and replace:

    Code (Text):
    1.  
    2. align macro
    3.     cnop 0,\1
    4.     endm
    With this:

    Code (Text):
    1.         include "Equz80.asm"
    2.         include "Macros.asm"
    >> 2. Download this file, and place at the root of the disassembly:

    [​IMG]

    >> 3. Download this SEGA wav file, and place it in the "sound" folder (and delete the old "segapcm.bin" while you're at it):

    [​IMG]

    >> 4. Inside the "Dual PCM" folder, create a new folder and name it "Samples":

    [​IMG]

    >> 5. Download and extract this into that new "Samples" folder:

    Download (32-bit)
    Download (64-bit)

    (For those who want the source for ConvPCM, download here).

    [​IMG]

    >> 6. Open up "sonic1.asm" and go to the very bottom where you'll find:

    Code (Text):
    1. ; end of 'ROM'
    2. EndOfRom:
    3.  
    4.  
    5.         END
    Above this, place the following:

    Code (Text):
    1. ; ===========================================================================
    2. ; ---------------------------------------------------------------------------
    3. ; Sample 68k PCM list
    4. ; ---------------------------------------------------------------------------
    5.  
    6. SampleList:     dc.l    StopSample          ; 80 (THIS IS A REST NOTE, DO NOT EDIT...)
    7.             dc.l    Sonic1Kick          ; 81
    8.             dc.l    Sonic1Snare         ; 82
    9.             dc.l    Sonic1TimpaniLow        ; 83
    10.             dc.l    StopSample          ; 84
    11.             dc.l    StopSample          ; 85
    12.             dc.l    StopSample          ; 86
    13.             dc.l    StopSample          ; 87
    14.             dc.l    Sonic1TimpaniHigh       ; 88
    15.             dc.l    Sonic1TimpaniMid        ; 89
    16.             dc.l    Sonic1TimpaniLow        ; 8A
    17.             dc.l    Sonic1TimpaniLower      ; 8B
    18.  
    19. ; ---------------------------------------------------------------------------
    20. ; Sample z80 pointers
    21. ; ---------------------------------------------------------------------------
    22.  
    23. StopSample:     dcz80   SWF_StopSample
    24. Sonic1Kick:     dcz80   SWF_S1Kick
    25. Sonic1Snare:        dcz80   SWF_S1Snare
    26. Sonic1TimpaniHigh:  dcz80   SWF_S1TimpaniHigh
    27. Sonic1TimpaniMid:   dcz80   SWF_S1TimpaniMid
    28. Sonic1TimpaniLow:   dcz80   SWF_S1TimpaniLow
    29. Sonic1TimpaniLower: dcz80   SWF_S1TimpaniLower
    30.  
    31. ; ---------------------------------------------------------------------------
    32. ; Sample file includes
    33. ; ---------------------------------------------------------------------------
    34.             align   $20,$FF
    35. SWF_StopSample:     dcb.b   $7FFF,$00
    36.             dc.b    $80
    37. ; ---------------------------------------------------------------------------
    38. SWF_S1Kick:     incbin  "Dual PCM\Samples\incswf\Sonic 1 Kick.swf"
    39. SWF_S1Snare:        incbin  "Dual PCM\Samples\incswf\Sonic 1 Snare.swf"
    40. SWF_S1TimpaniHigh:  incbin  "Dual PCM\Samples\incswf\Sonic 1 Timpani High.swf"
    41. SWF_S1TimpaniMid:   incbin  "Dual PCM\Samples\incswf\Sonic 1 Timpani Mid.swf"
    42. SWF_S1TimpaniLow:   incbin  "Dual PCM\Samples\incswf\Sonic 1 Timpani Low.swf"
    43. SWF_S1TimpaniLower: incbin  "Dual PCM\Samples\incswf\Sonic 1 Timpani Lower.swf"
    44.  
    45. ; ===========================================================================

    Step 05 - Adjustments

    The new driver will make the current SMPS music files incompatible, and we need to make the new samples compatible also.

    >> 1. Drag and drop all of the "music" files from the "sound" folder, onto a program inside the "_Assembly Tools" folder named "AddDAC.exe", like so:

    [​IMG]

    YOU ONLY NEED TO DO THIS ONCE, DO NOT DO IT MORE THAN ONCE.

    This will give all of the music files an extra PCM channel, and point it to an F2 stop flag, this will simply make it compatible for the new driver, and won't actually change the song's result.

    >> 2. Inside the "Dual PCM\Samples" folder, you will need to drag and drop all of the ".wav" files onto that program named "ConvPCM.exe", like so:

    [​IMG]

    Let the program do its thing, and press enter when it's finished, this will create a folder named "incswf", it'll convert the ".wav" files into the correct format and rate, and save the converted files inside "incswf" as ".swf" files, and THOSE are the files that are included into the source, the program will NEVER tamper with the original ".wav" files, so you may keep the original files in their former format/quality without having to worry.

    Step 06 - DMA Stops

    There are a series of Z80 stops when DMA transfers are due to occur, we need to replace those with Z80 DMA requests.

    >> 1. Replace all of this:

    Code (Text):
    1. loc_BBA:
    2.         move.w  #1,($FFFFF644).w
    3.         move.w  #$100,($A11100).l
    4.  
    5. loc_BC8:
    6.         btst    #0,($A11100).l
    7.         bne.s   loc_BC8
    8.         tst.b   ($FFFFF64E).w
    9.         bne.s   loc_BFE
    10.         lea ($C00004).l,a5
    11.         move.l  #$94009340,(a5)
    12.         move.l  #$96FD9580,(a5)
    13.         move.w  #$977F,(a5)
    14.         move.w  #$C000,(a5)
    15.         move.w  #$80,($FFFFF640).w
    16.         move.w  ($FFFFF640).w,(a5)
    17.         bra.s   loc_C22
    18. ; ===========================================================================
    19.  
    20. loc_BFE:                ; XREF: loc_BC8
    21.         lea ($C00004).l,a5
    22.         move.l  #$94009340,(a5)
    23.         move.l  #$96FD9540,(a5)
    24.         move.w  #$977F,(a5)
    25.         move.w  #$C000,(a5)
    26.         move.w  #$80,($FFFFF640).w
    27.         move.w  ($FFFFF640).w,(a5)
    28.  
    29. loc_C22:                ; XREF: loc_BC8
    30.         move.w  ($FFFFF624).w,(a5)
    31.         move.w  #0,($A11100).l
    32.         bra.w   loc_B5E
    33. ; ===========================================================================
    34.  
    35. loc_C32:                ; XREF: off_B6E
    36.         bsr.w   sub_106E
    37.  
    38. loc_C36:                ; XREF: off_B6E
    39.         tst.w   ($FFFFF614).w
    40.         beq.w   locret_C42
    41.         subq.w  #1,($FFFFF614).w
    42.  
    43. locret_C42:
    44.         rts
    45. ; ===========================================================================
    46.  
    47. loc_C44:                ; XREF: off_B6E
    48.         bsr.w   sub_106E
    49.         bsr.w   sub_6886
    50.         bsr.w   sub_1642
    51.         tst.w   ($FFFFF614).w
    52.         beq.w   locret_C5C
    53.         subq.w  #1,($FFFFF614).w
    54.  
    55. locret_C5C:
    56.         rts
    57. ; ===========================================================================
    58.  
    59. loc_C5E:                ; XREF: off_B6E
    60.         bsr.w   sub_106E
    61.         rts
    62. ; ===========================================================================
    63.  
    64. loc_C64:                ; XREF: off_B6E
    65.         cmpi.b  #$10,($FFFFF600).w ; is game mode = $10 (special stage) ?
    66.         beq.w   loc_DA6     ; if yes, branch
    67.  
    68. loc_C6E:                ; XREF: off_B6E
    69.         move.w  #$100,($A11100).l ; stop the Z80
    70.  
    71. loc_C76:
    72.         btst    #0,($A11100).l  ; has Z80 stopped?
    73.         bne.s   loc_C76     ; if not, branch
    74.         bsr.w   ReadJoypads
    75.         tst.b   ($FFFFF64E).w
    76.         bne.s   loc_CB0
    77.         lea ($C00004).l,a5
    78.         move.l  #$94009340,(a5)
    79.         move.l  #$96FD9580,(a5)
    80.         move.w  #$977F,(a5)
    81.         move.w  #$C000,(a5)
    82.         move.w  #$80,($FFFFF640).w
    83.         move.w  ($FFFFF640).w,(a5)
    84.         bra.s   loc_CD4
    85. ; ===========================================================================
    86.  
    87. loc_CB0:                ; XREF: loc_C76
    88.         lea ($C00004).l,a5
    89.         move.l  #$94009340,(a5)
    90.         move.l  #$96FD9540,(a5)
    91.         move.w  #$977F,(a5)
    92.         move.w  #$C000,(a5)
    93.         move.w  #$80,($FFFFF640).w
    94.         move.w  ($FFFFF640).w,(a5)
    95.  
    96. loc_CD4:                ; XREF: loc_C76
    97.         move.w  ($FFFFF624).w,(a5)
    98.         lea ($C00004).l,a5
    99.         move.l  #$940193C0,(a5)
    100.         move.l  #$96E69500,(a5)
    101.         move.w  #$977F,(a5)
    102.         move.w  #$7C00,(a5)
    103.         move.w  #$83,($FFFFF640).w
    104.         move.w  ($FFFFF640).w,(a5)
    105.         lea ($C00004).l,a5
    106.         move.l  #$94019340,(a5)
    107.         move.l  #$96FC9500,(a5)
    108.         move.w  #$977F,(a5)
    109.         move.w  #$7800,(a5)
    110.         move.w  #$83,($FFFFF640).w
    111.         move.w  ($FFFFF640).w,(a5)
    112.         tst.b   ($FFFFF767).w
    113.         beq.s   loc_D50
    114.         lea ($C00004).l,a5
    115.         move.l  #$94019370,(a5)
    116.         move.l  #$96E49500,(a5)
    117.         move.w  #$977F,(a5)
    118.         move.w  #$7000,(a5)
    119.         move.w  #$83,($FFFFF640).w
    120.         move.w  ($FFFFF640).w,(a5)
    121.         move.b  #0,($FFFFF767).w
    122.  
    123. loc_D50:
    124.         move.w  #0,($A11100).l
    125.         movem.l ($FFFFF700).w,d0-d7
    126.         movem.l d0-d7,($FFFFFF10).w
    127.         movem.l ($FFFFF754).w,d0-d1
    128.         movem.l d0-d1,($FFFFFF30).w
    129.         cmpi.b  #$60,($FFFFF625).w
    130.         bcc.s   Demo_Time
    131.         move.b  #1,($FFFFF64F).w
    132.         addq.l  #4,sp
    133.         bra.w   loc_B64
    134.  
    135. ; ---------------------------------------------------------------------------
    136. ; Subroutine to run a demo for an amount of time
    137. ; ---------------------------------------------------------------------------
    138.  
    139. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    140.  
    141.  
    142. Demo_Time:              ; XREF: loc_D50; PalToCRAM
    143.         bsr.w   LoadTilesAsYouMove
    144.         jsr AniArt_Load
    145.         jsr HudUpdate
    146.         bsr.w   sub_165E
    147.         tst.w   ($FFFFF614).w   ; is there time left on the demo?
    148.         beq.w   Demo_TimeEnd    ; if not, branch
    149.         subq.w  #1,($FFFFF614).w ; subtract 1 from time left
    150.  
    151. Demo_TimeEnd:
    152.         rts
    153. ; End of function Demo_Time
    154.  
    155. ; ===========================================================================
    156.  
    157. loc_DA6:                ; XREF: off_B6E
    158.         move.w  #$100,($A11100).l ; stop the Z80
    159.  
    160. loc_DAE:
    161.         btst    #0,($A11100).l  ; has Z80 stopped?
    162.         bne.s   loc_DAE     ; if not, branch
    163.         bsr.w   ReadJoypads
    164.         lea ($C00004).l,a5
    165.         move.l  #$94009340,(a5)
    166.         move.l  #$96FD9580,(a5)
    167.         move.w  #$977F,(a5)
    168.         move.w  #$C000,(a5)
    169.         move.w  #$80,($FFFFF640).w
    170.         move.w  ($FFFFF640).w,(a5)
    171.         lea ($C00004).l,a5
    172.         move.l  #$94019340,(a5)
    173.         move.l  #$96FC9500,(a5)
    174.         move.w  #$977F,(a5)
    175.         move.w  #$7800,(a5)
    176.         move.w  #$83,($FFFFF640).w
    177.         move.w  ($FFFFF640).w,(a5)
    178.         lea ($C00004).l,a5
    179.         move.l  #$940193C0,(a5)
    180.         move.l  #$96E69500,(a5)
    181.         move.w  #$977F,(a5)
    182.         move.w  #$7C00,(a5)
    183.         move.w  #$83,($FFFFF640).w
    184.         move.w  ($FFFFF640).w,(a5)
    185.         move.w  #0,($A11100).l
    186.         bsr.w   PalCycle_SS
    187.         tst.b   ($FFFFF767).w
    188.         beq.s   loc_E64
    189.         lea ($C00004).l,a5
    190.         move.l  #$94019370,(a5)
    191.         move.l  #$96E49500,(a5)
    192.         move.w  #$977F,(a5)
    193.         move.w  #$7000,(a5)
    194.         move.w  #$83,($FFFFF640).w
    195.         move.w  ($FFFFF640).w,(a5)
    196.         move.b  #0,($FFFFF767).w
    197.  
    198. loc_E64:
    199.         tst.w   ($FFFFF614).w
    200.         beq.w   locret_E70
    201.         subq.w  #1,($FFFFF614).w
    202.  
    203. locret_E70:
    204.         rts
    205. ; ===========================================================================
    206.  
    207. loc_E72:                ; XREF: off_B6E
    208.         move.w  #$100,($A11100).l ; stop the Z80
    209.  
    210. loc_E7A:
    211.         btst    #0,($A11100).l  ; has Z80 stopped?
    212.         bne.s   loc_E7A     ; if not, branch
    213.         bsr.w   ReadJoypads
    214.         tst.b   ($FFFFF64E).w
    215.         bne.s   loc_EB4
    216.         lea ($C00004).l,a5
    217.         move.l  #$94009340,(a5)
    218.         move.l  #$96FD9580,(a5)
    219.         move.w  #$977F,(a5)
    220.         move.w  #$C000,(a5)
    221.         move.w  #$80,($FFFFF640).w
    222.         move.w  ($FFFFF640).w,(a5)
    223.         bra.s   loc_ED8
    224. ; ===========================================================================
    225.  
    226. loc_EB4:                ; XREF: loc_E7A
    227.         lea ($C00004).l,a5
    228.         move.l  #$94009340,(a5)
    229.         move.l  #$96FD9540,(a5)
    230.         move.w  #$977F,(a5)
    231.         move.w  #$C000,(a5)
    232.         move.w  #$80,($FFFFF640).w
    233.         move.w  ($FFFFF640).w,(a5)
    234.  
    235. loc_ED8:                ; XREF: loc_E7A
    236.         move.w  ($FFFFF624).w,(a5)
    237.         lea ($C00004).l,a5
    238.         move.l  #$940193C0,(a5)
    239.         move.l  #$96E69500,(a5)
    240.  
    241. loc_EEE:
    242.         move.w  #$977F,(a5)
    243.         move.w  #$7C00,(a5)
    244.         move.w  #$83,($FFFFF640).w
    245.         move.w  ($FFFFF640).w,(a5)
    246.         lea ($C00004).l,a5
    247.         move.l  #$94019340,(a5)
    248.         move.l  #$96FC9500,(a5)
    249.         move.w  #$977F,(a5)
    250.         move.w  #$7800,(a5)
    251.         move.w  #$83,($FFFFF640).w
    252.         move.w  ($FFFFF640).w,(a5)
    253.         tst.b   ($FFFFF767).w
    254.         beq.s   loc_F54
    255.         lea ($C00004).l,a5
    256.         move.l  #$94019370,(a5)
    257.         move.l  #$96E49500,(a5)
    258.         move.w  #$977F,(a5)
    259.         move.w  #$7000,(a5)
    260.         move.w  #$83,($FFFFF640).w
    261.         move.w  ($FFFFF640).w,(a5)
    262.         move.b  #0,($FFFFF767).w
    263.  
    264. loc_F54:
    265.         move.w  #0,($A11100).l  ; start the Z80
    266.         movem.l ($FFFFF700).w,d0-d7
    267.         movem.l d0-d7,($FFFFFF10).w
    268.         movem.l ($FFFFF754).w,d0-d1
    269.         movem.l d0-d1,($FFFFFF30).w
    270.         bsr.w   LoadTilesAsYouMove
    271.         jsr AniArt_Load
    272.         jsr HudUpdate
    273.         bsr.w   sub_1642
    274.         rts
    275. ; ===========================================================================
    276.  
    277. loc_F8A:                ; XREF: off_B6E
    278.         bsr.w   sub_106E
    279.         addq.b  #1,($FFFFF628).w
    280.         move.b  #$E,($FFFFF62A).w
    281.         rts
    282. ; ===========================================================================
    283.  
    284. loc_F9A:                ; XREF: off_B6E
    285.         bsr.w   sub_106E
    286.         move.w  ($FFFFF624).w,(a5)
    287.         bra.w   sub_1642
    288. ; ===========================================================================
    289.  
    290. loc_FA6:                ; XREF: off_B6E
    291.         move.w  #$100,($A11100).l ; stop the Z80
    292.  
    293. loc_FAE:
    294.         btst    #0,($A11100).l  ; has Z80 stopped?
    295.         bne.s   loc_FAE     ; if not, branch
    296.         bsr.w   ReadJoypads
    297.         lea ($C00004).l,a5
    298.         move.l  #$94009340,(a5)
    299.         move.l  #$96FD9580,(a5)
    300.         move.w  #$977F,(a5)
    301.         move.w  #$C000,(a5)
    302.         move.w  #$80,($FFFFF640).w
    303.         move.w  ($FFFFF640).w,(a5)
    304.         lea ($C00004).l,a5
    305.         move.l  #$94019340,(a5)
    306.         move.l  #$96FC9500,(a5)
    307.         move.w  #$977F,(a5)
    308.         move.w  #$7800,(a5)
    309.         move.w  #$83,($FFFFF640).w
    310.         move.w  ($FFFFF640).w,(a5)
    311.         lea ($C00004).l,a5
    312.         move.l  #$940193C0,(a5)
    313.         move.l  #$96E69500,(a5)
    314.         move.w  #$977F,(a5)
    315.         move.w  #$7C00,(a5)
    316.         move.w  #$83,($FFFFF640).w
    317.         move.w  ($FFFFF640).w,(a5)
    318.         move.w  #0,($A11100).l  ; start the Z80
    319.         tst.b   ($FFFFF767).w
    320.         beq.s   loc_1060
    321.         lea ($C00004).l,a5
    322.         move.l  #$94019370,(a5)
    323.         move.l  #$96E49500,(a5)
    324.         move.w  #$977F,(a5)
    325.         move.w  #$7000,(a5)
    326.         move.w  #$83,($FFFFF640).w
    327.         move.w  ($FFFFF640).w,(a5)
    328.         move.b  #0,($FFFFF767).w
    329.  
    330. loc_1060:
    331.         tst.w   ($FFFFF614).w
    332.         beq.w   locret_106C
    333.         subq.w  #1,($FFFFF614).w
    334.  
    335. locret_106C:
    336.         rts
    337.  
    338. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    339.  
    340.  
    341. sub_106E:               ; XREF: loc_C32; et al
    342.         move.w  #$100,($A11100).l ; stop the Z80
    343.  
    344. loc_1076:
    345.         btst    #0,($A11100).l  ; has Z80 stopped?
    346.         bne.s   loc_1076    ; if not, branch
    347.         bsr.w   ReadJoypads
    348.         tst.b   ($FFFFF64E).w
    349.         bne.s   loc_10B0
    350.         lea ($C00004).l,a5
    351.         move.l  #$94009340,(a5)
    352.         move.l  #$96FD9580,(a5)
    353.         move.w  #$977F,(a5)
    354.         move.w  #$C000,(a5)
    355.         move.w  #$80,($FFFFF640).w
    356.         move.w  ($FFFFF640).w,(a5)
    357.         bra.s   loc_10D4
    358. ; ===========================================================================
    359.  
    360. loc_10B0:               ; XREF: sub_106E
    361.         lea ($C00004).l,a5
    362.         move.l  #$94009340,(a5)
    363.         move.l  #$96FD9540,(a5)
    364.         move.w  #$977F,(a5)
    365.         move.w  #$C000,(a5)
    366.         move.w  #$80,($FFFFF640).w
    367.         move.w  ($FFFFF640).w,(a5)
    368.  
    369. loc_10D4:               ; XREF: sub_106E
    370.         lea ($C00004).l,a5
    371.         move.l  #$94019340,(a5)
    372.         move.l  #$96FC9500,(a5)
    373.         move.w  #$977F,(a5)
    374.         move.w  #$7800,(a5)
    375.         move.w  #$83,($FFFFF640).w
    376.         move.w  ($FFFFF640).w,(a5)
    377.         lea ($C00004).l,a5
    378.         move.l  #$940193C0,(a5)
    379.         move.l  #$96E69500,(a5)
    380.         move.w  #$977F,(a5)
    381.         move.w  #$7C00,(a5)
    382.         move.w  #$83,($FFFFF640).w
    383.         move.w  ($FFFFF640).w,(a5)
    384.         move.w  #0,($A11100).l  ; start the Z80
    385.         rts
    386. ; End of function sub_106E
    With this:

    Code (Text):
    1. loc_BBA:
    2.         move.w  #1,($FFFFF644).w
    3.     Z80DMA_ON
    4.         tst.b   ($FFFFF64E).w
    5.         bne.s   loc_BFE
    6.         lea ($C00004).l,a5
    7.         move.l  #$94009340,(a5)
    8.         move.l  #$96FD9580,(a5)
    9.         move.w  #$977F,(a5)
    10.         move.w  #$C000,(a5)
    11.         move.w  #$80,($FFFFF640).w
    12.         move.w  ($FFFFF640).w,(a5)
    13.         bra.s   loc_C22
    14. ; ===========================================================================
    15.  
    16. loc_BFE:                ; XREF: loc_BC8
    17.         lea ($C00004).l,a5
    18.         move.l  #$94009340,(a5)
    19.         move.l  #$96FD9540,(a5)
    20.         move.w  #$977F,(a5)
    21.         move.w  #$C000,(a5)
    22.         move.w  #$80,($FFFFF640).w
    23.         move.w  ($FFFFF640).w,(a5)
    24.  
    25. loc_C22:                ; XREF: loc_BC8
    26.         move.w  ($FFFFF624).w,(a5)
    27.     Z80DMA_OFF
    28.         bra.w   loc_B5E
    29. ; ===========================================================================
    30.  
    31. loc_C32:                ; XREF: off_B6E
    32.         bsr.w   sub_106E
    33.  
    34. loc_C36:                ; XREF: off_B6E
    35.         tst.w   ($FFFFF614).w
    36.         beq.w   locret_C42
    37.         subq.w  #1,($FFFFF614).w
    38.  
    39. locret_C42:
    40.         rts
    41. ; ===========================================================================
    42.  
    43. loc_C44:                ; XREF: off_B6E
    44.         bsr.w   sub_106E
    45.         bsr.w   sub_6886
    46.         bsr.w   sub_1642
    47.         tst.w   ($FFFFF614).w
    48.         beq.w   locret_C5C
    49.         subq.w  #1,($FFFFF614).w
    50.  
    51. locret_C5C:
    52.         rts
    53. ; ===========================================================================
    54.  
    55. loc_C5E:                ; XREF: off_B6E
    56.         bsr.w   sub_106E
    57.         rts
    58.  
    59. Return:
    60.         bsr.w   ReadJoypads
    61.         rts
    62. ; ===========================================================================
    63.  
    64. loc_C64:                ; XREF: off_B6E
    65.         cmpi.b  #$10,($FFFFF600).w ; is game mode = $10 (special stage) ?
    66.         beq.w   loc_DA6     ; if yes, branch
    67.  
    68. loc_C6E:                ; XREF: off_B6E
    69.     Z80DMA_ON
    70.         bsr.w   ReadJoypads
    71.         tst.b   ($FFFFF64E).w
    72.         bne.s   loc_CB0
    73.         lea ($C00004).l,a5
    74.         move.l  #$94009340,(a5)
    75.         move.l  #$96FD9580,(a5)
    76.         move.w  #$977F,(a5)
    77.         move.w  #$C000,(a5)
    78.         move.w  #$80,($FFFFF640).w
    79.         move.w  ($FFFFF640).w,(a5)
    80.         bra.s   loc_CD4
    81. ; ===========================================================================
    82.  
    83. loc_CB0:                ; XREF: loc_C76
    84.         lea ($C00004).l,a5
    85.         move.l  #$94009340,(a5)
    86.         move.l  #$96FD9540,(a5)
    87.         move.w  #$977F,(a5)
    88.         move.w  #$C000,(a5)
    89.         move.w  #$80,($FFFFF640).w
    90.         move.w  ($FFFFF640).w,(a5)
    91.  
    92. loc_CD4:                ; XREF: loc_C76
    93.         move.w  ($FFFFF624).w,(a5)
    94.         lea ($C00004).l,a5
    95.         move.l  #$940193C0,(a5)
    96.         move.l  #$96E69500,(a5)
    97.         move.w  #$977F,(a5)
    98.         move.w  #$7C00,(a5)
    99.         move.w  #$83,($FFFFF640).w
    100.         move.w  ($FFFFF640).w,(a5)
    101.         lea ($C00004).l,a5
    102.         move.l  #$94019340,(a5)
    103.         move.l  #$96FC9500,(a5)
    104.         move.w  #$977F,(a5)
    105.         move.w  #$7800,(a5)
    106.         move.w  #$83,($FFFFF640).w
    107.         move.w  ($FFFFF640).w,(a5)
    108.         tst.b   ($FFFFF767).w
    109.         beq.s   loc_D50
    110.         lea ($C00004).l,a5
    111.         move.l  #$94019370,(a5)
    112.         move.l  #$96E49500,(a5)
    113.         move.w  #$977F,(a5)
    114.         move.w  #$7000,(a5)
    115.         move.w  #$83,($FFFFF640).w
    116.         move.w  ($FFFFF640).w,(a5)
    117.         move.b  #0,($FFFFF767).w
    118.  
    119. loc_D50:
    120.     Z80DMA_OFF
    121.         movem.l ($FFFFF700).w,d0-d7
    122.         movem.l d0-d7,($FFFFFF10).w
    123.         movem.l ($FFFFF754).w,d0-d1
    124.         movem.l d0-d1,($FFFFFF30).w
    125.         cmpi.b  #$60,($FFFFF625).w
    126.         bcc.s   Demo_Time
    127.         move.b  #1,($FFFFF64F).w
    128.         addq.l  #4,sp
    129.         bra.w   loc_B64
    130.  
    131. ; ---------------------------------------------------------------------------
    132. ; Subroutine to run a demo for an amount of time
    133. ; ---------------------------------------------------------------------------
    134.  
    135. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    136.  
    137.  
    138. Demo_Time:              ; XREF: loc_D50; PalToCRAM
    139.         bsr.w   LoadTilesAsYouMove
    140.         jsr AniArt_Load
    141.         jsr HudUpdate
    142.         bsr.w   sub_165E
    143.         tst.w   ($FFFFF614).w   ; is there time left on the demo?
    144.         beq.w   Demo_TimeEnd    ; if not, branch
    145.         subq.w  #1,($FFFFF614).w ; subtract 1 from time left
    146.  
    147. Demo_TimeEnd:
    148.         rts
    149. ; End of function Demo_Time
    150.  
    151. ; ===========================================================================
    152.  
    153. loc_DA6:                ; XREF: off_B6E
    154.         bsr.w   ReadJoypads
    155.     Z80DMA_ON
    156.         lea ($C00004).l,a5
    157.         move.l  #$94009340,(a5)
    158.         move.l  #$96FD9580,(a5)
    159.         move.w  #$977F,(a5)
    160.         move.w  #$C000,(a5)
    161.         move.w  #$80,($FFFFF640).w
    162.         move.w  ($FFFFF640).w,(a5)
    163.         lea ($C00004).l,a5
    164.         move.l  #$94019340,(a5)
    165.         move.l  #$96FC9500,(a5)
    166.         move.w  #$977F,(a5)
    167.         move.w  #$7800,(a5)
    168.         move.w  #$83,($FFFFF640).w
    169.         move.w  ($FFFFF640).w,(a5)
    170.         lea ($C00004).l,a5
    171.         move.l  #$940193C0,(a5)
    172.         move.l  #$96E69500,(a5)
    173.         move.w  #$977F,(a5)
    174.         move.w  #$7C00,(a5)
    175.         move.w  #$83,($FFFFF640).w
    176.         move.w  ($FFFFF640).w,(a5)
    177.         bsr.w   PalCycle_SS
    178.         tst.b   ($FFFFF767).w
    179.         beq.s   loc_E64
    180.         lea ($C00004).l,a5
    181.         move.l  #$94019370,(a5)
    182.         move.l  #$96E49500,(a5)
    183.         move.w  #$977F,(a5)
    184.         move.w  #$7000,(a5)
    185.         move.w  #$83,($FFFFF640).w
    186.         move.w  ($FFFFF640).w,(a5)
    187.         move.b  #0,($FFFFF767).w
    188.  
    189. loc_E64:
    190.     Z80DMA_OFF
    191.         tst.w   ($FFFFF614).w
    192.         beq.w   locret_E70
    193.         subq.w  #1,($FFFFF614).w
    194.  
    195. locret_E70:
    196.         rts
    197. ; ===========================================================================
    198.  
    199. loc_E72:                ; XREF: off_B6E
    200.         bsr.w   ReadJoypads
    201.     Z80DMA_ON
    202.         tst.b   ($FFFFF64E).w
    203.         bne.s   loc_EB4
    204.         lea ($C00004).l,a5
    205.         move.l  #$94009340,(a5)
    206.         move.l  #$96FD9580,(a5)
    207.         move.w  #$977F,(a5)
    208.         move.w  #$C000,(a5)
    209.         move.w  #$80,($FFFFF640).w
    210.         move.w  ($FFFFF640).w,(a5)
    211.         bra.s   loc_ED8
    212. ; ===========================================================================
    213.  
    214. loc_EB4:                ; XREF: loc_E7A
    215.         lea ($C00004).l,a5
    216.         move.l  #$94009340,(a5)
    217.         move.l  #$96FD9540,(a5)
    218.         move.w  #$977F,(a5)
    219.         move.w  #$C000,(a5)
    220.         move.w  #$80,($FFFFF640).w
    221.         move.w  ($FFFFF640).w,(a5)
    222.  
    223. loc_ED8:                ; XREF: loc_E7A
    224.         move.w  ($FFFFF624).w,(a5)
    225.         lea ($C00004).l,a5
    226.         move.l  #$940193C0,(a5)
    227.         move.l  #$96E69500,(a5)
    228.  
    229. loc_EEE:
    230.         move.w  #$977F,(a5)
    231.         move.w  #$7C00,(a5)
    232.         move.w  #$83,($FFFFF640).w
    233.         move.w  ($FFFFF640).w,(a5)
    234.         lea ($C00004).l,a5
    235.         move.l  #$94019340,(a5)
    236.         move.l  #$96FC9500,(a5)
    237.         move.w  #$977F,(a5)
    238.         move.w  #$7800,(a5)
    239.         move.w  #$83,($FFFFF640).w
    240.         move.w  ($FFFFF640).w,(a5)
    241.         tst.b   ($FFFFF767).w
    242.         beq.s   loc_F54
    243.         lea ($C00004).l,a5
    244.         move.l  #$94019370,(a5)
    245.         move.l  #$96E49500,(a5)
    246.         move.w  #$977F,(a5)
    247.         move.w  #$7000,(a5)
    248.         move.w  #$83,($FFFFF640).w
    249.         move.w  ($FFFFF640).w,(a5)
    250.         move.b  #0,($FFFFF767).w
    251.  
    252. loc_F54:
    253.     Z80DMA_OFF
    254.         movem.l ($FFFFF700).w,d0-d7
    255.         movem.l d0-d7,($FFFFFF10).w
    256.         movem.l ($FFFFF754).w,d0-d1
    257.         movem.l d0-d1,($FFFFFF30).w
    258.         bsr.w   LoadTilesAsYouMove
    259.         jsr AniArt_Load
    260.         jsr HudUpdate
    261.         bsr.w   sub_1642
    262.         rts
    263. ; ===========================================================================
    264.  
    265. loc_F8A:                ; XREF: off_B6E
    266.         bsr.w   sub_106E
    267.         addq.b  #1,($FFFFF628).w
    268.         move.b  #$E,($FFFFF62A).w
    269.         rts
    270. ; ===========================================================================
    271.  
    272. loc_F9A:                ; XREF: off_B6E
    273.         bsr.w   sub_106E
    274.         move.w  ($FFFFF624).w,(a5)
    275.         bra.w   sub_1642
    276. ; ===========================================================================
    277.  
    278. loc_FA6:                ; XREF: off_B6E
    279.         bsr.w   ReadJoypads
    280.     Z80DMA_ON
    281.         lea ($C00004).l,a5
    282.         move.l  #$94009340,(a5)
    283.         move.l  #$96FD9580,(a5)
    284.         move.w  #$977F,(a5)
    285.         move.w  #$C000,(a5)
    286.         move.w  #$80,($FFFFF640).w
    287.         move.w  ($FFFFF640).w,(a5)
    288.         lea ($C00004).l,a5
    289.         move.l  #$94019340,(a5)
    290.         move.l  #$96FC9500,(a5)
    291.         move.w  #$977F,(a5)
    292.         move.w  #$7800,(a5)
    293.         move.w  #$83,($FFFFF640).w
    294.         move.w  ($FFFFF640).w,(a5)
    295.         lea ($C00004).l,a5
    296.         move.l  #$940193C0,(a5)
    297.         move.l  #$96E69500,(a5)
    298.         move.w  #$977F,(a5)
    299.         move.w  #$7C00,(a5)
    300.         move.w  #$83,($FFFFF640).w
    301.         move.w  ($FFFFF640).w,(a5)
    302.         tst.b   ($FFFFF767).w
    303.         beq.s   loc_1060
    304.         lea ($C00004).l,a5
    305.         move.l  #$94019370,(a5)
    306.         move.l  #$96E49500,(a5)
    307.         move.w  #$977F,(a5)
    308.         move.w  #$7000,(a5)
    309.         move.w  #$83,($FFFFF640).w
    310.         move.w  ($FFFFF640).w,(a5)
    311.         move.b  #0,($FFFFF767).w
    312.  
    313. loc_1060:
    314.     Z80DMA_OFF
    315.         tst.w   ($FFFFF614).w
    316.         beq.w   locret_106C
    317.         subq.w  #1,($FFFFF614).w
    318.  
    319. locret_106C:
    320.         rts
    321.  
    322. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    323.  
    324.  
    325. sub_106E:               ; XREF: loc_C32; et al
    326.         bsr.w   ReadJoypads
    327.     Z80DMA_ON
    328.         tst.b   ($FFFFF64E).w
    329.         bne.s   loc_10B0
    330.         lea ($C00004).l,a5
    331.         move.l  #$94009340,(a5)
    332.         move.l  #$96FD9580,(a5)
    333.         move.w  #$977F,(a5)
    334.         move.w  #$C000,(a5)
    335.         move.w  #$80,($FFFFF640).w
    336.         move.w  ($FFFFF640).w,(a5)
    337.  
    338. PAL1_LOAD:
    339.         bra.s   loc_10D4
    340. ; ===========================================================================
    341.  
    342. loc_10B0:
    343.         lea ($C00004).l,a5
    344.         move.l  #$94009340,(a5)
    345.         move.l  #$96FD9540,(a5)
    346.         move.w  #$977F,(a5)
    347.         move.w  #$C000,(a5)
    348.         move.w  #$80,($FFFFF640).w
    349.         move.w  ($FFFFF640).w,(a5)
    350. loc_10D4:
    351.         lea ($C00004).l,a5
    352.         move.l  #$94019340,(a5)
    353.         move.l  #$96FC9500,(a5)
    354.         move.w  #$977F,(a5)
    355.         move.w  #$7800,(a5)
    356.         move.w  #$83,($FFFFF640).w
    357.         move.w  ($FFFFF640).w,(a5)
    358.         lea ($C00004).l,a5
    359.         move.l  #$940193C0,(a5)
    360.         move.l  #$96E69500,(a5)
    361.         move.w  #$977F,(a5)
    362.         move.w  #$7C00,(a5)
    363.         move.w  #$83,($FFFFF640).w
    364.         move.w  ($FFFFF640).w,(a5)
    365.     Z80DMA_OFF
    366.         rts
    367. ; End of function sub_106E
    Basically, all we've done is replaced all of these instances:

    Code (Text):
    1.         move.w  #$100,($A11100).l ; stop the Z80
    2.  
    3. location:
    4.         btst    #0,($A11100).l  ; has Z80 stopped?
    5.         bne.s   location    ; if not, branch
    With these:

    Code (Text):
    1.     Z80DMA_ON
    And all of these instances:

    Code (Text):
    1.         move.w  #0,($A11100).l  ; start the Z80
    With these:

    Code (Text):
    1.     Z80DMA_OFF
    So now instead of stopping the Z80, it'll just send it a note saying that there's a DMA transfer to occur.

    Finished

    Your disassembly is now setup with the new Dual PCM driver, here is a download link to a Sonic 1 disassembly with the changes already applied.

    Download (32-bit)
    Download (64-bit)

    Adding in new samples

    Alright, so now that everything's pretty much setup, you'll no doubt want to put new samples in, or, replace the old ones, or whatever. Here, we look at putting in the sample, converting it, and including it properly.

    Step 01 - Adjusting the volume of your sample

    This driver fuses two samples together by "addition" before flushing out the final result, the problem is, when you add two samples together, you are in danger of overflowing the 8-bit limit. Getting Dual PCM to cap the limit if it overflows would take extra processing time, and this would cause the sample rate to drop really low.

    So, instead, the tool "ConvPCM" will automatically convert the sample to 7-bit, this ensures that the samples (when added/fused together) don't overflow, this creates a problem though, 7-bit samples playing in the lower of 8-bit will sound very quiet and low volume, there is no avoiding this. What I would advise you to do, is to raise the volume of your sample by twice as much before putting it into the game.

    Now you might say "won't this cause the sample to overflow", quite possibly, however, there is a phenomina known as the "Loudness Wars", long story short, sharp sounds (such as drums or waves that jitter very eratically) can be overflown to a degree without any notice-able damage to the quality. Because they're so sharp, the resulting overflow is also sharp, therefore there appears to be no difference in quality. You can use this to your advantage, many of your samples you will be able to get away with multiplying the volume to 200% (an extra 100%), this will help the volume of the sample sound normal in-game. There are plenty of tools out there you can use to edit the sample's volume (Audacity for example).

    The tool doesn't adjust the volume twice as loud to compensate for you, the reason is that you might want the sample a specific volume (that, and not all samples sound great at 200%, some may just need 150%), the Sonic 1 samples provided above have their volumes already raised to 200%, and if you listen, you'll find barely any difference in quality (in fact, it'll be higher quality because of the driver, which is irrelevant to the conversion anyway...).

    Step 02 - Putting your sample file in

    Put the ".wav" or ".bin" file Inside the "Dual PCM\Samples" folder, for example, we'll have a sample called "Scratch.wav" just as an example:

    [​IMG]

    If you open up "ConvPCM.txt" you'll find this:

    Code (Text):
    1. Sample Rate:    20500
    2. Interpolation:  TRUE
    It is recommended that you keep the "Sample Rate" at 20500, this is just for any changes to the driver that'll cause a sample rate change, what might be of interest to you is the "Interpolation" setting, I've had it set to "TRUE" by default, this simply smooths out the samples when they change from say... 44,100Hz to 20,500Hz, this will make all sharp sounds that might sound horrible at 20,500Hz, soften up. If you do not like the result and want all of your samples to remain sharp, change this to "FALSE" (this will effect any samples you convert).

    Now, all that's left, is to drag and drop "Scratch.wav" onto "ConvPCM.exe":

    [​IMG]

    A "Scratch.swf" file shall now exist in the "incswf" folder, and we can now include it into the game. Open up "sonic1.asm" and go down to here:

    Code (Text):
    1. ; ---------------------------------------------------------------------------
    2. ; Sample file includes
    3. ; ---------------------------------------------------------------------------
    4.             align   $20,$FF
    5. SWF_StopSample:     dcb.b   $7FFF,$00
    6.             dc.b    $80
    7. ; ---------------------------------------------------------------------------
    8. SWF_S1Kick:     incbin  "Dual PCM\Samples\incswf\Sonic 1 Kick.swf"
    9. SWF_S1Snare:        incbin  "Dual PCM\Samples\incswf\Sonic 1 Snare.swf"
    10. SWF_S1TimpaniHigh:  incbin  "Dual PCM\Samples\incswf\Sonic 1 Timpani High.swf"
    11. SWF_S1TimpaniMid:   incbin  "Dual PCM\Samples\incswf\Sonic 1 Timpani Mid.swf"
    12. SWF_S1TimpaniLow:   incbin  "Dual PCM\Samples\incswf\Sonic 1 Timpani Low.swf"
    13. SWF_S1TimpaniLower: incbin  "Dual PCM\Samples\incswf\Sonic 1 Timpani Lower.swf"
    You can now insert your new incbin for "Scratch.swf" on the end:

    Code (Text):
    1. SWF_Scratch:        incbin  "Dual PCM\Samples\incswf\Scratch.swf"
    Next thing to do, is to create a Z80 pointer for it here:

    Code (Text):
    1. ; ---------------------------------------------------------------------------
    2. ; Sample z80 pointers
    3. ; ---------------------------------------------------------------------------
    4.  
    5. StopSample:     dcz80   SWF_StopSample
    6. Sonic1Kick:     dcz80   SWF_S1Kick
    7. Sonic1Snare:        dcz80   SWF_S1Snare
    8. Sonic1TimpaniHigh:  dcz80   SWF_S1TimpaniHigh
    9. Sonic1TimpaniMid:   dcz80   SWF_S1TimpaniMid
    10. Sonic1TimpaniLow:   dcz80   SWF_S1TimpaniLow
    11. Sonic1TimpaniLower: dcz80   SWF_S1TimpaniLower
    Add it onto the end of the list:

    Code (Text):
    1. Scratch:        dcz80   SWF_Scratch
    Finally, you now need to place it in a slot somewhere, right here:

    Code (Text):
    1. ; ---------------------------------------------------------------------------
    2. ; Sample 68k PCM list
    3. ; ---------------------------------------------------------------------------
    4.  
    5. SampleList:     dc.l    StopSample          ; 80 (THIS IS A REST NOTE, DO NOT EDIT...)
    6.             dc.l    Sonic1Kick          ; 81
    7.             dc.l    Sonic1Snare         ; 82
    8.             dc.l    Sonic1TimpaniLow        ; 83
    9.             dc.l    StopSample          ; 84
    10.             dc.l    StopSample          ; 85
    11.             dc.l    StopSample          ; 86
    12.             dc.l    StopSample          ; 87
    13.             dc.l    Sonic1TimpaniHigh       ; 88
    14.             dc.l    Sonic1TimpaniMid        ; 89
    15.             dc.l    Sonic1TimpaniLow        ; 8A
    16.             dc.l    Sonic1TimpaniLower      ; 8B
    You can use any of the slots already taken so far, by replacing the name with "Scratch", for example, we could replace "Sonic1Snare" with "Scratch", and this will cause the DAC ID 82 to play the scratch sample instead of Sonic 1's snare sample. You could use slot 84, 85, 86 or 87 since they're unused, or, you can add in new slots onto the end like so:

    Code (Text):
    1. SampleList:     dc.l    StopSample          ; 80 (THIS IS A REST NOTE, DO NOT EDIT...)
    2.             dc.l    Sonic1Kick          ; 81
    3.             dc.l    Sonic1Snare         ; 82
    4.             dc.l    Sonic1TimpaniLow        ; 83
    5.             dc.l    StopSample          ; 84
    6.             dc.l    StopSample          ; 85
    7.             dc.l    StopSample          ; 86
    8.             dc.l    StopSample          ; 87
    9.             dc.l    Sonic1TimpaniHigh       ; 88
    10.             dc.l    Sonic1TimpaniMid        ; 89
    11.             dc.l    Sonic1TimpaniLow        ; 8A
    12.             dc.l    Sonic1TimpaniLower      ; 8B
    13.             dc.l    Scratch             ; 8C
    From now on, DAC ID "8C" will play the scratch sample.

    The SMPS format only allows you to play samples from 81 to DF, so that will be your limit, this is not a limit of Dual PCM, this is a limit of SMPS

    The scratch sample itself doesn't have to be any specific size, it can be a 1 minute sample if you really wanted it to, what you have to watch out for though, is your ROM limit, again, not a limit of Dual PCM, but rather a limit of the CPU's memory map.

    One important thing to note, I have used ".wav" files here, and the program converts them from any uncompressed "RIFF" format to the right format for Dual PCM, you can use ".bin" files if you want, but your files MUST be 8-bit, MUST be mono, MUST be unsigned, and MUST be 20,500Hz, the program will only convert the important related parts, it cannot know the what bit format, rate, channels, etc, so it simply "assumes" that all ".bin" files will be 8-bit, mono, unsigned, 20,500Hz samples, with NO extra headers/information, just RAW sample data.

    If you make a change to any of the sample files, you MUST redrag them onto the program to convert them once again to update the ".swf" files.

    SMPS Tracker Format

    The only difference to the SMPS files now, is that there's an extra pointer put in for the second PCM channel, and an F2 stop flag for it, and the number of FM/DAC channels has been increased by 1:

    [​IMG]

    After:

    [​IMG]

    And that's it, treat this new channel as you would a normal DAC channel, it is nothing more than having another DAC channel.

    Optimising SFX

    The more FM channels you have running, then the more the Z80 needs to be accessed by the 68k for passing on FM operator data.

    However, I do have something to combat this, a new set of optimised SFX tracks, you can download them here:

    Optimised Sound Pack

    Not all SFX have changed, only some of them (I forget which so I included all of them...).

    A lot of Sonic 1's SFX used multiple channels, even though they really didn't need to, there were also some stereo effects, and so on, and while they might have seem awesome at the time, they are often something that people don't really notice...

    ..and do you know how I know? Because I've used these optimised SFX files (and improved on them) ever since Sonic 1 Brother Trouble, I even used them in Sonic 1 The Next Level, and you know what? No-one even noticed.

    The only person who came close to noticing was one person who mentioned that a track on Brother Trouble seemed to use "extra channels", what they didn't realise was that it's because the SFX didn't mute the music much, they use less channels and sound almost the same. But its use here is more for prevention of quality loss in the PCM playback, the lack of channel stopping is a bonus, you can't say fairer than that~

    Final Stuff

    If you plan to perform DMA transfers, ALWAYS put in a "Z80DMA_ON" before, and a "Z80DMA_OFF" afterwards, to allow the Z80 to avoid getting stopped during a transfer. If you have multiple transfers, DO NOT turn DMA on and off and on and off between each transfer. Turn it on, do all of your transfers, then turn it off. This will reduce the amount of changes the Z80 needs to make to account for the transfers.

    If you plan to write something to the YM2612 from the 68k side, make sure that once you're finished, you write $2A to the YM2612 address port before starting the Z80 again. The Dual PCM driver will NOT set the YM2612 address, it simply "assumes" it already is at $2A, this is to save on Z80 processing time.

    All samples MUST be aligned to a $20th position in the ROM, and the sample MUST end with $80 on the $1Fth position. I have already set this up for you, the program that converts the ".wav" files into ".swf" files will automatically pad to the next $20, and place an $80 on the last byte. And the alignment is already done in the source here:

    Code (Text):
    1. ; ---------------------------------------------------------------------------
    2. ; Sample file includes
    3. ; ---------------------------------------------------------------------------
    4.             align   $20,$FF
    As long as you place all includes here, you will be fine.

    A thank you to "Ralakimus" for providing 32-bit builds of my programs, and to "Egor The Cat" for his helpful guide, and for reminding me of extra details I forgot to add.

    I will be doing some clean up and some quality improvements as time goes on, but I am hoping that some other Z80 programmers out there will contribute to improve the driver, we need as many improvements as we can get if we want Pitch/Volume support. Adding those may cause a major drop in sample rate, and so, we need to be careful how we go about this.

    If any of you have any ideas, or wish to contribute in some way, by all means post away, I'll be happy to at least "attempt" to implement or allow the implementation of ideas into the product as it grows (if it grows).

    I need to stop typing more stuff now as the site's editor is lagging from the amount of text and code put in this tiny dialogue box, have fun~
     
  2. amphobius

    amphobius

    doing more important things with my life Member
    2,120
    0
    16
    life
    You're a madman and I love you.
     
  3. nineko

    nineko

    I am the Holy Cat Tech Member
    6,298
    475
    63
    italy
    Many of you might think that it's a small detail, but one thing I really like is how the pitches of the timpanis are correct. Many custom drivers do terrible things to the timpanis for some reason, and while it's particularly noticeable in the 1-up jingle and in the boss theme, many people don't even seem to notice that.

    Aside from all the obvious things which can be praised about this driver (sound quality, dual channel, ease of use, and so on), having proper timpanis is always good.
     
  4. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,192
    404
    63
    Japan
    Your reputation proceeds you Nineko!

    I am so glad you noticed, I spent hours adjusting the sample rate value in the ".wav" files, until the output pitch matched the originals.
     
  5. rata

    rata

    Member
    689
    72
    28
    Argentina
    Trying to be useful somehow.
    I may try to add this to my base rom, wish me luck! (GitHub's modern disassembly user here)

    This is so awesome it's like black magic or something, thank you very much for doing this!

    Now, correct me if I'm wrong, but as far I can notice, since I have to double the volume of the samples to play properly on the lower bit, theese samples have to be forever bound to the second channel, am I right? Not that it is a problem, not at all, it's just to make sure I'm understanding things right since I'm a bit dumb for theese things.

    Also, before starting, one serious doubt: do I have to first insert a 68k sound driver and after that putting this? This raises my faliure possibilities to like, quad as much as before :p.
     
  6. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,192
    404
    63
    Japan
    No.

    When you use the program of your choice to raise the volume of your samples to twice as loud, that program will most definitely cap it if it overflows. ConvPCM.exe will convert it to 7-bit no matter how loud you have it, allowing the samples to be played on any of the two channels at any time, without overflow, so you do not have to bound your samples to a specific channel. In the test ROM shared at the top of the first post, the Sonic 1 samples have their volumes doubled, as well as the piano/guitar samples, ConvPCM forced them to a capped 7-bit, this is why they don't ever overflow.

    You do not have to worry about which channel you use the samples on, when you use them, or anything like that. Use both of them as much to your heart's contempt, abuse them, get the most out of them! Just raise the volume of your samples until it sounds loud enough for your liking.

    You will need a 68k driver for FM/PSG/tracker playback, like I said, Dual PCM needs the entire Z80's resources to do its job. If you are hacking a game that does not have a 68k FM/PSG/tracker playback driver, then I'd suggest looking into the Clone Driver (originally by Tweaker, and someone else I currently forget who. And lately being improved by Clownacy with heaps of bug-fixes).

    The guide above, is nothing more than a guide.
     
  7. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,192
    404
    63
    Japan
    Update...

    Some changes that will improve the quality slightly...

    Open up "sonic1.asm" source, find this:

    Code (Text):
    1. Z80ROM:     incbin  "Dual PCM\Z80.bin"
    2. Z80ROM_End: even
    Change it to this:

    Code (Text):
    1. Z80ROM:     incbin  "Dual PCM\Z80.bin"
    2.         dcz80   SWF_StopSample
    3. Z80ROM_End: even
    Then find this:

    Code (Text):
    1. SWF_StopSample: dcb.b   $1F,$00
    2.         dc.b    $80
    Change it to this:

    Code (Text):
    1. SWF_StopSample: dcb.b   $7FFF,$00
    2.         dc.b    $80
    Download this new Z80.asm file, and replace the old one.

    And finally, open up "ConvPCM.txt" and change "19500" to "20500", and of course, drag and drop your samples again.

    ------------------------------------------------------------------------------------

    Basically, the sample flushing is staggered, but it wasn't 100% smooth/consistent. I analysed the output waveform and found difference in times between each byte flush, I've changed the order slightly, and now it's considerably smoother, this'll remove the "crinkly" sound you here a little bit.

    In addition, some emulators (like KEGA) as well as hardware had samples playing at a slightly higher pitch when one of the channels were resting, I'm not too sure though I suspect the Z80 accessing the window is slightly slower. And so, the null/mute sample that the channels will play when resting, will now be on the 68k side and accessed through the window instead. This will cost you $8000 bytes of ROM space. But it'll mean the pitch will also remain consistent now.

    I'll update the first post to include this update in a moment.
     
  8. rata

    rata

    Member
    689
    72
    28
    Argentina
    Trying to be useful somehow.
    Thank you very much for your answer, I will follow your advice and try to port Clone Driver then.
     
  9. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,192
    404
    63
    Japan
    I am a little embarrassed to report that...

    ...well, I've made a fatal error that caused the sound driver to sound aweful on hardware. I STRONGLY suggest fixing it by opening up "Macro.asm", and in "Z80DMA_ON", changing this:

    Code (Text):
    1.         move.w  #$0000,d7
    To this:

    Code (Text):
    1.         move.w  #$0180,d7
    This didn't allow the Z80 enough time, and well, the results were horrible, this will fix the quality greatly... You won't notice this quality on emulation, but you will definately on hardware!

    I will have an update coming later on tonight which will ensure the highest quality possible for 20,500Hz Dual samples, it's gonna be AMAZING guys, because you'll be able to hear the difference on emulation as well as hardware~

    Edit; here's a recording of it so far from hardware:

    Model 1 Recording
    Nomad Recording

    I couldn't get a Model 2 recording because it lacks a headphone jack, but it sounds pretty damn fine on there (in fact, Model 2's filter seems to do the samples some extra justice).
     
  10. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,192
    404
    63
    Japan
    UPDATE!!

    We now have an update, this driver now avoids Z80 stops caused by FM operator data being written, I shall update the first post with the most recent version, but here is a list of steps you those that already have the driver installed and in use.

    >> 1. Download this new "Z80.asm" source, and replace the old one in the "Dual PCM" folder.

    >> 2. Download this new "Macros.asm" source, and replace the old one.

    >> 3. Open up "sonic1.asm" and find "sub_71B4C:":

    Code (Text):
    1. sub_71B4C:              ; XREF: loc_B10; PalToCRAM
    2.         lea ($FFF000).l,a6
    Replace this, with:

    Code (Text):
    1. YM_Access_WaitRead:
    2.         StartZ80                    ; EXT: request Z80 stop off (allow it to continue)
    3.         rept    $10                 ; EXT: delay for a long enough time to allow the...
    4.         nop                     ; EXT: '' ...68k pointer to be saved correctly.
    5.         endr                        ; EXT: ''
    6.  
    7. sub_71B4C:  
    8.         lea ($FFF000).l,a6
    9.  
    10.         lea ($A00000+YM_Access).l,a0        ; EXT: load access address in Z80
    11.         move.l  #$A00000,d0             ; EXT: prepare Z80 RAM address in d0 (i.e. start of Cue list address)
    12.         StopZ80                     ; EXT: request Z80 stop on
    13.         tst.b   (a0)+                   ; EXT: is the Z80 accessing the 68k pointer?
    14.         bne.s   YM_Access_WaitRead          ; EXT: if so, branch and wait for it to finish...
    15.         move.b  (a0)+,d1                ; EXT: load lower byte of pointer
    16.         move.b  (a0)+,d0                ; EXT: load upper byte of pointer
    17.         StartZ80                    ; EXT: request Z80 stop off
    18.         lsl.w   #$08,d0                 ; EXT: shift upper byte up
    19.         move.b  d1,d0                   ; EXT: put lower byte with it
    20.         move.l  d0,$10(a6)              ; EXT: store the cue address
    >> 4. Find "loc_71C44:":

    Code (Text):
    1. loc_71C44:
    2.         rts
    Replace it with this:

    Code (Text):
    1. loc_71C44:
    2.         bra.s   YM_Access_TestWrite         ; EXT: jump into the access loop
    3.  
    4. YM_Access_WaitWrite:
    5.         StartZ80                    ; EXT: request Z80 stop off (allow it to continue)
    6.         rept    $10                 ; EXT: delay for a long enough time to let the Z80...
    7.         nop                     ; EXT: '' ...finish writing the 68k pointer, so it doesn't...
    8.         endr                        ; EXT: '' ...clash with 68k's pointer writing.
    9.  
    10. YM_Access_TestWrite:
    11.         lea ($A00000+YM_Access).l,a0        ; EXT: load access address in Z80
    12.         lea $13(a6),a1              ; EXT: load the 68k's pointer finish location
    13.         StopZ80                     ; EXT: request Z80 stop on
    14.         tst.b   (a0)+                   ; EXT: is the Z80 accessing the 68k pointer?
    15.         bne.s   YM_Access_WaitWrite         ; EXT: if so, branch and wait for it to finish...
    16.         move.b  (a1),(a0)+              ; EXT: save lower byte of pointer
    17.         move.b  -(a1),(a0)              ; EXT: save upper byte of pointer
    18.         StartZ80                    ; EXT: request Z80 stop off
    19.  
    20.         rts
    >> 5. Find routine "loc_72068:", and delete these:

    Code (Text):
    1.         moveq   #$FFFFFFFF,d2               ; MJ: clear PCM finish flag
    Code (Text):
    1.         addq.b  #$01,d2                 ; MJ: set PCM finish flag
    2.         beq.s   SD_NoFM                 ; MJ: if it hasn't finished yet (not for two turns), branch
    3.         moveq   #$02,d5                 ; MJ: set longer delay for FM/PSG channels (DAC has delay now...)
    4.  
    5. SD_NoFM:
    >> 6. Find routine "loc_72114:", and insert this instruction directly after the label:

    Code (Text):
    1.         moveq   #$02,d5                 ; EXT: set PSG to delay for 1 extra frame (This is to match the PSG with the FM/DAC which is delayed a frame by the Z80)
    2.  
    >> 7. Find routine "loc_72228:":

    Code (Text):
    1. loc_72228:
    2.         moveq   #0,d3
    3.         move.b  1(a1),d3
    4.         move.b  d3,d4
    5.         bmi.s   loc_72244
    6.         subq.w  #2,d3
    7.         lsl.w   #2,d3
    And replace it with:

    Code (Text):
    1. loc_72228:
    2.         moveq   #0,d3
    3.         move.b  1(a1),d3
    4.         moveq   #$02,d2                 ; EXT: set PSG to delay for 1 extra frame (This is to match the PSG with the FM/DAC which is delayed a frame by the Z80)
    5.         move.b  d3,d4
    6.         bmi.s   loc_72244
    7.         move.b  #$01,d2                 ; EXT: set DAC/FM to delay for 0 frames like normal (these have an auto delay of 1 frame in the Z80)
    8.         subq.w  #2,d3
    9.         lsl.w   #2,d3
    >> 8. Find "loc_72276:", further down you will find this:

    Code (Text):
    1.         move.b  #1,$E(a5)
    Replace it with this:

    Code (Text):
    1.         move.b  d2,$E(a5)               ; EXT: moving d2 contents (1 for FM/4 for PSG)
    >> 9. Find "Sound_E4:":

    Code (Text):
    1. Sound_E4:               ; XREF: Sound_ChkValue; Sound_ExIndex; sub_72504
    2.         moveq   #$2B,d0
    3.         move.b  #$80,d1
    4.         jsr sub_7272E(pc)
    5.         moveq   #$27,d0
    6.         moveq   #0,d1
    7.         jsr sub_7272E(pc)
    8.         movea.l a6,a0
    9.         move.w  #$EF,d0             ; MJ: new size of data to clear
    10.  
    11. loc_725B6:
    12.         clr.l   (a0)+
    13.         dbf d0,loc_725B6
    14.  
    15.         move.b  #$80,9(a6)  ; set music to $80 (silence)
    16.         jsr sub_7256A(pc)
    17.         bra.w   sub_729B6
    18.  
    19. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    20.  
    21.  
    22. sub_725CA:              ; XREF: Sound_ChkValue
    23.         movea.l a6,a0
    24.         move.b  0(a6),d1
    25.         move.b  $27(a6),d2
    26.         move.b  $2A(a6),d3
    27.         move.b  $26(a6),d4
    28.         move.w  $A(a6),d5
    29.         move.w  #$93,d0             ; MJ: new size
    30.  
    31. loc_725E4:
    32.         clr.l   (a0)+
    33.         dbf d0,loc_725E4
    34.  
    35.         move.b  d1,0(a6)
    36.         move.b  d2,$27(a6)
    37.         move.b  d3,$2A(a6)
    38.         move.b  d4,$26(a6)
    39.         move.w  d5,$A(a6)
    40.         move.b  #$80,9(a6)
    41.         jsr sub_7256A(pc)
    42.         bra.w   sub_729B6
    43. ; End of function sub_725CA
    Replace it with this:

    Code (Text):
    1. Sound_E4:
    2.         StopZ80
    3.         lea (StopSample).l,a0               ; EXT: load stop sample address
    4.         lea ($A00000+PCM1_Sample).l,a1          ; EXT: load PCM 1 slot address
    5.         move.b  (a0)+,(a1)+                 ; EXT: set address of sample
    6.         move.b  (a0)+,(a1)+                 ; EXT: ''
    7.         move.b  (a0)+,(a1)+                 ; EXT: ''
    8.         move.b  #(CUPCM1_NewSample&$FF),($A00000+CU_Stack).l    ; EXT: set routine to run
    9.         move.b  #(CUPCM1_NewSample>>$08),($A00000+CU_Stack+1).l ; EXT: ''
    10.         move.b  #%11001001,($A00000+CUPCM1_RET).l       ; EXT: change "NOP" to "RET"
    11.         lea (StopSample).l,a0               ; EXT: load stop sample address
    12.         lea ($A00000+PCM2_Sample).l,a1          ; EXT: load PCM 2 slot address
    13.         move.b  (a0)+,(a1)+                 ; EXT: ''
    14.         move.b  (a0)+,(a1)+                 ; EXT: ''
    15.         move.b  (a0)+,(a1)+                 ; EXT: ''
    16.         move.b  #%00101000,($A00000+CUPCM2_RET).l       ; EXT: change "JR NZ" to "JR Z"
    17.         StartZ80
    18.  
    19.         moveq   #$2B,d0
    20.         move.b  #$80,d1
    21.         jsr sub_7272E(pc)
    22.         moveq   #$27,d0
    23.         moveq   #0,d1
    24.         jsr sub_7272E(pc)
    25.         movea.l a6,a0
    26.         move.l  $10(a6),d6                  ; EXT: store YM Cue list pointer
    27.         move.w  #$EF,d0                     ; MJ: new size of data to clear
    28.  
    29. loc_725B6:
    30.         clr.l   (a0)+
    31.         dbf d0,loc_725B6
    32.  
    33.         move.l  d6,$10(a6)                  ; EXT: restore YM Cue list pointer
    34.         move.b  #$80,9(a6)  ; set music to $80 (silence)
    35.         jsr sub_7256A(pc)
    36.         bra.w   sub_729B6
    37.  
    38. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    39.  
    40.  
    41. sub_725CA:              ; XREF: Sound_ChkValue
    42.         movea.l a6,a0
    43.         move.b  0(a6),d1
    44.         move.b  $27(a6),d2
    45.         move.b  $2A(a6),d3
    46.         move.b  $26(a6),d4
    47.         move.w  $A(a6),d5
    48.         move.l  $10(a6),d6                  ; EXT: store YM Cue list pointer
    49.         move.w  #$93,d0                     ; MJ: new size
    50.  
    51. loc_725E4:
    52.         clr.l   (a0)+
    53.         dbf d0,loc_725E4
    54.  
    55.         move.b  d1,0(a6)
    56.         move.b  d2,$27(a6)
    57.         move.b  d3,$2A(a6)
    58.         move.b  d4,$26(a6)
    59.         move.w  d5,$A(a6)
    60.         move.l  d6,$10(a6)                  ; EXT: restore YM Cue list pointer
    61.         move.b  #$80,9(a6)
    62.         jsr sub_7256A(pc)
    63.         bra.w   sub_729B6
    64. ; End of function sub_725CA
    >> 10. Find this:

    Code (Text):
    1. sub_7272E:
    2.         pea (a0)                    ; MJ: store register
    3.         lea ($A04000).l,a0              ; MJ: load YM2612 address port
    4.         StopZ80                     ; MJ: request Z80 stop "ON"
    5.         move.b  d0,(a0)                 ; MJ: write address
    6.     rept    $0F
    7.         nop                     ; MJ: delay (Tested on MD1 and 2. F nops are required)
    8.     endr
    9.         move.b  d1,$01(a0)              ; MJ: write data
    10.     rept    $0F
    11.         nop                     ; MJ: delay (Tested on MD1 and 2. F nops are required)
    12.     endr
    13.         move.b  #$2A,(a0)               ; MJ: write address (set it back to DAC port for the Z80)
    14.         StartZ80                    ; MJ: request Z80 stop "OFF"
    15.         move.l  (sp)+,a0                ; MJ: restore register
    16.         rts                     ; MJ: return
    17.  
    18. ; End of function sub_7272E
    19.  
    20. ; ===========================================================================
    21.  
    22. loc_7275A:              ; XREF: sub_72722
    23.         move.b  1(a5),d2
    24.         bclr    #2,d2
    25.         add.b   d2,d0
    26.  
    27. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    28.  
    29.  
    30. sub_72764:
    31.         pea (a0)                    ; MJ: store register
    32.         lea ($A04000).l,a0              ; MJ: load YM2612 address port
    33.         StopZ80                     ; MJ: request Z80 stop "ON"
    34.         move.b  d0,$02(a0)              ; MJ: write address
    35.     rept    $0F
    36.         nop                     ; MJ: delay (Tested on MD1 and 2. F nops are required)
    37.     endr
    38.         move.b  d1,$03(a0)              ; MJ: write data
    39.     rept    $0F
    40.         nop                     ; MJ: delay (Tested on MD1 and 2. F nops are required)
    41.     endr
    42.         move.b  #$2A,(a0)               ; MJ: write address (set it back to DAC port for the Z80)
    43.         StartZ80                    ; MJ: request Z80 stop "OFF"
    44.         move.l  (sp)+,a0                ; MJ: restore register
    45.         rts                     ; MJ: return
    Replace it with:

    Code (Text):
    1. sub_7272E:
    2.         movem.l d2/a0,-(sp)             ; EXT: store register data
    3.         movea.l $10(a6),a0              ; EXT: load Cue pointer
    4.         addq.w  #$01,a0                 ; EXT: skip $40
    5.         move.b  #$00,d2                 ; EXT: prepare d2 for YM2612 port address ($4000 - $4001)
    6.         StopZ80                     ; EXT: request Z80 stop "ON"
    7.         move.b  d2,(a0)+                ; EXT: write YM2612 port address
    8.         move.b  d1,(a0)+                ; EXT: write YM2612 data
    9.         move.b  d0,(a0)+                ; EXT: write YM2612 address
    10.         StartZ80                    ; EXT: request Z80 stop "OFF"
    11.         move.w  a0,d2                   ; EXT: load Cue pointer
    12.         andi.w  #$0FFF,d2               ; EXT: wrap it
    13.         ori.w   #$1000,d2               ; EXT: ''
    14.         move.w  d2,$12(a6)              ; EXT: update it
    15.         movem.l (sp)+,d2/a0             ; EXT: restore register data
    16.         rts                     ; EXT: return
    17.  
    18. ; ===========================================================================
    19.  
    20. loc_7275A:              ; XREF: sub_72722
    21.         move.b  1(a5),d2
    22.         bclr    #2,d2
    23.         add.b   d2,d0
    24.  
    25. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    26.  
    27.  
    28. sub_72764:
    29.         movem.l d2/a0,-(sp)             ; EXT: store register data
    30.         movea.l $10(a6),a0              ; EXT: load Cue pointer
    31.         addq.w  #$01,a0                 ; EXT: skip $40
    32.         move.b  #$02,d2                 ; EXT: prepare d2 for YM2612 port address ($4002 - $4003)
    33.         StopZ80                     ; EXT: request Z80 stop "ON"
    34.         move.b  d2,(a0)+                ; EXT: write YM2612 port address
    35.         move.b  d1,(a0)+                ; EXT: write YM2612 data
    36.         move.b  d0,(a0)+                ; EXT: write YM2612 address
    37.         StartZ80                    ; EXT: request Z80 stop "OFF"
    38.         move.w  a0,d2                   ; EXT: load Cue pointer
    39.         andi.w  #$0FFF,d2               ; EXT: wrap it
    40.         ori.w   #$1000,d2               ; EXT: ''
    41.         move.w  d2,$12(a6)              ; EXT: update it
    42.         movem.l (sp)+,d2/a0             ; EXT: restore register data
    43.         rts                     ; EXT: return
    >> 11. Find this:

    Code (Text):
    1. SoundDriverLoad:
    2.         lea (Z80ROM).l,a0               ; load Z80 ROM data
    3.         lea ($A00000).l,a1              ; load Z80 RAM space address
    4.         move.w  #(Z80ROM_End-Z80ROM)-$01,d1     ; set repeat times
    5.         move.w  #$2000,d2               ; prepare total Z80 size
    6.         sub.w   d1,d2                   ; subtract repeat times from total size
    7.         subq.w  #$02,d2                 ; decrease by 2 (for dbf)
    8.         move.w  #$0100,($A11100).l          ; request Z80 stop (ON)
    9.         move.w  #$0100,($A11200).l          ; request Z80 reset (OFF)
    10.         btst.b  #$00,($A11100).l            ; has the Z80 stopped yet?
    11.         bne.s   *-$08                   ; if not, branch
    12.  
    13. SM_LoadZ80:
    14.         move.b  (a0)+,(a1)+             ; dump Z80 data to Z80 space
    15.         dbf d1,SM_LoadZ80               ; repeat til done
    16.  
    17. SM_ClearZ80:
    18.         move.b  d0,(a1)+                ; clear remaining Z80 space
    19.         dbf d2,SM_ClearZ80              ; repeat til done
    20.         move.w  #$0000,($A11200).l          ; request Z80 reset (ON)
    21.         moveq   #$7F,d1                 ; set repeat times
    22.         dbf d1,*                    ; there's no way of checking for reset, so a manual delay is necessary
    23.         move.w  #$0000,($A11100).l          ; request Z80 stop (OFF)
    24.         move.w  #$0100,($A11200).l          ; request Z80 reset (OFF)
    25.         rts                     ; return
    Replace it with:

    Code (Text):
    1. SoundDriverLoad:
    2.         lea (Z80ROM).l,a0               ; load Z80 ROM data
    3.         lea ($A00000).l,a1              ; load Z80 RAM space address
    4.         move.w  #(Z80ROM_End-Z80ROM)-$01,d1     ; set repeat times
    5.         move.w  #$0100,($A11100).l          ; request Z80 stop (ON)
    6.         move.w  #$0100,($A11200).l          ; request Z80 reset (OFF)
    7.         btst.b  #$00,($A11100).l            ; has the Z80 stopped yet?
    8.         bne.s   *-$08                   ; if not, branch
    9.  
    10. SM_LoadZ80:
    11.         move.b  (a0)+,(a1)+             ; dump Z80 data to Z80 space
    12.         dbf d1,SM_LoadZ80               ; repeat til done
    13.         lea (StopSample).l,a0           ; load stop/mute sample address
    14.         lea ($A00000+MuteSample).l,a1       ; load Z80 RAM space where the pointer is to be stored
    15.         move.b  (a0)+,(a1)+             ; copy pointer over into Z80
    16.         move.b  (a0)+,(a1)+             ; ''
    17.         move.b  (a0)+,(a1)+             ; ''
    18.         move.w  #$0000,($A11200).l          ; request Z80 reset (ON)
    19.         moveq   #$7F,d1                 ; set repeat times
    20.         dbf d1,*                    ; there's no way of checking for reset, so a manual delay is necessary
    21.         move.w  #$0000,($A11100).l          ; request Z80 stop (OFF)
    22.         move.w  #$0100,($A11200).l          ; request Z80 reset (OFF)
    23.         rts                     ; return
    >> 12. Find this:

    Code (Text):
    1. Z80ROM:     incbin  "Dual PCM\Z80.bin"
    2.         dcz80   SWF_StopSample
    3. Z80ROM_End: even
    Replace it with this:

    Code (Text):
    1. Z80ROM:     incbin  "Dual PCM\Z80.bin"
    2. Z80ROM_End: even
    Finished... I'll be updating the first post now.
     
  11. Caverns 4

    Caverns 4

    Member
    346
    0
    16
    Sonic: Retold
    I really, honestly doubted something like would be possible just because of how limited the Z80's power is, but I'm happy to eat my words.
    This is outstanding, MarkeyJester!
     
  12. rata

    rata

    Member
    689
    72
    28
    Argentina
    Trying to be useful somehow.
    Thank god I didn't start with that yet :p.

    Also, I thought that Model 2 was worse in terms of sound? What did I miss now?
     
  13. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,192
    404
    63
    Japan
    Alright ladies and gentlemen, I have some good news for you all!

    I rewrote the Z80 side of Dual PCM in order to support pitch control, this form of pitch control isn't done by delay however since a delay would cause both samples to pitch at the same time. Instead I'm using a mathematical fixed point 16 bit quotient 8 bit dividend to control the pitch of each PCM channel individually, this also means that a specific pitch can be played, any specific pitch that PCM playback can muster. This brought the sample playback down to about 13.000Hz unfortunately...

    However, after rearranging the time in which the samples are fused (doing on playback rather than collection), I was able to increase that sample rate to 14.400Hz. And with suggestions, support and encouragement from Natsumi, as well as a lot of shared ideas, we've managed to get a stable enough build to play back any two samples, any size, at any pitch, including looping sample support, as well as reversal playback. All at a sample rate of 14.400Hz, but with little to no chopping on hardware for that clean and crisp quality.

    http://mrjester.hapisan.com/01_Public/DualPCMPitchTest.mp3

    (I posted this in the music thread.)

    However, I went a step further and wondered how well it'd perform by changing the number of bytes loaded into the buffer vs playback. Dual PCM has always been; "Load 20, Play 10". So after ripping the driver apart, and applying some careful buffer wrapping methods for non-POT (not power of two) sizes, I tried with; "Load 18, Play 10", and this raised the sample rate to 16.500Hz. I then went a step further and tried "Load 14, Play 10", and the sample rate is a nice healthy 18.000Hz playback!

    I've muted FM and PSG playback so you can hear just Dual PCM running (FM and PSG are still running in the background, they in quite mode):

    http://mrjester.hapisan.com/01_Public/DualPCMPitchTest2.mp3

    I haven't tested this on hardware yet, and I suspect there may be a considerable delay, there's also a lot of testing and some clean-up to do, so stay tuned~

    This is so exciting! =D
     
  14. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,192
    404
    63
    Japan
    A small bump (nothing major yet).

    After some heavy drumbling, a lot of nudging and fudging, and some very precise instruction usage, and abusing undocumented quirks, I have managed to do the following so far:
    1. The sample rate playback is currently 20,500Hz and counting (might get it a little higher if you're lucky).
    2. The samples are now stored on the ROM in their native unsigned 8-bit format. The output is still the same, as in, you'll still have a 7-bit sample being played, but 8-bit unsigned is stored on the ROM. So you could in reality just include an unsigned 8-bit sample, without the use of the tool I've written. You just have to make sure that the byte "00" isn't used anywhere in the sample (I'm keeping the tool in of course, just for ease of use for noobs, but still...)
    3. I "might" include some volume control at the expense of some of that sample rate (let me know your opinion on that).
    4. The SMPS structure to DAC channels has changed significantly. Now you select a sample using the F5 flag (F5 XX, where XX is the instrument/sample ID), and you play the note you want from 81 to DF (for pitch/notes).
    5. The FA flag will turn on/off the "reverse playback" mode, use once to turn on, use again to turn off.
    6. The FB flag will turn on/off the "looping" mode, when the sample reaches the end it'll loop back and play again (will be useful for instruments/sounds that play a sound/note forever with no decay).
    7. The E1 and F0 (detune and modulation) flags affect the frequency/pitch of the samples, so you can make it vibrato, or bend or whatever... as well as the E9 flag for pitch changing.
    8. Reduced the wait time on the 68k side by a MASSIVE amount of time.
    All of the above is working with the (still) ability to play any sample, anywhere, any size, anytime, and at near perfect quality on hardware (due to Jester Stream Technology, and the YMCUE Listing System).

    I have a lot of clean up to do, but so long as you're all patient the coming weeks, you'll be thankful of the features and control available to you on release~ Also, I'm open to feature ideas related to the driver itself, if I can support those ideas, I will. But you have to speak up...
     
  15. redquebec

    redquebec

    Member
    39
    0
    6
    Thanks a lot for the hard-work you provide to us all. Some features? Well, I don't know how much it is possible, but the smooth PCM panning? LINK: http://www.sega-16.com/forum/showthread.php?20704-Undocumented-YM2612-register-2C-Smooth-PCM-panning!
     
  16. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,192
    404
    63
    Japan
    Yeah, I know about that (in fact, my name is plastered all over the thread! Yay! =D).

    The issue though, is that by enabling this, you convert all FM channels into a DAC channel each, unfortunately, they reference from the same 8-bit port, meaning that they playback exactly the same sound, so there's no variation. But, in regards to the "panning" trick oerg pulled by manipulating the left/right speaker on/off of each channel. Is that, firstly, this will control all sounds flushed in so both PCM channels will be panned the same, rather than individually, though it's still better than absolute panning. But the second issue is a real problem, the fact that it disables FM operator playback means that you are sacrificing 5 FM channels, just for some smooth panning and a slightly louder playback. The third issue, is that you will only experience this quirk on hardware as it was an unknown quirk at the time of those many of public emulators out there being released. So no emulators will support this, this heavily hinders and limits the audience.

    If the two sounds being flushed could pan individually, then it may have more benefit, we could stuff the entire ROM with sample data, and flush out BGM through one, and SFX through the other, especially given that we potentially have unlimited memory on the cartridge, but again, it all comes down to emulators supporting DTAK on cartridge, to access the Mega CD and 32X memory map as cartridge space, and even memory mappers are limited on emulators. But the lack of individual channel panning (even if not smooth) would have been prefered.

    tl;dr, this causes more sacrifice than the benefits it's meant to give. Sorry =o