Sonic 1 "Mega PCM" driver

Discussion in 'Engineering & Reverse Engineering' started by vladikcomper, Jun 11, 2012.

  1. PsychoSk8r

    PsychoSk8r

    HighKnights Oldbie
    2,580
    0
    0
    Walsall, UK
    30 Day Project: Revisited.A New Release!
    Haha, sweet. That should keep things neater. There's got to be some data somewhere on how macros work differently with the two assemblers. Such a shame we don't have one assembler that's supported globally. Also, the "strcmp" (which I loved the usage of in this case) added to the IncludeDAC macro is incompatible. Googling for a compatible alternative yielded no results. =P
     
  2. ValleyBell

    ValleyBell

    Tech Member
    237
    10
    18
    researching SMPS sound drivers
    The AS manual has an example in Chaper 3.4.1 where two strings are compared in a sort of case insensitive way.
    But there's indeed a lack of documentation for the assemblers. At least a txt with a link to the assembler manuals somewhere in the disassembly would be nice.
     
  3. PsychoSk8r

    PsychoSk8r

    HighKnights Oldbie
    2,580
    0
    0
    Walsall, UK
    30 Day Project: Revisited.A New Release!
    Excellent link. I think perhaps we should attempt to provide documentation with each disassembly, perhaps just throw in a new folder "_Docs" or something. It could be immense amounts of help to anyone trying to familiarise themselves, or porting code. The biggest challenge faced with porting large amounts of code is compatibility between assemblers, I've found.
    Thanks for that link. =P
     
  4. Caverns 4

    Caverns 4

    Member
    342
    0
    16
    Sanik Quest: Journey To The Right
    I would like to see this able to work in Sonic 2. Partly because that's what I am hacking, but also partly because the page for porting the Sonic 1 sound driver into Sonic 2 provides an ASM file that looks like somebody screwed with it. There's a bunch of unintelligible garbage data in the file, some of with is replacing pointers and addresses. implementing this might be a good solution even if it's a little more (lot more) advanced than what I was to do.

    It looks really awesome, excellent work! I didn't know the genesis was capable of this!
     
  5. Clownacy

    Clownacy

    Tech Member
    797
    29
    28
    Building on what I gathered from the previous posts, I have compiled a guide on porting the Mega PCM driver to the Sonic 2 Clone Driver. Included in the guide is a fix for the DPCM bug, and Sonic 2 compatible Z80 stop and VBlank/V_Int optimisations.

    Update 17/12/13 dd/mm/yy General clean up. Fixed some factual errors, formatted the last section to a better degree and made the 'Optimizing Z80 stops in SMPS' section an actual guide as opposed to a paragraph long 'I dunno.' Also, new opening.

    —INSTALLING MEGA PCM—
    Before we can install Mega PCM, we've got to install the Clone Driver, guides can be found here and here. You can install the stock Sonic 1 sound driver if you want to: (here, go nuts), but be aware that this guide does not have that in mind.

    Once done, follow the How-To in the main post for installing Mega PCM with the following changes:

    • Apply it to Sonic 2 Clone Driver.asm (mainly) and s2.asm (when replacing SoundDriverLoad).
    • If following mine or Cavern 4's guide on implementing the Clone Driver, replace JmpTo_SoundDriverLoad instead of SoundDriverLoad.
    • Fix local labels (@Load) (just replace the '@' with '.').
    • When replacing loc_71EDC, replace all instances of @UnpauseDAC with loc_71EFE.

    If you try building your ROM, you'll encounter a lot of errors, not to do with the code modifications you just made, but with MegaPCM.asm itself, with the new assembler and all. Let's get to work on it.



    —MAKING MEGAPCM.ASM AS COMPATIBLE—
    Open up MegaPCM.asm and replace the IncludeDAC macro with the following (credit to ValleyBell for the original fix, improved by myself):

    Code (ASM):
    1. IncludeDAC macro Name,Extension
    2. Name:       label   *
    3.     if ("Extension"="WAV")
    4.         BINCLUDE    "sound/DAC/Name.Extension",$3A
    5.     else
    6.         BINCLUDE    "sound/DAC/Name.Extension"
    7.     endif
    8. Name_End:   label   *
    9.     endm


    This makes the macro compatible with the different assembler.

    Replace instances of 'incbin' with 'BINCLUDE', and remove the marks surrounding 'MegaPCM.z80' (or replace them with "), also remove the slashes (/) found in the DAC_Entry and z80word macros. Again, assembler differences.



    —PCM TRANSPLANT—
    Now build your ROM, open the result in your emulator of choice and proceed to have your ears blasted. This is that DPCM failure. So, if you look around the previous posts, you'll get the idea to just "decompress" the DPCMs. While that is a suitable workaround, that's just it, it's a workaround, not a fix, and believe me it will bite you in the arse later on, as mentioned above. However, for the sake of you, the hacker, experiencing your progress first-hand instead of me just telling you how it's going, we'll go ahead and "decompress" the samples, use JMan's s1sndcomp tool (link here) or any other DPCM to PCM converter and "decompress" each sample (three in all) to "Kick.raw", "Snare.raw", and "Timpani.raw".

    Now modify the pointers in MegaPCM.asm to point to the .raw files: Replace the 'dpcm' flags with 'pcm' and in the Samples Files, replace the instances of 'bin' with 'raw'. Build and test.

    The results should be pleasing... for now: You'll notice certain samples not play in several instances such as Emerald Hill's intro and Metropolis, whose sole duty is now to deafen you. But this is all to be expected, right? Well, there are only three samples registered to Mega PCM while, as you may guess, stock Sonic 2 includes more, seven in total to be exact, so let's get to adding those.

    Open your sound folder and locate the following files:

    • dac1d.bin
    • dac2d.bin
    • dac3d.bin
    • dac4d.bin
    • dac5d.bin
    • dac6d.bin
    • dac7d.bin



    Throw these into your DAC folder (not the one inside your sound folder) and, for the sake of user-friendliness, rename them:

    • DAC1KICK.BIN
    • DAC2SNARE.BIN
    • DAC3CLAP.BIN
    • DAC4SCRATCH.BIN
    • DAC5TIMPANI.BIN
    • DAC6TOM.BIN
    • DAC7BONGO.BIN



    Now "decompress" them, following the same name scheme, but with the .raw file extension.

    Once again, we've got to modify the pointers to use the new samples, but first we need a guideline:

    Take a peek inside Sonic 2 Clone Driver.asm and find the label PCM_Table, it should look like this:

    Code (ASM):
    1. PCM_Table:  dc.l    $A00200, DAC1
    2.         dc.w    $352
    3.         dc.b    $19,0
    4.         dc.l    $A00208, DAC2
    5.         dc.w    $770
    6.         dc.b    $4,0
    7.         dc.l    $A00210, DAC3
    8.         dc.w    $576
    9.         dc.b    $8,0
    10.         dc.l    $A00218, DAC4
    11.         dc.w    $BB5
    12.         dc.b    $A,0
    13.         dc.l    $A00220, DAC5
    14.         dc.w    $1016
    15.         dc.b    $1D,0
    16.         dc.l    $A00228, DAC6
    17.         dc.w    $622
    18.         dc.b    $C,0
    19.         dc.l    $A00230, DAC7
    20.         dc.w    $5C4
    21.         dc.b    $1D,0


    Would you look at that, the similarities make porting this all the easier. See the first value in each dc.b entry? That's our tempo/pitch, and the DACX (X being a number) in the dc.l? Well, you can guess what that is. Apply these values to the Samples Table in MegaPCM.asm, you should be left with this:

    Code (ASM):
    1. ; ---------------------------------------------------------------
    2. ; DAC Samples Table
    3. ; ---------------------------------------------------------------
    4.  
    5.     DAC_Entry       $19, DAC1KICK, pcm          ; $81   - Kick
    6.     DAC_Entry       $04, DAC2SNARE, pcm         ; $82   - Snare
    7.     DAC_Entry       $08, DAC3CLAP, pcm          ; $83   - Clap
    8.     DAC_Entry       $0A, DAC4SCRATCH, pcm           ; $84   - Scratch
    9.     DAC_Entry       $1D, DAC5TIMPANI, pcm           ; $85   - Timpani
    10.     DAC_Entry       $0C, DAC6TOM, pcm           ; $86   - Tom
    11.     DAC_Entry       $1D, DAC7BONGO, pcm         ; $87   - Bongo
    12.  
    13. MegaPCM_End:


    Also, below it, modify the Samples Files table to include the new samples, doing so should give you this:

    Code (ASM):
    1. ; ---------------------------------------------------------------
    2. ; DAC Samples Files
    3. ; ---------------------------------------------------------------
    4.  
    5.     IncludeDAC  DAC1KICK, raw
    6.     IncludeDAC  DAC2SNARE, raw
    7.     IncludeDAC  DAC3CLAP, raw
    8.     IncludeDAC  DAC4SCRATCH, raw
    9.     IncludeDAC  DAC5TIMPANI, raw
    10.     IncludeDAC  DAC6TOM, raw
    11.     IncludeDAC  DAC7BONGO, raw
    12.     even

    Now, save and build.

    But wait, we're missing something! Play the end of act theme and listen to the music's DAC channel, it goes blank partway through! You can find the cause by examining the original MegaPCM.asm.

    Code (ASM):
    1. ; ---------------------------------------------------------------
    2. ; DAC Samples Table
    3. ; ---------------------------------------------------------------
    4.  
    5.     DAC_Entry   $08, Kick, dpcm         ; $81   - Kick
    6.     DAC_Entry   $08, Snare, dpcm        ; $82   - Snare
    7.     DAC_Entry   $1B, Timpani, dpcm      ; $83   - Timpani
    8.     dc.l    0,0                 ; $84   - <Free>
    9.     dc.l    0,0                 ; $85   - <Free>
    10.     dc.l    0,0                 ; $86   - <Free>
    11.     dc.l    0,0                 ; $87   - <Free>
    12.     DAC_Entry   $12, Timpani, dpcm      ; $88   - Hi-Timpani
    13.     DAC_Entry   $15, Timpani, dpcm      ; $89   - Mid-Timpani
    14.     DAC_Entry   $1B, Timpani, dpcm      ; $8A   - Mid-Low-Timpani
    15.     DAC_Entry   $1D, Timpani, dpcm      ; $8B   - Low-Timpani


    Notice the entries at the bottom? They're additional Timpani entries! Each defines a unique pitch/tempo (with the exception of Mid-Low-Timpani), and if you listen to stock Sonic 2, you'll find that it is these Timpani samples that are missing from the current port! The fix is simple; copy and paste them over and adjust the pitch, as such:

    Code (ASM):
    1. ; ---------------------------------------------------------------
    2. ; DAC Samples Table
    3. ; ---------------------------------------------------------------
    4. PCM_Table:
    5.         DAC_Entry       $19, DAC1KICK, pcm                      ; $81   - Kick
    6.         DAC_Entry       $04, DAC2SNARE, pcm                     ; $82   - Snare
    7.         DAC_Entry       $08, DAC3CLAP, pcm                      ; $83   - Clap
    8.         DAC_Entry       $0A, DAC4SCRATCH, pcm                   ; $84   - Scratch
    9.         DAC_Entry       $1D, DAC5TIMPANI, pcm                   ; $85   - Timpani
    10.         DAC_Entry       $0C, DAC6TOM, pcm                       ; $86   - Tom
    11.         DAC_Entry       $1D, DAC7BONGO, pcm                     ; $87   - Bongo
    12.     DAC_Entry       $14, DAC5TIMPANI, pcm                   ; $88   - Hi-Timpani
    13.     DAC_Entry       $17, DAC5TIMPANI, pcm                   ; $89   - Mid-Timpani
    14.     DAC_Entry       $1E, DAC5TIMPANI, pcm                   ; $8A   - Low-Timpani
    15.     DAC_Entry       $1F, DAC5TIMPANI, pcm                   ; $8B   - Floor-Timpani


    You see here, the pitch/tempo of these instruments differs between Sonic 1 and 2, these new values can be found under byte_71CC4 in Sonic 2 Clone Driver.asm. With that out of the way, save and build.

    Alright, we're in business now; all instruments ported, everything sounds okay as far as the title screen and Emerald Hill go, I guess we're done here! Nope, we've still got the problem of getting the DPCMs working again, and give Metropolis Zone a listen. Yep, it's still there. Even though DAC4SCRATCH is included and is in the right place.



    —FIXING DPCM—
    So, remember PCM_Table? It's still there, double defining and double including sound samples, let's get rid of it.

    Mosey on over to PCM_Table and delete or comment it out, the entire table:

    Now move to the end of Sonic 2 Clone Driver.asm and find this:

    Code (ASM):
    1.         align $8000
    2. DAC1: BINCLUDE sound\dac1d.bin
    3.         even
    4. DAC2: BINCLUDE sound\dac2d.bin
    5.         even
    6. DAC3: BINCLUDE sound\dac3d.bin
    7.         even
    8. DAC4: BINCLUDE sound\dac4d.bin
    9.         even
    10. DAC5: BINCLUDE sound\dac5d.bin
    11.         even
    12. DAC6: BINCLUDE sound\dac6d.bin
    13.         even
    14. DAC7: BINCLUDE sound\dac7d.bin
    15.         even


    Delete it.

    So what about Calculate_PCM? It's still pointing to PCM_Table! Delete that too, along with the Calc_PCM2 found below it. But now we've got to remove the references to Calculate_PCM to avoid 'symbol undefined' errors. Search and delete all instances of "jsr Calculate_PCM". From what I can tell, this is a part of JMan's DAC driver, which was integrated into the Clone Driver a while back. It and Mega PCM don't get along.

    That should do it. Save, build, and test. Mega PCM should now be fully working, even Metropolis is cooperating! Now for the part we've all been waiting for: Efficiency(!) Change MegaPCM.asm to use the "compressed" samples (DAC1KICK.BIN, etc) by changing the "raw"s in the Sample Files table to "bin"s, and the "pcm"s in the Samples Table to "dpcm"s.

    Upon saving and building, the DPCMs should now play ungarbled, mission accomplished!

    As a note, playing samples such as the Sonic CD 1up "yes" come out scratchy, so Vladikcomper's optimisations will have to be ported. Guess what we're doing next?



    —REMOVING THE PITCH-SHIFTERS—
    Nope. Remember when the additional timpani pitches stopped working? We somehow left these two functions intact but broken: the remnants still handle alternate tom and bongo pitches. As with the timpani, we must add these to the Samples Table and eliminate the remnants. We'll start with familiar ground and begin with the former.

    Look for byte_71CC4 again, and you'll find this:

    Code (ASM):
    1. byte_71CC4: dc.b $14, $17, $1E, $1F
    2. Tom_71CC4: dc.b $4, $7, $A, $FF
    3. Bongo_71CC4: dc.b $A, $D, $14, $FF


    The first list contains the timpani tempos we used earlier, the second contains the tom tempos, and the third holds the bongo tempos. Adding this to the Samples Table should give you this:

    Code (ASM):
    1.         DAC_Entry       $19, DAC1KICK,      dpcm    ; $81   - Kick
    2.         DAC_Entry       $04, DAC2SNARE,     dpcm    ; $82   - Snare
    3.         DAC_Entry       $08, DAC3CLAP,      dpcm    ; $83   - Clap
    4.         DAC_Entry       $0A, DAC4SCRATCH,   dpcm    ; $84   - Scratch
    5.         DAC_Entry       $1D, DAC5TIMPANI,   dpcm    ; $85   - Timpani
    6.         DAC_Entry       $0C, DAC6TOM,       dpcm    ; $86   - Tom
    7.         DAC_Entry       $1D, DAC7BONGO,     dpcm    ; $87   - Bongo
    8.     DAC_Entry       $14, DAC5TIMPANI,   dpcm    ; $88   - Hi-Timpani
    9.     DAC_Entry       $17, DAC5TIMPANI,   dpcm    ; $89   - Mid-Timpani
    10.     DAC_Entry       $1E, DAC5TIMPANI,   dpcm    ; $8A   - Low-Timpani
    11.     DAC_Entry       $1F, DAC5TIMPANI,   dpcm    ; $8B   - Floor-Timpani
    12.     DAC_Entry   $04, DAC6TOM,       dpcm    ; $8C   - Hi-Tom
    13.     DAC_Entry   $07, DAC6TOM,       dpcm    ; $8D   - Mid-Tom
    14.     DAC_Entry   $0A, DAC6TOM,       dpcm    ; $8E   - Low-Tom
    15.     DAC_Entry   $FF, DAC6TOM,       dpcm    ; $8F   - Floor-Tom
    16.     DAC_Entry   $0A, DAC7BONGO,     dpcm    ; $90   - Hi-Bongo
    17.     DAC_Entry   $0D, DAC7BONGO,     dpcm    ; $91   - Mid-Bongo
    18.     DAC_Entry   $14, DAC7BONGO,     dpcm    ; $92   - Low-Bongo
    19.     DAC_Entry   $FF, DAC7BONGO,     dpcm    ; $93   - Floor-Bongo


    Hang on, why are the floor entries $FF? The most likely answer is that the floor entries borrow the tempos of the default tom and bongo entries.

    Code (ASM):
    1.         DAC_Entry       $0C, DAC6TOM,       dpcm    ; $86   - Tom
    2.         DAC_Entry       $1D, DAC7BONGO,     dpcm    ; $87   - Bongo


    These ones.

    In any case, they sound better than $FF so let's replace them with those.

    Code (ASM):
    1.         DAC_Entry       $19, DAC1KICK,      dpcm    ; $81   - Kick
    2.         DAC_Entry       $04, DAC2SNARE,     dpcm    ; $82   - Snare
    3.         DAC_Entry       $08, DAC3CLAP,      dpcm    ; $83   - Clap
    4.         DAC_Entry       $0A, DAC4SCRATCH,   dpcm    ; $84   - Scratch
    5.         DAC_Entry       $1D, DAC5TIMPANI,   dpcm    ; $85   - Timpani
    6.         DAC_Entry       $0C, DAC6TOM,       dpcm    ; $86   - Tom
    7.         DAC_Entry       $1D, DAC7BONGO,     dpcm    ; $87   - Bongo
    8.     DAC_Entry       $14, DAC5TIMPANI,   dpcm    ; $88   - Hi-Timpani
    9.     DAC_Entry       $17, DAC5TIMPANI,   dpcm    ; $89   - Mid-Timpani
    10.     DAC_Entry       $1E, DAC5TIMPANI,   dpcm    ; $8A   - Low-Timpani
    11.     DAC_Entry       $1F, DAC5TIMPANI,   dpcm    ; $8B   - Floor-Timpani
    12.     DAC_Entry   $04, DAC6TOM,       dpcm    ; $8C   - Hi-Tom
    13.     DAC_Entry   $07, DAC6TOM,       dpcm    ; $8D   - Mid-Tom
    14.     DAC_Entry   $0A, DAC6TOM,       dpcm    ; $8E   - Low-Tom
    15.     DAC_Entry   $0C, DAC6TOM,       dpcm    ; $8F   - Floor-Tom
    16.     DAC_Entry   $0A, DAC7BONGO,     dpcm    ; $90   - Hi-Bongo
    17.     DAC_Entry   $0D, DAC7BONGO,     dpcm    ; $91   - Mid-Bongo
    18.     DAC_Entry   $14, DAC7BONGO,     dpcm    ; $92   - Low-Bongo
    19.     DAC_Entry   $1D, DAC7BONGO,     dpcm    ; $93   - Floor-Bongo


    With that done, we can remove the pitch-shifting code.

    Code (ASM):
    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.         cmp.b   #0,($FFFFFF3A).w
    10.         bgt.s   locret_71CAA
    11.         cmp.b   #$8C,d0
    12.         bge.s   loc_71CAC
    13.         move.b  d0,($A01FFF).l
    14.  
    15.  
    16. locret_71CAA:
    17.         rts


    Our problem stems from loc_71C88, seen here. It checks for a DAC value above $8C, and if so, branches to a subroutine which handles each instrument and pitch. This isn't the first we've seen of this system: A smaller version can be found in Sonic 1, though it only handles the timpani. Anyway, this is now redundant, and soon, it will become a hindrance, so we'd best remove it. We shall begin by removing the branch, also, it might be worth removing the one above it too, it check an unused RAM address that's never written to, it's useless. You should be left with this:

    Code (ASM):
    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.         move.b  d0,($A01FFF).l
    10.  
    11.  
    12. locret_71CAA:
    13.         rts


    Now to finally be rid of this code. Starting with loc_71CAC, we shall remove the code before reaching its end at sub_71CCA.

    Find and delete this code:

    Code (ASM):
    1. loc_71CAC:
    2.         cmpi.b  #$8C,d0
    3.         beq.w   Tom_71CAC
    4.         cmpi.b  #$8D,d0
    5.         beq.w   Tom_71CAC
    6.         cmpi.b  #$8E,d0
    7.         beq.w   Tom_71CAC
    8.         cmpi.b  #$8F,d0
    9.         beq.w   Bongo_71CAC
    10.         cmpi.b  #$90,d0
    11.         beq.w   Bongo_71CAC
    12.         cmpi.b  #$91,d0
    13.         beq.w   Bongo_71CAC
    14.         move.l  d0,-(sp)
    15.         move.b  #$85,d0
    16.         move.l  (sp)+,d0
    17.         subi.b  #$88,d0
    18.         move.b  byte_71CC4(pc,d0.w),d0
    19.         move.b  d0,($A00224).l
    20.         move.b  #$85,($A01FFF).l
    21.         rts
    22.  
    23. Tom_71CAC:
    24.         move.l  d0,-(sp)
    25.         move.b  #$86,d0
    26.         move.l  (sp)+,d0
    27.         subi.b  #$8C,d0
    28.         move.b  Tom_71CC4(pc,d0.w),d0
    29.         move.b  d0,($A0022C).l
    30.         move.b  #$86,($A01FFF).l
    31.         rts
    32.  
    33. Bongo_71CAC:
    34.         move.l  d0,-(sp)
    35.         move.b  #$87,d0
    36.         move.l  (sp)+,d0
    37.         subi.b  #$8F,d0
    38.         move.b  Bongo_71CC4(pc,d0.w),d0
    39.         move.b  d0,($A00234).l
    40.         move.b  #$87,($A01FFF).l
    41.         rts
    42.  
    43. NoBend_71CAC:
    44.         move.b  d0,d1
    45.         subi.b  #7,d1
    46.         move.b  d1,d0
    47.         move.b  d0,($A01FFF).l
    48.         bra.w   locret_71CAA
    49.  
    50. ; End of function sub_71C4E
    51.  
    52. ; ===========================================================================
    53. byte_71CC4: dc.b $14, $17, $1E, $1F
    54. Tom_71CC4: dc.b $4, $7, $A, $FF
    55. Bongo_71CC4: dc.b $A, $D, $14, $FF


    With that finally eliminated, we can move on to Vladikcomper's optimisations!



    —OPTIMISING Z80 STOPS—
    Follow Vladikcomper's guide with the following changes:

    • Apply guide to Sonic 2 Clone Driver.asm.
    • You only have to define the waitYM macro.
    • To fix an error with the original guide, comment out or remove the three lines below the ones detailed in the first part of the guide. Not doing so will cause your ROM to hang upon booting, infinitly checking for something that will never happen.

      Code (ASM):
      1. sub_71B4C:
      2. ;       move.w  #$100,($A11100).l ; stop the Z80
      3. ;       nop
      4. ;       nop
      5. ;       nop
      6.  
      7. loc_71B5A:                              ; <--   Delete
      8.         btst    #0,($A11100).l      ; Is the z80 busy?  ; <--   Delete
      9.         bne.s   loc_71B5A       ; If so, wait       ; <--   Delete



    —OPTIMISING VBLANK ROUTINES—
    PCM playback quality is dragged down by unnecessary Z80 interruptions. Here, we'll see to removing these. Most of them are in V-Int, though there are notable instances elsewhere.

    First, search for this:

    Code (ASM):
    1. dma68kToVDP Sprite_Table_2,VRAM_Sprite_Attribute_Table,VRAM_Sprite_Attribute_Table_Size,VRAM


    You should find it sandwiched between a stop and a start. Delete these first two. That covers H-Int

    Now, onto V-Int.

    • VintSub0 (if you haven't already deleted them while removing sndDriverInput)
    • loc_4C4, the other at loc_54A
    • Vint0_noWater
    • VintSub14
    • VintSub8, the other is at loc_748
    • Vint10_specialStage, the other at loc_86E
    • VintSubA, with the other way over above loc_9B8
    • VintSub1A
    • VintSubC, with the other being at loc_BD6
    • VintSub18
    • VintSub16
    • Do_ControllerPal, the other at loc_EFE


    Now for the rest.

    • JoypadInit
    • ClearScreen
    • EndingSequence



    —REFORMATTING—
    Slapping this all together, saving, and building will produce some... odd results. Turns out we were wrong. Our table is inaccurate. Very inaccurate. Really, the toms, timpani, and bongos are all over the place. Listen to the options theme, the act complete theme, MCZ 2 player theme, it's ridiculous. Our current table is this:

    Code (ASM):
    1.         DAC_Entry       $19, DAC1KICK,      dpcm    ; $81   - Kick
    2.         DAC_Entry       $04, DAC2SNARE,     dpcm    ; $82   - Snare
    3.         DAC_Entry       $08, DAC3CLAP,      dpcm    ; $83   - Clap
    4.         DAC_Entry       $0A, DAC4SCRATCH,   dpcm    ; $84   - Scratch
    5.         DAC_Entry       $1D, DAC5TIMPANI,   dpcm    ; $85   - Timpani
    6.         DAC_Entry       $0C, DAC6TOM,       dpcm    ; $86   - Tom
    7.         DAC_Entry       $1D, DAC7BONGO,     dpcm    ; $87   - Bongo
    8.     DAC_Entry       $14, DAC5TIMPANI,   dpcm    ; $88   - Hi-Timpani
    9.     DAC_Entry       $17, DAC5TIMPANI,   dpcm    ; $89   - Mid-Timpani
    10.     DAC_Entry       $1E, DAC5TIMPANI,   dpcm    ; $8A   - Low-Timpani
    11.     DAC_Entry       $1F, DAC5TIMPANI,   dpcm    ; $8B   - Floor-Timpani
    12.     DAC_Entry   $04, DAC6TOM,       dpcm    ; $8C   - Hi-Tom
    13.     DAC_Entry   $07, DAC6TOM,       dpcm    ; $8D   - Mid-Tom
    14.     DAC_Entry   $0A, DAC6TOM,       dpcm    ; $8E   - Low-Tom
    15.     DAC_Entry   $0C, DAC6TOM,       dpcm    ; $8F   - Floor-Tom
    16.     DAC_Entry   $0A, DAC7BONGO,     dpcm    ; $90   - Hi-Bongo
    17.     DAC_Entry   $0D, DAC7BONGO,     dpcm    ; $91   - Mid-Bongo
    18.     DAC_Entry   $14, DAC7BONGO,     dpcm    ; $92   - Low-Bongo
    19.     DAC_Entry   $1D, DAC7BONGO,     dpcm    ; $93   - Floor-Bongo
    20.  
    21.  
    22. MegaPCM_End:


    SMPS2ASM gives us the answer (you could probably find the answer in s2.sounddriver.asm as well), look at the DAC equates.

    Code (ASM):
    1.     elseif SonicDriverVer==2
    2.         enum dKick=$81,dSnare,dClap,dScratch,dTimpani,dHiTom,dVLowClap,dHiTimpani,dMidTimpani
    3.         enum dLowTimpani=dMidTimpani+1,dVLowTimpani,dMidTom,dLowTom,dFloorTom,dHiClap
    4.         enum dMidClap=dHiClap+1,dLowClap


    Note that all clap entries but the first are actually bongo entries. Applying this to our Samples Table gives us:

    Code (ASM):
    1.         DAC_Entry       $19, DAC1KICK,      dpcm    ; $81   - Kick
    2.         DAC_Entry       $04, DAC2SNARE,     dpcm    ; $82   - Snare
    3.         DAC_Entry       $08, DAC3CLAP,      dpcm    ; $83   - Clap
    4.         DAC_Entry       $0A, DAC4SCRATCH,   dpcm    ; $84   - Scratch
    5.         DAC_Entry       $1D, DAC5TIMPANI,   dpcm    ; $85   - Timpani
    6.     DAC_Entry   $04, DAC6TOM,       dpcm    ; $86   - Hi-Tom
    7.     DAC_Entry   $FF, DAC7BONGO,     dpcm    ; $87   - Low-Bongo
    8.     DAC_Entry       $14, DAC5TIMPANI,   dpcm    ; $88   - Hi-Timpani
    9.     DAC_Entry       $17, DAC5TIMPANI,   dpcm    ; $89   - Mid-Timpani
    10.     DAC_Entry       $1E, DAC5TIMPANI,   dpcm    ; $8A   - Mid-Low-Timpani
    11.     DAC_Entry       $1F, DAC5TIMPANI,   dpcm    ; $8B   - Low-Timpani
    12.     DAC_Entry   $07, DAC6TOM,       dpcm    ; $8C   - Mid-Tom
    13.     DAC_Entry   $0A, DAC6TOM,       dpcm    ; $8D   - Mid-Low-Tom
    14.     DAC_Entry   $FF, DAC6TOM,       dpcm    ; $8E   - Low-Tom
    15.     DAC_Entry   $0A, DAC7BONGO,     dpcm    ; $8F   - Hi-Bongo
    16.     DAC_Entry   $0D, DAC7BONGO,     dpcm    ; $90   - Mid-Bongo
    17.     DAC_Entry   $14, DAC7BONGO,     dpcm    ; $91   - Mid-Low-Bongo
    18. ;       DAC_Entry       $0C, DAC6TOM,       dpcm    ; $XX   - Tom   ; Unneeded
    19. ;       DAC_Entry       $1D, DAC7BONGO,     dpcm    ; $XX   - Bongo ; Unneeded
    20.  
    21.  
    22. MegaPCM_End:


    With this we no longer need those two tom and bongo entries from the top, turns out they were unused and unneeded the entire time, well, unless you count the floor entries mimicking them. With that done, we are now finished. You can add samples and play them back with no scratchiness.

    ...

    Oh wait.



    —PLAYING SAMPLES—
    Riiiiight, the samples. One last bit, when using samples in this manner:

    Code (ASM):
    1.     moveq   #$FFFFFF84,d0
    2.     jsr     PlaySample


    Make the moveq value byte length, so you have:

    Code (ASM):
    1.     moveq   #$84,d0
    2.     jsr     PlaySample


    Leaving it the way it is will just give you an error.

    Information stream:
    Timpani Troubles
    EDIT:Noticed some missing (Timpani?) notes in the act complete music, Sonic 1 Mega PCM had separate instances of Timpani defined with unique pitches, and upon trying to add a sample of my own in both slot 88 and slot 8C (with dc.l 0,0 filling the 88, 89, 8A, and 8B slots), the first missing note would play the sample, Stock Sonic 2 Clone Driver doesn't appear to manage it this way, looking into alternate pitches. This makes the 1up jingle DAC-less, as its entire DAC library consists of these missing notes.

    EDIT2: I copied the values found in the Sonic 1-ready MegaPCM.asm to the Sonic 2-compatable MegaPCM.asm and increased each entry's pitch by two to match the main Timpani sample's. This fixed all missing samples, however, I am unsure as to whether the pitch is correct, I don't have much of an ear for these things. Pushing new information to guide.

    EDIT6: There are now some missing notes in the options and level select theme, this is brought on by the Z80 stop optimisations. Great! Optimisations have been relocated until fix is found.

    EDIT8: Everything related to Calculate_PCM has been removed. This has fixed the above problem. Calculate PCM was a workaround for the missing instrument, the timpani pitches, the tom, and the bongo, an alternative to simply adding them to the DAC entry list as we did with the timpani. Turns out we didn't remove it fully. It was enough to get the scratch working, but the optimisations dealt the killing blow to the undead Calculate_PCM, and the tom and bongo samples simply came out mute. Adding information on fully removing Calculate_PCM, along with re-adding the optimisations guide complete with a new section, now.

    EDIT7: While adding HG comments to Sonic 2 Clone Driver.asm, I discovered the true timpani pitches; $14, $17, $1E, and $1F. Also found are the true names of instruments BOP and COWBELL, which have been identified as Tom and Bongo. Findings pushed to guide.
    MD.crash
    EDIT3: It would appear that I broke something, as DAC now crashes MD.emu, while Sonic 1 (outfitted with Mega PCM) works fine. Fusion works though. The most interesting part is that MD.emu works with ROMs where the DPCM hasn't been fixed, looking into Sonic 1 Calculate_PCM equivalent for fix (EDIT: This was before I was aware that the Clone Driver used Jman's DAC driver, which is the origin of Calculate_PCM.)

    EDIT4: No equivalent found. Investigating how to eliminate Calculate_PCM.

    EDIT5: Fix was pretty simple; remove all references to Calculate_PCM, which was as easy as just commenting out the "jsr Calculate_PCM"s doted around Sonic 2 Clone Driver.asm, pushing new info to guide. This eliminates a good chunk of the "Fixing DPCM" section.
    Optimizing Z80 stops in SMPS
    EDIT6: I've ported the optimisations to allow high quality sample playback. Information pushed to guide.

    EDIT6: There are now some missing notes in the options and level select theme, this is brought on by the Z80 stop optimisations. Great! Optimisations have been relocated until fix is found.

    EDIT8: Everything related to Calculate_PCM has been removed. This has fixed the above problem. Calculate PCM was a workaround for the missing instrument, the timpani pitches, the tom, and the bongo, an alternative to simply adding them to the DAC entry list as we did with the timpani. Turns out we didn't remove it fully. It was enough to get the scratch working, but the optimisations dealt the killing blow to the undead Calculate_PCM, and the tom and bongo samples simply came out mute. Adding information on fully removing Calculate_PCM, along with re-adding the optimisations guide complete with a new section, now

    Original post:
    I've got it! Sonic 2 Clone Driver DPCM functionality regained!

    Okay, so I've been fooling around with this for a while but gave up when logic died on me: I had ported Mega PCM to the Clone Driver and applied its PCM_Table to MegaPCM.asm, allowing me full DAC accuracy and instruments, but, as has been said before, the samples could only play in raw PCM, I just worked around this by "decompressing" (I use the marks because they aren't really compressed, not in the traditional sense anyway) all of the samples and moving on... Then I found out that one sample had really messed up: the 'scratch', featured in Metropolis Zone's music, it was the same static-y noise heard upon trying to play a DPCM sample in the port's current, buggy state, except this sample was standard uncompressed 8-bit stereo PCM just like all the others, so what happened? This confused me to the point of abandoning the project and deeming Mega PCM unportable by my own means, as I had tried every conceivable method of fixing it, all to no avail. However, a month later, curiosity got the better of me and I had one final shot at it. What are the chances that I fix it first try, and in a matter of seconds, no less? Well, there's newbie luck for you.

    Here's a long and dragged out how-to!
     
  6. redquebec

    redquebec

    Member
    38
    0
    0
    Thank you vlad, it's been a while since the DAC drivers didn't got some love. Amazing work. Thanks again
     
  7. Clownacy

    Clownacy

    Tech Member
    797
    29
    28
    So, while working with my driver, I found myself making a pair of size optimisations that don't affect speed to Mega PCM's code:

    • Removed two of the three 'di' instructions at the beginning of the driver.
    • Moved DPCM_DeltaArray from address 200h to 100h. This was done by moving DPCM_DeltaArray and its align to above InitBankSwitching. This reduces the amount of padding needed for the align.

    While DPCM_DeltaArray's padding negates the space saved by the removal of the 'di's, the resulting binary's size is reduced from 210h bytes to 1EEh bytes. Size can also be reduced by compressing the binary file and making SoundDriverLoad decompress the data to Z80 RAM. Flamewing's koscmp works well for compressing.

    EDIT: Actually, it seems I can take this even further:

    At the end of both Process_PCM and Process_DPCM is this code:

    Code (Text):
    1.     ; Quit playback loop
    2. +   exx
    3.     jp  Event_EndPlayback
    It's the exact same between the two, and doesn't call back into their respective routines. So, we can make the driver use only one copy of this code, and we can make it occupy the space otherwise used by DPCM_DeltaArray's padding.

    So, for example, above DPCM_DeltaArray, you can have this:

    Code (Text):
    1. ; ---------------------------------------------------------------
    2. ; Quit playback loop (used by Process_PCM/Process_DPCM)
    3. ; ---------------------------------------------------------------
    4.  
    5. QuitPlaybackLoop:
    6.     exx
    7.     jp  Event_EndPlayback
    And, in Process_PCM/Process_DPCM, you can replace this:

    Code (Text):
    1.     jp  p,+++           ; 10    ; if yes, quit playback loop
    ...with this:

    Code (Text):
    1.     jp  p,QuitPlaybackLoop  ; 10    ; if yes, quit playback loop
    And you can delete both of these:

    Code (Text):
    1.     ; Quit playback loop
    2. +   exx
    3.     jp  Event_EndPlayback
    Doing this will reduce the driver's size from 1EEh bytes to 1E6h bytes.

    EDIT2: Here's another optimisation. This improves the speed and size of LoadDAC.

    Move this...

    Code (Text):
    1.     ld  b,0h
    ...above this:

    Code (Text):
    1.     ld  (hl),0h
    And then make both that line, and the 'ld h,0h' use register b instead of using the 0h. Doing this should save space and cycles. Unfortunately, the space freed will be padded by the align, and the optimisation is not in a cycle-intensive area.
     
  8. Advanced?

    Advanced?

    Member
    29
    1
    3
    Sonic 1 Hack
    Links are down again
     
    • Agree Agree x 1
    • Funny Funny x 1
    • List
  9. Ralakimus

    Ralakimus

    i don't care anymore Tech Member
    550
    156
    43
    Hell
  10. Rrose80149

    Rrose80149

    Member
    23
    0
    1
    How do I get the Sonic 3 & Knuckles drums to play for Sonic 1 & Sonic 2?
     
  11. Joseph A. Rose

    Joseph A. Rose

    Member
    13
    0
    1
    Yeah. How can my brother Ronald and I get the Sonic 3 & Knuckles Drums to play for Sonic 1 and Sonic 2?
     
  12. Inferno

    Inferno

    Member
    10
    3
    3
    Sonic 1 Definitive
    Well, if you actually read in detail the original post...

    If you've installed this driver, everything but the timpani are already from S3, and the timpani is easy enough to get if you even have a S3 disasm.
    Oh, and if you need the sample rates, oh, I don't know, search Google, or, if you have a SSRG account, check the Tutorial Archives.
     
  13. vexatious

    vexatious

    Member
    34
    2
    8
    This is great stuff! This would probably go good with Neto D.O.S. or similar, or other diy development.

    I'm assuming this muxes both the z80 and core yamaha but I didn't quite understand how many channels are mixed...? Is this intended to leave space for GEMS or similar? Thanks.
     
  14. nineko

    nineko

    I am the Holy Cat Tech Member
    I don't mean to sound rude or anything, but... your post doesn't make sense at all, not the slightest bit, you're confusing at least three different things.

    This driver is an improved variant of the SMPS driver, GEMS is another driver altogether and it has nothing to do with this. In theory nothing prevents you from having two (or more) drivers in the same ROM, but as rule of thumb it would be extremely silly to have them running at the same time. Also, why are you interested about GEMS? The only Sonic game which uses GEMS is Spinball.

    The Z80 isn't playing music itself, it's only a CPU with no audio output. Other than the YM2612, there is an SN76489 (also known as PSG, programmable sound generator), and both audio chips can be controlled by both the Z80 and the M68000.

    For the sake of documentation, the YM2612 has 6 channels, and the SN76489 has 4 channels, but all of them are always mixed together, that's a hardware feature and you literally can't do otherwise.

    Finally, the Neto thing is used for flashcarts, and, again, it isn't related to this at all. You can burn a Sonic hack on a flashcart, but that's pretty much the only link between these two things.

    Please redo from start.

    (edit: reworded a sentence for clarity)
     
    Last edited: Apr 8, 2020
    • Agree Agree x 3
    • Like Like x 1
    • List
  15. vexatious

    vexatious

    Member
    34
    2
    8
    Geeze you make me angry nineko... I mean, am I supposed to mux marijuana and tobacco and blow it up someone's cornholio or something like that?

    edit:
    I'm interested in Gems because it's usable with msdos. I could possibly demo a custom sound set with timidity and use it in GEMS and mux it later with the richo or pwm.
     
    Last edited: Apr 8, 2020
  16. Inferno

    Inferno

    Member
    10
    3
    3
    Sonic 1 Definitive
    Even if you are interested in GEMS, this sure isn't the right topic for it. This is a topic about MegaPCM, a modified Sonic 1 sound driver, not even remotely related to GEMS.

    Please find a more suitable thread to talk about GEMS, maybe you will get a less "what are you talking about" response then.
     
    • Agree Agree x 5
    • Like Like x 1
    • List
  17. Ralakimus

    Ralakimus

    i don't care anymore Tech Member
    550
    156
    43
    Hell
    @vexatious While it's probably not impossible to integrate Mega PCM with GEMS, there is a problem, in which I'll explain later.

    The Genesis can choose to run a sound driver on either the main 68000 CPU or the Z80 CPU. The Z80 CPU was mainly included to carry the load of sound driver running off of the 68000, but it's not required to be used. The YM2612 can sacrifice its 6th FM channel for a PCM channel, in which PCM data must be continually streamed by a CPU. This is the only part of the sound hardware that does this kind of thing, as all of the other sound channels are mixed in with this PCM channel via hardware. In this case, it's a really bad idea to do that on the 68000, since it also has to also run the game, so PCM streaming quality would end up being typically bad, so that's where the Z80 can come in. Without having to run anything too heavy, the Z80 can stream PCM data without many issues (not accounting for hardware issues such as DMAing data from ROM to VDP memory while the Z80 tries to access 68000 memory). Even if the main sound driver is ran on the Z80, PCM streaming quality can be deemed "acceptable", because it's just the sound driver that it's running, and not the entire game.

    Sonic 1 in particular chooses to run its sound driver on the 68000, with the Z80 left to stream PCM samples. However, the stock PCM driver supplied with Sonic 1 is pretty limited, since PCM samples are to be stored in the Z80's limited RAM space, and it has to be stored in a 4-bit DPCM format (except for the SEGA chant, but that's a special case with its own limitations).

    The problem that I mentioned before? Well, Mega PCM seems to be designed as just a replacement for the Sonic 1 PCM driver, to make setting up PCM samples easier, or at the very least, just a standalone PCM driver to be paired with some other 68000 sound driver. Its code continually streams PCM data from ROM to the YM2612's PCM channel without it being interrupted with the burden of running a full sound driver. If you want to get something like this in a full Z80 sound driver such as GEMS or even SMPS Z80, then sacrifices and changes will have to be made, but I don't think it's impossible.

    For one, because the Z80 will have to be running a sound driver alongside PCM streaming, PCM playback quality is generally gonna be cut down. You'll also have to get clever with how you stream your PCM data. You go with the easy route and just stream PCM data continuously in the main routine, and then just have the sound driver run on VBlank or when a YM timer is finished, but then what you'd get is consistent playback quality during the regular loop, but then a period of nothing being streamed while the sound driver gets updated. It may be worth checking out how GEMS does it. IIRC it integrates PCM streaming inside the sound driver update code, keeping PCM playback at least somewhat more consistent.

    Hopefully this helps answer your inquiry regarding Mega PCM and even GEMS.
     
  18. vexatious

    vexatious

    Member
    34
    2
    8
    Thanks for the response Ralakimus. It's very informative and helpful. So basically it sounds like this MegaPCM is purely for PCM playback from the core 68000 with yamaha fm.

    edit:
    MegaPcm.asm has the sample table for z80... It still confuses me a little why this is here. Is this merely for compatibility with Sonic hacks? Thanks.
     
    Last edited: Apr 12, 2020
  19. Ralakimus

    Ralakimus

    i don't care anymore Tech Member
    550
    156
    43
    Hell
    I meant that it streams to the YM2612 from the Z80 while the 68000 is left to do everything else, like how it was in the original PCM driver for Sonic 1. The 68000 simply doesn't have enough processing time to properly stream PCM samples, due to the fact it has to run the game engine. The Z80 takes care of that. It's just that there's also sound drivers that run alongside PCM streaming on the Z80, which does affect the quality of the sample playback, but not enough to be redeemed "unacceptable".

    Mega PCM acts as a replacement for that to make setting up custom samples much easier in Sonic 1 hacks with less restrictions, but of course, can be installed alongside any other 68000 based sound driver.

    I guess I should also clarify that what I mean by "sound driver" in this instance is a driver that parses music tracker data and sets up the sound hardware to play notes and stuff.
     
    Last edited: Apr 12, 2020
  20. MarkeyJester

    MarkeyJester

    ♡ ! Resident Jester
    May I ask vexatious; out of curiosity, you appear to need something sound driver related, but haven't quite specified what it is you want, and it seems you and everyone above have a communication barrier at hand, and are misunderstanding one another.

    What is it you are looking for specifically? Are you looking for a specific sound driver which fits a strict criteria for perhaps a project of yours?