FIXED Improving the Fade to White Routines

Discussion in 'Tutorials' started by ProjectFM, Mar 6, 2020.

  1. ProjectFM

    ProjectFM Optimistic and self-dependent Member

    Joined:
    Oct 4, 2014
    Messages:
    846
    Location:
    Portland, Maine
    In 2015, I created a tutorial for a modified version of MarkeyJester's palette fading subroutine which would smoothly fade from and to white. It turns out that tutorial had a pretty big flaw in that when fading in from white, the colors would be a shade darker than they should be.

    Special thanks to Iso Kilo for bringing this to my attention.

    In Sonic 1's Hivebrain disassembly, just replace the beginning of Pal_MakeWhite to the end of Pal_AddColor2. Implementing this into other disassemblies or Sonic games should just require replacing the variables and calls to outside subroutines with your disassembly's equivalent.
    Code:
    ; ---------------------------------------------------------------------------
    ; Subroutine to fill the pallet with white (special stage)
    ; ---------------------------------------------------------------------------
    
    ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    
    
    Pal_MakeWhite: ; XREF: SpecialStage
            move.w #$3F,($FFFFF626).w
            moveq #0,d0
            lea ($FFFFFB00).w,a0
            move.b ($FFFFF626).w,d0
            adda.w d0,a0
            move.w #$EEE,d1
            move.b ($FFFFF627).w,d0
    
    PalWhite_Loop:
            move.w d1,(a0)+
            dbf d0,PalWhite_Loop ; fill pallet with $000 (black)
            moveq #$0E,d4 ; MJ: prepare maximum colour check
            moveq #$00,d6 ; MJ: clear d6
    
    loc_1EF4:
            bsr.w RunPLC_RAM
            move.b #$12,($FFFFF62A).w
            bsr.w DelayProgram
            bchg #$00,d6 ; MJ: change delay counter
            beq loc_1EF4 ; MJ: if null, delay a frame
            bsr.s Pal_WhiteToBlack
            subq.b #$02,d4 ; MJ: decrease colour check
            bne loc_1EF4 ; MJ: if it has not reached null, branch
            move.b #$12,($FFFFF62A).w ; MJ: wait for V-blank again (so colours transfer)
            bra DelayProgram ; MJ: ''
    ; End of function Pal_MakeWhite
    
    
    ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    
    
    Pal_WhiteToBlack: ; XREF: Pal_MakeWhite
            moveq #0,d0
            lea ($FFFFFB00).w,a0
            lea ($FFFFFB80).w,a1
            move.b ($FFFFF626).w,d0
            adda.w d0,a0
            adda.w d0,a1
            move.b ($FFFFF627).w,d0
    
    loc_1F20:
            bsr.s Pal_DecColor2
            dbf d0,loc_1F20
            cmpi.b #1,($FFFFFE10).w
            bne.s locret_1F4A
            moveq #0,d0
            lea ($FFFFFA80).w,a0
            lea ($FFFFFA00).w,a1
            move.b ($FFFFF626).w,d0
            adda.w d0,a0
            adda.w d0,a1
            move.b ($FFFFF627).w,d0
    
    loc_1F44:
            bsr.s Pal_DecColor2
            dbf d0,loc_1F44
    
    locret_1F4A:
            rts
    ; End of function Pal_WhiteToBlack
    
    
    ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    
    
    Pal_DecColor2: ; XREF: Pal_WhiteToBlack
            move.b (a1),d5 ; MJ: load blue
            move.w (a1)+,d1 ; MJ: load green and red
            move.b d1,d2 ; MJ: load red
            lsr.b #$04,d1 ; MJ: get only green
            andi.b #$0E,d2 ; MJ: get only red
            move.w (a0),d3 ; MJ: load current colour in buffer
            cmp.b d5,d4 ; MJ: is it time for blue to fade?
            bls FCI2_NoBlue ; MJ: if not, branch
            subi.w #$0200,d3 ; MJ: dencrease blue
    
    FCI2_NoBlue:
            cmp.b d1,d4 ; MJ: is it time for green to fade?
            bls FCI2_NoGreen ; MJ: if not, branch
            subi.b #$20,d3 ; MJ: dencrease green
    
    FCI2_NoGreen:
            cmp.b d2,d4 ; MJ: is it time for red to fade?
            bls FCI2_NoRed ; MJ: if not, branch
            subq.b #$02,d3 ; MJ: dencrease red
    
    FCI2_NoRed:
            move.w d3,(a0)+ ; MJ: save colour
            rts ; MJ: return
    ; End of function Pal_DecColor2
    
    ; ---------------------------------------------------------------------------
    ; Subroutine to make a white flash when you enter a special stage
    ; ---------------------------------------------------------------------------
    
    ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    
    
    Pal_MakeFlash: ; XREF: SpecialStage
            move.w #$3F,($FFFFF626).w
            moveq #$07,d4 ; MJ: set repeat times
            moveq #$00,d6 ; MJ: clear d6
    
    loc_1F86:
            bsr.w RunPLC_RAM
            move.b #$12,($FFFFF62A).w
            bsr.w DelayProgram
            bchg #$00,d6 ; MJ: change delay counter
            beq loc_1F86 ; MJ: if null, delay a frame
            bsr.s Pal_ToWhite
            dbf d4,loc_1F86
            rts
    ; End of function Pal_MakeFlash
    
    
    ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    
    
    Pal_ToWhite: ; XREF: Pal_MakeFlash
            moveq #0,d0
            lea ($FFFFFB00).w,a0
            move.b ($FFFFF626).w,d0
            adda.w d0,a0
            move.b ($FFFFF627).w,d0
    
    loc_1FAC:
            bsr.s Pal_AddColor2
            dbf d0,loc_1FAC
    
            moveq #0,d0
            lea ($FFFFFA80).w,a0
            move.b ($FFFFF626).w,d0
            adda.w d0,a0
            move.b ($FFFFF627).w,d0
    
    loc_1FC2:
            bsr.s Pal_AddColor2
            dbf d0,loc_1FC2
            rts
    ; End of function Pal_ToWhite
    
    
    ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    
    
    Pal_AddColor2: ; XREF: Pal_ToWhite
            move.w (a0),d5 ; MJ: load colour
            cmpi.w #$EEE,d5
            beq.s FCO2_NoRed
            move.w d5,d1 ; MJ: copy to d1
            move.b d1,d2 ; MJ: load green and red
            move.b d1,d3 ; MJ: load red
            andi.w #$0E00,d1 ; MJ: get only blue
            cmpi.w #$0E00,d1
            beq FCO2_NoBlue ; MJ: if blue is finished, branch
            addi.w #$0200,d5 ; MJ: increase blue
    
    FCO2_NoBlue:
            andi.w #$00E0,d2 ; MJ: get only green (needs to be word)
            cmpi.w #$00E0,d2
            beq FCO2_NoGreen ; MJ: if green is finished, branch
            addi.b #$20,d5 ; MJ: increase green
    
    FCO2_NoGreen:
            andi.b #$0E,d3 ; MJ: get only red
            cmpi.b #$0E,d3
            beq FCO2_NoRed ; MJ: if red is finished, branch
            addq.b #$02,d5 ; MJ: increase red
    
    FCO2_NoRed:
            move.w d5,(a0)+ ; MJ: save new colour
            rts ; MJ: return
    ; End of function Pal_AddColor2
     
    DeltaWooloo and Iso Kilo like this.
  2. Iso Kilo

    Iso Kilo Local Wolf-Fox Member

    Joined:
    Oct 9, 2017
    Messages:
    251
    Location:
    Small Town in BC, Canada
    You may want to actually include an example of the issue. :p
    [​IMG]
    As well as an explanation as to what you changed from last time:
    upload_2020-3-6_12-5-53.png
    Just helps give a better understanding as to what's being done.
     
    Samey and ProjectFM like this.