Converting Art to use DPLCs? (Sonic 2)

Discussion in 'Discussion & Q&A' started by Psi, Nov 20, 2020.

  1. Psi

    Psi Well-Known Member Member

    Joined:
    Dec 20, 2014
    Messages:
    85
    Hello. I'm trying to get a little free space in the VRAM for my game by converting the shields to use DPLCs (so they only need to load one frame at once). How I've got it right now loads the shield okay however:

    [​IMG]

    The shield art is loading four times over in the VRAM, meaning it's taking up MORE room now and overwriting a couple objects like the invincibility stars. Any idea what I'm doing wrong here?

    Here's how I set up the DPLCs for reference by the way:

    Code:
    Obj38_Display:
        lea    (byte_1DBD6).l,a1
        jsr    AnimateSprite
        bsr.w    LoadShieldDynPLC
        jmp    DisplaySprite
    ; ===========================================================================
    
    return_1D976:
        rts
    ; ===========================================================================
    
    JmpTo7_DeleteObject 
        jmp    DeleteObject
    ; ---------------------------------------------------------------------------
    ; Shield pattern loading subroutine
    ; ---------------------------------------------------------------------------
    
    ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    
    ; loc_1D1AC:
    LoadShieldDynPLC:
        moveq    #0,d0
        move.b    mapping_frame(a0),d0                ; load frame number
    ; loc_1D1B2:
    LoadShieldDynPLC_Part2:
        cmp.b    objoff_32(a0),d0
        beq.w    return_ShieldDPLC
        move.b    d0,objoff_32(a0)
        lea    (MapRUnc_Shield).l,a2
        add.w    d0,d0
        adda.w    (a2,d0.w),a2
        move.w    (a2)+,d5
        subq.w    #1,d5
        bmi.s    return_ShieldDPLC
        move.w    #$9740,d4                        ; ****** Here
    ; loc_1D1D2:
    ShPLC_ReadEntry:
        moveq    #0,d1
        move.w    (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
        addi.l    #ArtUnc_Shield_Unc,d1
        move.w    d4,d2
        add.w    d3,d4
        add.w    d3,d4
        jsr    (QueueDMATransfer).l
        dbf    d5,ShPLC_ReadEntry                        ; repeat for number of entries
    
    return_ShieldDPLC:
        rts
     
  2. Jdpense

    Jdpense Custom Title Member

    Joined:
    Jan 2, 2013
    Messages:
    92
    Location:
    No where-ville
    I believe the reason it repeats is due to how the DPLC routine replaces tiles for every piece of a mapping sprite as oppose to just one mapping piece by default. I was able to prevent repeating tiles by loading a shield object art via DPLC with myself before with my own DPLC method. My method works similar to how HUD numbers' uncompressed art is loaded.

    So first, you will need an arranged mappings for my method, which I have right here. Which you should replace this with your current mappings for obj38 ("mappings/sprite/obj38.bin").

    The second I would replace "LoadShieldDynPLC:" routine with this:

    Code:
    ; ---------------------------------------------------------------------------
    ; Shield pattern loading subroutine
    ; ---------------------------------------------------------------------------
    
    ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    
    ; loc_1D1AC:
    LoadShieldDynPLC:
        moveq    #0,d0
        moveq    #0,d1
        moveq    #0,d2
        moveq   #0,d6                              ; clear any cache data from data registers
        lea   (ArtUnc_Shield).l,a1              ; load shield art into address register 1
        lea   (Shield_Tile_Arr).l,a2              ; load shield starting tile array into address register 2
        move.w    #$97C0,d0                          ; load VRAM number
        moveq      #$B,d6                              ; load number of total number of tiles to replace
        move.b    mapping_frame(a0),d1              ; load frame number
      
    LoadShieldDynPLC_Part2:
        lea     ($C00000).l,a6                         ; load VDP control address into address register 6
        lsl.l       #2,d0
        lsr.w    #2,d0
        ori.w    #$4000,d0
        swap    d0                                    ; convert VRAM number to DMA VRAM address
        cmp.b   #6,d1                                ; is the mapping frame at 6?
        beq.w   return_ShieldDPLC                    ; if yes, then end DPLC
        add.w   d1,d1                                ; convert size of fetch number (frame number) to array's index's number(starting tile)
        move.w  (a2,d1.w),d2                        ; transfer word size number data (starting tile) into data register 2
        mulu.w  #$20,d2                                ; convert starting tile's number size into a size for the length of each tile in the art file
      
    ; ------------------------------------------------------------------------------
    ; Loads any Uncompressed Art directly to VDP without the need of a DPLC
    ; Loads into 1 tile of space per loop (rept 8)
    ; ------------------------------------------------------------------------------
                  
    ShPLC_ReadEntry:
        move.l    d0,4(a6)        ; load VRAM DMA into VDP Control
        lea      (a1,d2.w),a3        ; transfer the location of the starting pixels of the current tile into address register 3
        move.l    (a3)+,(a6)
        move.l    (a3)+,(a6)
        move.l    (a3)+,(a6)
        move.l    (a3)+,(a6)
        move.l    (a3)+,(a6)
        move.l    (a3)+,(a6)
        move.l    (a3)+,(a6)
        move.l    (a3)+,(a6)        ; load pixels into VRAM DMA by each pixel
        addi.l      #$200000,d0        ; add on for the very next 32 pixels from VRAM DMA location
        addi.w    #$20,d2           ; add on for the very next 32 pixels from the art file
        dbf    d6,ShPLC_ReadEntry ; repeat depending on the number of tiles there are to change
      
    return_ShieldDPLC:
        rts
    ; --------------------------------------------------------------------------------------
    
    Shield_Tile_Arr:
        dc.w   0, 4, 8, $C, $10, $14, $0
        even       
      
    ; --------------------------------------------------------------------------------------
    Lastly, I would replace the shield animation, "byte_1DBD6", with this:

    Code:
    byte_1DBD6:    dc.b   0,  2,  0,  6,  5,  6,  0,  6,  5,  6,  1,  6,  5
                   dc.b   6,  2,  6,  5,  6,  3,  6,  5,  6,  4, $FF
                   even
    Now, you should get a result simliar to this (assuming you disabled the Nem Shield art from loading):
    [​IMG]

    Hopefully this helps!
     
    ProjectFM likes this.
  3. Psi

    Psi Well-Known Member Member

    Joined:
    Dec 20, 2014
    Messages:
    85
    That seems to have done the trick. Thank you very much. :D

    It even seems to work on 2p mode with two at once.