Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- @include
- ;===============================================================================
- ; LazyHDMA by ExoticMatter
- ;
- ; This libraryis a simple way to manage multiple HDMA effects without having
- ; to copy/paste a lot of code.
- ;
- ; To use LazyHDMA, incsrc lazyhdma.asm once from uberASM or levelASM. Then, use
- ; code such as the following:
- ;
- ; level105init:
- ; %LazyInitEffect(MyGradient)
- ; RTS
- ;
- ; MyGradient:
- ; %LazyBGDouble(3, .RedGreen)
- ; %LazyBGSingle(4, .Blue)
- ; %LazyEnd()
- ;
- ; .RedGreen and .Blue are HDMA tables. Using sublabels is not required.
- ; To use a table that is in a different bank, use the _Long suffix. Otherwise,
- ; the table must be in the same bank as the descriptor.
- ;
- ; Make sure to apply IceMan's HDMA patch to prevent common HDMA problems
- ; including disappearing HDMA, flickering, and gradients that briefly appear
- ; when going through a pipe or door.
- ; http://www.smwcentral.net/?p=section&a=details&id=4176
- ;===============================================================================
- ; Main macros:
- ;
- ; %LazyInitEffect[_Tail](effect) - Initializes an HDMA effect.
- ; This macro will set A, X, and Y to 8-bit and overwrite scratch RAM.
- ; The _Tail suffix causes the subroutine to not return. This can only be
- ; used where RTS can be used. (Or RTL, if !LongCall is nonzero.)
- ; %LazyInitEffect only needs to be called once. Initializing an effect
- ; that contains a scrolling gradient every frame will induce slowdown.
- ;
- ; %LazyRunEffect[_Tail](effect) - Runs an HDMA effect.
- ; Like %LazyInitEffect, this macro sets A, X, and Y to 8-bit and overwrite
- ; scratch RAM.
- ; Only scrolling gradients need to be run every frame.
- ; LazyHDMA does not update parallax effects at this point in time.
- ;===============================================================================
- ; Definition macros:
- ;
- ; %LazyBaseBG(color) - Defines the background color in BGR15 format.
- ; Use rgb(r, g, b) to create a BGR15 color:
- ; %LazyBaseBG(rgb(31,31,31))
- ;
- ; %LazyHDMA[_Long](channel, parameters, register, address) - Defines an HDMA
- ; channel with the specified properties.
- ; <register> must be between $2100-$21FF, although $00-$FF are also
- ; allowed.
- ;
- ; %LazyBGSingle[_Long](channel, address) - Defines a background HDMA channel
- ; that writes once per scanline, i.e. transfer mode 0.
- ;
- ; %LazyBGDouble[_Long](channel, address) - Defines a background HDMA channel
- ; that writes twice per scanline, i.e. transfer mode 2.
- ;
- ; %LazyCGRAM[_Long](channel, address) - Defines a palette HDMA channel that
- ; writes to two registers twice per scanline, i.e. transfer mode 3.
- ;
- ; %LazyBrightness[_Long](channel, address) - Defines a brightness HDMA channel
- ; that writes to one register once per scanline, i.e. transfer mode 0.
- ;
- ; %LazyScroll[_Long](channelAB, channelC, address) - Defines a scrolling
- ; background HDMA gradient that is decompressed into memory.
- ; For the scrolling to occur, you must call %Lazy
- ;
- ; %LazyEnd() - Marks the end of the effect.
- ;===============================================================================
- ; Configuration:
- ;
- ; !LongCall: If set to a nonzero value, LazyHDMA will use JSL/JSR, allowing
- ; LazyHDMA to be called from a different bank. Off by default.
- ;
- ; !IncludeScrollingGradientCode: If set to a nonzero value, the scrolling
- ; gradient routines will be included. Off by default.
- ;
- ; !ScrollingFreeRAM_(AB|C): The location to put decompressed scrolling gradient
- ; tables. By default, $7F:B260 and $7F:B830 are used, respectively.
- ;
- ; To configure LazyHDMA, set one or more of these defines before incsrc.
- ;===============================================================================
- !LongCall ?= 0
- !IncludeScrollingGradientCode ?= 0
- !ScrollingFreeRAM_AB ?= $7FB260
- !ScrollingFreeRAM_C ?= $7FB830
- if !LongCall
- !LazyHDMA_Call = JSL : !LazyHDMA_CallS = "JSL "
- !LazyHDMA_Tail = JML : !LazyHDMA_TailS = "JML "
- !LazyHDMA_Return = RTL : !LazyHDMA_ReturnS = "RTL "
- else
- !LazyHDMA_Call = JSR.w : !LazyHDMA_CallS = "JSR.w "
- !LazyHDMA_Tail = JMP.w : !LazyHDMA_TailS = "JMP.w "
- !LazyHDMA_Return = RTS : !LazyHDMA_ReturnS = "RTS "
- endif
- macro _LazyHDMA_LoadLong(effect)
- SEP #$30
- LDA.b #<effect>
- LDY.b #<effect>>>8
- LDX.b #<effect>>>16
- endmacro
- _LazyHDMA:
- macro LazyInitEffect(effect)
- %_LazyHDMA_LoadLong(<effect>)
- !LazyHDMA_Call .InitializeEffect
- endmacro
- macro LazyInitEffect_Tail(effect)
- %_LazyHDMA_LoadLong(<effect>)
- !LazyHDMA_Tail .InitializeEffect
- endmacro
- if !IncludeScrollingGradientCode
- macro LazyRunEffect(effect)
- %_LazyHDMA_LoadLong(<effect>)
- !LazyHDMA_Call .RunEffect
- endmacro
- macro LazyRunEffect_Tail(effect)
- %_LazyHDMA_LoadLong(<effect>)
- !LazyHDMA_Tail .RunEffect
- endmacro
- else
- macro LazyRunEffect(effect)
- endmacro
- macro LazyRunEffect_Tail(effect)
- endmacro
- endif
- !HDMA_ColorData = $2132
- !HDMA_Brightness = $2100
- !HDMA_CGRAM = $2121
- !LazyHDMA_CommandMask = $1F
- !LazyHDMA_ChannelMask = $E0
- macro _LazyHDMA_LoadArgs()
- STA $00 ; Descriptor pointer, LSB
- STY $01 ; Descriptor pointer, MSB
- STX $02 ; Descriptor pointer, Bank
- ; STX $03 ; Other address bank (initialization only)
- ; $04 ; HDMA index (channel << 4)
- ; $05 ; second HDMA index (scrolling gradients only)
- endmacro
- .InitializeEffect
- %_LazyHDMA_LoadArgs()
- STX $03
- - SEP #$30 ; 8-bit A, X, Y
- LDA [$00]
- AND #!LazyHDMA_CommandMask
- BEQ +
- ASL
- TAX
- LDA [$00]
- AND #!LazyHDMA_ChannelMask
- LSR
- STA $04
- REP #$20 ; 16-bit A
- INC $00
- JSR (.Subroutines-2, X)
- BRA -
- + !LazyHDMA_Return
- !_LazySubroutine = 1
- !_LazySubroutineSizes = 1
- macro _LazySubroutine(name, size)
- assert !_LazySubroutine <= !LazyHDMA_CommandMask
- !LazyHDMA_<name> #= !_LazySubroutine
- !_LazySubroutine #= !_LazySubroutine+1
- !_LazySubroutineSizes += ,<size>
- dw .Set<name>
- endmacro
- macro _LazySkip()
- dw $0000
- !_LazySubroutine #= !_LazySubroutine+1
- !_LazySubroutineSizes += ,<size>
- endmacro
- .Subroutines
- %_LazySubroutine(LongPtr, 2)
- %_LazySubroutine(BG, 3)
- %_LazySubroutine(BGDouble, 3)
- %_LazySubroutine(CGRAM, 3)
- %_LazySubroutine(Brightness, 3)
- if !IncludeScrollingGradientCode
- %_LazySubroutine(ScrollGradient, 4)
- else
- %_LazySkip(4)
- endif
- %_LazySubroutine(HDMA, 5)
- %_LazySubroutine(BGFill, 3)
- if !IncludeScrollingGradientCode
- .SubroutineSizes db !_LazySubroutineSizes
- endif
- !LazyHDMA_Invalid = !_LazySubroutine
- .SetLongPtr
- SEP #$20 ; \ 8-bit A
- LDA [$00] ; | \ Set the source bank number
- STA $03 ; | /
- REP #$20 ; / 16-bit A
- INC $00 ; Next
- RTS
- .SetBGFill
- LDA [$00]
- STA $0701
- INC $00
- INC $00
- RTS
- .SetBG
- LDA.w #!HDMA_ColorData<<8
- .SimpleCommon
- LDX $04
- STA $4300,X
- LDA [$00]
- STA $4302,X
- SEP #$20 ; 8-bit A
- LDA $03
- STA $4304,X
- TXA
- LSR #4
- TAX
- LDA .Bits,X
- TSB $0D9F
- REP #$20 ; 16-bit A
- INC $00
- INC $00
- LDX $02 ; \ Restore the data table bank
- STX $03 ; / to the same bank as the descriptor
- RTS
- .SetBGDouble
- LDA.w #(!HDMA_ColorData<<8)|2
- BRA .SimpleCommon
- .SetCGRAM
- LDA.w #(!HDMA_CGRAM<<8)|3
- BRA .SimpleCommon
- .SetBrightness
- LDA.w #!HDMA_Brightness<<8
- BRA .SimpleCommon
- .SetHDMA
- LDA [$00]
- INC $00
- INC $00
- BRA .SimpleCommon
- .Bits db %00000001,%00000010,%00000100,%00001000,%00010000,%00100000,%01000000,%10000000
- if !IncludeScrollingGradientCode
- .SetScrollGradient
- LDY #$02 ; \
- LDA [$00],Y ; | Load the second HDMA channel
- TAX ; | number and store it to scratch RAM
- STX $05 ; /
- LDA $04 ; \
- PHA ; |
- LDX $02 ; |
- PHX ; |
- LDA $00 ; | Preserve scratch RAM
- INC A ; | \
- INC A ; | | Advance the command pointer
- INC A ; | /
- PHA ; /
- LDA [$00] ; Load table pointer
- PHB ; Preserve data bank
- LDX $03 ; \
- PHX ; | Set data bank
- PLB ; /
- REP #$30 ; 16-bit A, X, Y
- STA $02
- INC
- STA $04
- INC
- STA $06
- INC
- STA $08
- LDA.w #!ScrollingFreeRAM_AB
- STA $0A
- LDA.w #!ScrollingFreeRAM_C
- STA $0D
- SEP #$20 ; 8-bit A
- LDA #!ScrollingFreeRAM_AB>>16
- STA $0C
- if !ScrollingFreeRAM_AB>>16 != !ScrollingFreeRAM_C>>16
- LDA #!ScrollingFreeRAM_C>>16
- endif
- STA $0F
- - LDA ($02)
- BEQ +
- STA $00
- -- LDA #$01
- STA [$0A]
- STA [$0D]
- LDY #$0001
- LDA ($04)
- STA [$0A],y
- LDA ($08)
- STA [$0D],y
- INY
- LDA ($06)
- STA [$0A],y
- REP #$20
- INC $0A
- INC $0A
- INC $0A
- INC $0D
- INC $0D
- SEP #$20
- DEC $00
- BPL --
- REP #$20
- LDA $02
- CLC
- ADC #$0004
- STA $02
- INC
- STA $04
- INC
- STA $06
- INC
- STA $08
- SEP #$20
- BRA -
- + PLB ; Restore previous data bank number
- SEP #$10 ; Restore 8-bit X, Y
- REP #$20 ; Restore 16-bit A
- PLA ; \
- STA $00 ; |
- PLX ; |
- STX $02 ; | Restore scratch RAM
- STX $03 ; | | Restore the data source bank
- PLA ; |
- STA $04 ; /
- TAX ; \ Load the HDMA indexes
- LDY $05 ; /
- LDA.w #(!HDMA_ColorData<<8)|2 ; \
- STA $4300,X ; | Set HDMA channel types
- LDA.w #!HDMA_ColorData<<8 ; |
- STA $4300,Y ; /
- SEP #$20 ; 8-bit A
- TXA ; \
- LSR #4 ; |
- TAX ; | Enable gradient A
- LDA .Bits,X ; |
- TSB $0D9F ; /
- TYA ; \
- LSR #4 ; |
- TAX ; | Enable gradient B
- LDA .Bits,X ; |
- TSB $0D9F ; /
- REP #$20 ; 16-bit A
- .ScrollGradient:
- LDA $20 ; \ Load the Y-position of BG2
- LDX $1414 ; | \ Check how much the gradient should be shifted upward
- CPX #$01 ; | | \
- BEQ .Const ; | | / #$01: Constant
- CPX #$02 ; | | \
- BEQ .Var ; | | / #$02: Variable
- CPX #$03 ; | | \
- BEQ .Slow ; | | / #$03: Slow
- ; | |
- .None ; | | \ No scrolling (consider using fixed HDMA)
- SEC ; | | |
- SBC #$00C0 ; | | | shift 192 pixels downward
- BRA .Const ; | | / Continue
- ; | |
- .Slow ; | | \ Slow scrolling (consider using fixed HDMA)
- SEC ; | | |
- SBC #$00A8 ; | | | shift 168 pixels downward
- BRA .Const ; | | /
- ; | |
- .Var ; | | \ Variable scrolling
- SEC ; | | |
- SBC #$0060 ; | | / shift 96 pixels downward
- ; | |
- .Const ; | / < Constant scrolling (BG2:Camera = 1:1)
- ; |
- ; | \ Put an LSR/ASL or two here to change the rate at which
- ; | / the gradient scrolls.
- ; |
- STA $06 ; / and store it to scratch RAM.
- LDX $04 ; \ Load the HDMA indexes
- LDY $05 ; /
- LDA $06
- ASL ; \
- CLC ; | This transforms the Y-pos of BG2
- ADC $06 ; | into the address at which the HDMA
- CLC ; | gradient should start
- ADC.w #!ScrollingFreeRAM_AB
- STA $4302,X ; HDMA Channel A table starting address.
- LDA $06 ; \
- ASL ; | Y-pos of BG2 to
- CLC ; | HDMA table offset
- ADC.w #!ScrollingFreeRAM_C
- STA $4302,Y ; HDMA Channel B table starting address.
- SEP #$20 ; 8-bit A
- LDA.b #!ScrollingFreeRAM_AB>>16
- STA $4304,X
- if !ScrollingFreeRAM_AB>>16 != !ScrollingFreeRAM_C>>16
- LDA.b #!ScrollingFreeRAM_C>>16
- endif
- STA $4304,Y
- RTS
- .RunEffect:
- %_LazyHDMA_LoadArgs()
- - SEP #$30 ; 8-bit A, X, Y
- LDA [$00]
- AND #!LazyHDMA_CommandMask
- BEQ +
- CMP.b #!LazyHDMA_ScrollGradient
- BEQ ++
- TAX
- LDA .SubroutineSizes,X
- CLC
- REP #$20 ; 16-bit A
- AND #$00FF
- ADC $00
- STA $00
- BRA - ; Repeat
- ++ LDA [$00]
- AND #!LazyHDMA_ChannelMask
- LSR
- STA $04
- LDY #$04 ; \
- LDA [$00],Y ; | Load the second channel number
- STA $05 ; /
- REP #$20 ; 16-bit A
- INC $00
- JSR .ScrollGradient
- REP #$20 ; 16-bit A
- INC $00
- INC $00
- INC $00
- BRA -
- + !LazyHDMA_Return
- endif
- macro LazyBaseBG(color)
- assert <color> >= 0 && <color> < $8000, "Invalid color"
- db !LazyHDMA_BGFill
- dw <color>
- endmacro
- function rgb(r, g, b) = r|(g<<5)|(b<<10)
- macro LazyHDMA(channel, params, register, address)
- assert <channel> >= 0 && <channel> < 8, "Invalid HDMA channel"
- assert <params> >= 0 && <params> < $100, "Invalid HDMA parameters"
- if <register> >= $00 && <register> < $100
- elseif <register> >= $2100 && <register> < $2200
- else
- error "Invalid HDMA target register"
- endif
- db !LazyHDMA_HDMA|(<channel><<5)
- db <params>, <register>
- dw <address>
- endmacro
- macro LazyHDMA_Long(channel, params, register, address)
- db !LazyHDMA_LongPtr, (<address>>>16)
- %LazyHDMA(channel, params, register, address)
- endmacro
- macro LazySimple(type, channel, address)
- assert <type> > 0 && <type> < !LazyHDMA_Invalid, "Invalid channel type"
- assert <channel> >= 0 && <channel> < 8, "Invalid HDMA channel"
- db <type>|(<channel><<5)
- dw <address>
- endmacro
- macro LazyBGSingle(channel, address)
- %LazySimple(!LazyHDMA_BG, <channel>, <address>)
- endmacro
- macro LazyBGDouble(channel, address)
- %LazySimple(!LazyHDMA_BGDouble, <channel>, <address>)
- endmacro
- macro LazyCGRAM(channel, address)
- %LazySimple(!LazyHDMA_CGRAM, <channel>, <address>)
- endmacro
- macro LazyBrightness(channel, address)
- %LazySimple(!LazyHDMA_Brightness, <channel>, <address>)
- endmacro
- macro LazySimple_Long(type, channel, address)
- db !LazyHDMA_LongPtr, (<address>>>16)
- %LazySimple(<type>, <channel>, <address>)
- endmacro
- macro LazyBGSingle_Long(channel, address)
- %LazySimple_Long(!LazyHDMA_BG, <channel>, <address>)
- endmacro
- macro LazyBGDouble_Long(channel, address)
- %LazySimple_Long(!LazyHDMA_BGDouble, <channel>, <address>)
- endmacro
- macro LazyCGRAM_Long(channel, address)
- %LazySimple_Long(!LazyHDMA_CGRAM, <channel>, <address>)
- endmacro
- macro LazyBrightness_Long(channel, address)
- %LazySimple_Long(!LazyHDMA_Brightness, <channel>, <address>)
- endmacro
- if !IncludeScrollingGradientCode
- macro LazyScroll(channel, secondchannel, address)
- %LazySimple(!LazyHDMA_ScrollGradient, <channel>, <address>)
- db <secondchannel><<4
- endmacro
- macro LazyScroll_Long(channel, secondchannel, address)
- %LazySimple_Long(!LazyHDMA_ScrollGradient, <channel>, <address>)
- db <secondchannel><<4
- endmacro
- endif
- macro LazyEnd()
- db $00
- endmacro
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement