How to install UltraDMAQueue into Sonic 1 (ASM68K)

Discussion in 'Tutorials' started by DeltaWooloo, Mar 24, 2023.

  1. DeltaWooloo

    DeltaWooloo The noob next door Member

    Joined:
    Aug 7, 2019
    Messages:
    375
    Edit: updated the link. Most likely gonna fine-tune the guide though using what OrionNavattan provided me. For now, you newbies can use this at your own will. =)

    I'm not going to go into detail technical specs of the new DMA queue besides the fact that it's heavily optimized which surpasses Sonic 2's and Sonic and Knuckles's DMA queue by a long shot. If you want to know more about what it does, click on this link. This tutorial targets the ASM68K GitHub disassembly but should work with any other disassembly if you know what you're doing. This has been tested on Hivebrain 2005 however idk about Hivebrain's modern disassemblies at this time of writing. If the guide works with that disassembly in mind, let me know. AS assemblers may follow this guide, but it's best if you use the link above instead of the one below.

    Before we get started, if you already have Sonic 2's DMA queue installed because you ported the spindash, then you'll have to replace the code with what I'm about to give you. There are a few steps that you can skip if you already changed a few lines here and there, but it's best if you double-check if you added the code in. (trust me, it's worth checking along the way because you'll definitely have to change a few lines here and there)

    Firstly, we're going to add the DMA Queue itself. Let's create a file called DMA Queue.asm. Here's the version that'll work under ASM68K disassemblies in mind. (click me). I think it's based on a slightly older version of the DMA Queue however I'm not entirely sure at the moment.

    From there, you can save the file to your disassembly. I'll place it in the "_inc" folder in my case. The next step is to include the file in your disassembly so let's open up sonic.asm and make a line that includes the aforementioned .asm file. it doesn't matter where you put it exactly although I recommend placing it above the line that includes the Nemesis Decompression file like so:
    Code:
            include    "_inc\DMA Queue.asm"
            include    "_inc\Nemesis Decompression.asm"
    Before we do anything else in sonic.asm, we need to understand the fact that flamewing's DMA queue is only recognized by AS assemblers and since we're dealing with an ASM68K assembler, we need to make a few changes in order to get the file working. If you're using an AS disassembly, you can skip this section. Above your added line, insert this:
    Code:
        pusho    ; buffer local label symbol config
        opt ws+  ; change local label symbol to '.'
    and below it:
    Code:
        popo    ; buffer local label symbol config    
    So you should get this:
    Code:
        pusho    ; buffer local label symbol config
        opt ws+  ; change local label symbol to '.'
            include    "_inc\DMA Queue.asm"
        popo    ; buffer local label symbol config        
    The first two lines of code that we added will make sure the default labelling scheme would use dots as prefixes than @. "popo" will revert the local label to @ so no, it won't affect the rest of your disassembly.
    (AS disassembly users, come back) If you check the code, you can see that VDP_Command_Buffer and VDP_Command_Buffer_Slot aren't defined. So let's define them, shall we? =V
    Go to Variables.asm and insert this:
    Code:
    VDP_Command_Buffer:    equ    $FFFFC800
    VDP_Command_Buffer_Slot:    equ    VDP_Command_Buffer+7*$12*2
    If you done this correctly, the ROM should build although we need to initalize the DMA queue and put it into good use. Firstly, let's go to GameInit and above:
    Code:
            bsr.w    VDPSetupGame
    insert this:
    Code:
            bsr.w    InitDMAQueue
    This will load the DMA queue upon startup. Next, let's replace a bunch of VBlank junk that makes the game load Sonic's sprites using a shit-ton of RAM ($200 of RAM between $FFFFC900 to $FFFFCAFF).
    Find these four lines of code:
    Code:
            tst.b    (f_sonframechg).w ; has Sonic's sprite changed?
            beq.s    @nochg        ; if not, branch
            writeVRAM    v_sgfx_buffer,$2E0,vram_sonic ; load new Sonic gfx
            move.b    #0,(f_sonframechg).w
    and replace it with:
    Code:
            jsr     ProcessDMAQueue(pc)
    You can find these instances at VBla_08, VBla_0A, VBla_0C and VBla_16. Now let's load the DMA every time the game loads a new game mode. Inset this line:
    Code:
            ResetDMAQueue
    at the following:
    At GM_Sega, GM_Title, GM_Continue, GM_Credits, TryAgainEnd => insert this line under:
    Code:
            bsr.w    ClearScreen
    At Level_ClrVars3 and End_ClrRam3, under:
    Code:
            move.w    (v_hbla_hreg).w,(a6)
    And at loc_47D4 under:
    Code:
            jsr    Hud_Base
    Caution: if you ported Sonic 2's DMA queue (which is the code used from that spindash guide), replace these lines:
    Code:
            clr.w    ($FFFFC800).w
            move.l    #$FFFFC800,($FFFFC8FC).w
    with ResetDMAQueue. They can be found at loc_47D4 and Level_ClrVars3.
    Finally, let's make the game load Sonic's art via DMA. Let's head over to "_incObj/Sonic LoadGfx.asm" and replace everything with this:

    Code:
    ; ---------------------------------------------------------------------------
    ; Sonic    graphics loading subroutine
    ; ---------------------------------------------------------------------------
    ; ||||||||||||||| S U B    R O U T    I N E |||||||||||||||||||||||||||||||||||||||
    Sonic_LoadGfx:                ; XREF: Obj01_Control; et al
            moveq    #0,d0
            move.b    obFrame(a0),d0    ; load frame number
            cmp.b    (v_sonframenum).w,d0 ; has frame changed?
            beq.s    @nochange    ; if not, branch
            move.b    d0,(v_sonframenum).w
            lea    (SonicDynPLC).l,a2 ; load PLC script
            add.w    d0,d0
            adda.w    (a2,d0.w),a2
            moveq    #0,d5
            move.b    (a2)+,d5    ; read "number of entries" value
            subq.w    #1,d5
            bmi.s    @nochange    ; if zero, branch
            move.w    #$F000,d4
            move.l    #Art_Sonic,d6
    @readentry:
            moveq    #0,d1
            move.b    (a2)+,d1
            lsl.w    #8,d1
            move.b    (a2)+,d1
            move.w    d1,d3
            lsr.w    #8,d3
            andi.w    #$F0,d3
            addi.w    #$10,d3
            andi.w    #$FFF,d1
            lsl.l    #5,d1
            add.l    d6,d1
            move.w    d4,d2
            add.w    d3,d4
            add.w    d3,d4
            jsr    (QueueDMATransfer).l
            dbf    d5,@readentry    ; repeat for number of entries
    @nochange:
            rts
    ; End of function Sonic_LoadGfx
    

    From there, you can save, build and test your hack and it should load just fine. If there are any questions related to this, then please let me know.
     
    Last edited: Jun 21, 2023
    Dark Shamil Khan and Hame like this.
  2. Hame

    Hame Peepee Poopoo Member

    Joined:
    Jan 12, 2021
    Messages:
    56
    Location:
    Spain
  3. Devon

    Devon I'm a loser, baby, so why don't you kill me? Member

    Joined:
    Aug 26, 2013
    Messages:
    1,376
    Location:
    your mom
    @DeltaWooloo Yeah, don't hotlink to a post's attachment on another forum.
     
  4. DeltaWooloo

    DeltaWooloo The noob next door Member

    Joined:
    Aug 7, 2019
    Messages:
    375
    Alright, alright, relax. :p

    Don't worry, this wasn't intentional. I must've overlooked it when cross-posting my guide from SonicRetro. Check if it works now.
     
    Last edited: Mar 26, 2023
    Hame likes this.
  5. Hame

    Hame Peepee Poopoo Member

    Joined:
    Jan 12, 2021
    Messages:
    56
    Location:
    Spain
    Now it works, thanks :)
     
    DeltaWooloo likes this.