Advertisement
Guest User

LazyHDMA

a guest
Sep 3rd, 2015
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. @include
  2. ;===============================================================================
  3. ; LazyHDMA by ExoticMatter
  4. ;
  5. ; This libraryis a simple way to manage multiple HDMA effects without having
  6. ; to copy/paste a lot of code.
  7. ;
  8. ; To use LazyHDMA, incsrc lazyhdma.asm once from uberASM or levelASM. Then, use
  9. ; code such as the following:
  10. ;
  11. ; level105init:
  12. ;     %LazyInitEffect(MyGradient)
  13. ;     RTS
  14. ;
  15. ; MyGradient:
  16. ;     %LazyBGDouble(3, .RedGreen)
  17. ;     %LazyBGSingle(4, .Blue)
  18. ;     %LazyEnd()
  19. ;
  20. ; .RedGreen and .Blue are HDMA tables. Using sublabels is not required.
  21. ; To use a table that is in a different bank, use the _Long suffix. Otherwise,
  22. ; the table must be in the same bank as the descriptor.
  23. ;
  24. ; Make sure to apply IceMan's HDMA patch to prevent common HDMA problems
  25. ; including disappearing HDMA, flickering, and gradients that briefly appear
  26. ; when going through a pipe or door.
  27. ; http://www.smwcentral.net/?p=section&a=details&id=4176
  28. ;===============================================================================
  29. ; Main macros:
  30. ;
  31. ; %LazyInitEffect[_Tail](effect) - Initializes an HDMA effect.
  32. ;   This macro will set A, X, and Y to 8-bit and overwrite scratch RAM.
  33. ;   The _Tail suffix causes the subroutine to not return. This can only be
  34. ;   used where RTS can be used. (Or RTL, if !LongCall is nonzero.)
  35. ;   %LazyInitEffect only needs to be called once. Initializing an effect
  36. ;   that contains a scrolling gradient every frame will induce slowdown.
  37. ;
  38. ; %LazyRunEffect[_Tail](effect) - Runs an HDMA effect.
  39. ;   Like %LazyInitEffect, this macro sets A, X, and Y to 8-bit and overwrite
  40. ;   scratch RAM.
  41. ;   Only scrolling gradients need to be run every frame.
  42. ;   LazyHDMA does not update parallax effects at this point in time.
  43. ;===============================================================================
  44. ; Definition macros:
  45. ;
  46. ; %LazyBaseBG(color) - Defines the background color in BGR15 format.
  47. ;   Use rgb(r, g, b) to create a BGR15 color:
  48. ;   %LazyBaseBG(rgb(31,31,31))
  49. ;
  50. ; %LazyHDMA[_Long](channel, parameters, register, address) - Defines an HDMA
  51. ;   channel with the specified properties.
  52. ;   <register> must be between $2100-$21FF, although $00-$FF are also
  53. ;   allowed.
  54. ;
  55. ; %LazyBGSingle[_Long](channel, address) - Defines a background HDMA channel
  56. ;   that writes once per scanline, i.e. transfer mode 0.
  57. ;
  58. ; %LazyBGDouble[_Long](channel, address) - Defines a background HDMA channel
  59. ;   that writes twice per scanline, i.e. transfer mode 2.
  60. ;
  61. ; %LazyCGRAM[_Long](channel, address) - Defines a palette HDMA channel that
  62. ;   writes to two registers twice per scanline, i.e. transfer mode 3.
  63. ;
  64. ; %LazyBrightness[_Long](channel, address) - Defines a brightness HDMA channel
  65. ;   that writes to one register once per scanline, i.e. transfer mode 0.
  66. ;
  67. ; %LazyScroll[_Long](channelAB, channelC, address) - Defines a scrolling
  68. ;   background HDMA gradient that is decompressed into memory.
  69. ;   For the scrolling to occur, you must call %Lazy
  70. ;
  71. ; %LazyEnd() - Marks the end of the effect.
  72. ;===============================================================================
  73. ; Configuration:
  74. ;
  75. ; !LongCall: If set to a nonzero value, LazyHDMA will use JSL/JSR, allowing
  76. ; LazyHDMA to be called from a different bank. Off by default.
  77. ;
  78. ; !IncludeScrollingGradientCode: If set to a nonzero value, the scrolling
  79. ; gradient routines will be included. Off by default.
  80. ;
  81. ; !ScrollingFreeRAM_(AB|C): The location to put decompressed scrolling gradient
  82. ; tables. By default, $7F:B260 and $7F:B830 are used, respectively.
  83. ;
  84. ; To configure LazyHDMA, set one or more of these defines before incsrc.
  85. ;===============================================================================
  86. !LongCall ?= 0
  87. !IncludeScrollingGradientCode ?= 0
  88.  
  89. !ScrollingFreeRAM_AB ?= $7FB260
  90. !ScrollingFreeRAM_C ?= $7FB830
  91.  
  92. if !LongCall
  93.     !LazyHDMA_Call = JSL : !LazyHDMA_CallS = "JSL "
  94.     !LazyHDMA_Tail = JML : !LazyHDMA_TailS = "JML "
  95.     !LazyHDMA_Return = RTL : !LazyHDMA_ReturnS = "RTL "
  96. else
  97.     !LazyHDMA_Call = JSR.w : !LazyHDMA_CallS = "JSR.w "
  98.     !LazyHDMA_Tail = JMP.w : !LazyHDMA_TailS = "JMP.w "
  99.     !LazyHDMA_Return = RTS : !LazyHDMA_ReturnS = "RTS "
  100. endif
  101.  
  102. macro _LazyHDMA_LoadLong(effect)
  103.     SEP #$30
  104.     LDA.b #<effect>
  105.     LDY.b #<effect>>>8
  106.     LDX.b #<effect>>>16
  107. endmacro
  108.  
  109. _LazyHDMA:
  110.  
  111. macro LazyInitEffect(effect)
  112.     %_LazyHDMA_LoadLong(<effect>)
  113.     !LazyHDMA_Call .InitializeEffect
  114. endmacro
  115.  
  116. macro LazyInitEffect_Tail(effect)
  117.     %_LazyHDMA_LoadLong(<effect>)
  118.     !LazyHDMA_Tail .InitializeEffect
  119. endmacro
  120.  
  121. if !IncludeScrollingGradientCode
  122.     macro LazyRunEffect(effect)
  123.         %_LazyHDMA_LoadLong(<effect>)
  124.         !LazyHDMA_Call .RunEffect
  125.     endmacro
  126.  
  127.     macro LazyRunEffect_Tail(effect)
  128.         %_LazyHDMA_LoadLong(<effect>)
  129.         !LazyHDMA_Tail .RunEffect
  130.     endmacro
  131. else
  132.     macro LazyRunEffect(effect)
  133.     endmacro
  134.     macro LazyRunEffect_Tail(effect)
  135.     endmacro
  136. endif
  137.  
  138. !HDMA_ColorData = $2132
  139. !HDMA_Brightness = $2100
  140. !HDMA_CGRAM = $2121
  141.  
  142. !LazyHDMA_CommandMask = $1F
  143. !LazyHDMA_ChannelMask = $E0
  144.  
  145. macro _LazyHDMA_LoadArgs()
  146.     STA $00 ; Descriptor pointer, LSB
  147.     STY $01 ; Descriptor pointer, MSB
  148.     STX $02 ; Descriptor pointer, Bank
  149. ;   STX $03 ; Other address bank (initialization only)
  150.  
  151.     ;   $04 ; HDMA index (channel << 4)
  152.     ;   $05 ; second HDMA index (scrolling gradients only)
  153. endmacro
  154.  
  155. .InitializeEffect
  156.     %_LazyHDMA_LoadArgs()
  157.     STX $03
  158.  
  159.  -  SEP #$30    ; 8-bit A, X, Y
  160.     LDA [$00]
  161.     AND #!LazyHDMA_CommandMask
  162.     BEQ +
  163.     ASL
  164.     TAX
  165.     LDA [$00]
  166.     AND #!LazyHDMA_ChannelMask
  167.     LSR
  168.     STA $04
  169.  
  170.     REP #$20    ; 16-bit A
  171.     INC $00
  172.     JSR (.Subroutines-2, X)
  173.     BRA -
  174.  
  175.  +  !LazyHDMA_Return
  176.  
  177. !_LazySubroutine = 1
  178. !_LazySubroutineSizes = 1
  179.  
  180. macro _LazySubroutine(name, size)
  181.     assert !_LazySubroutine <= !LazyHDMA_CommandMask
  182.     !LazyHDMA_<name> #= !_LazySubroutine
  183.     !_LazySubroutine #= !_LazySubroutine+1
  184.     !_LazySubroutineSizes += ,<size>
  185.     dw .Set<name>
  186. endmacro
  187.  
  188. macro _LazySkip()
  189.     dw $0000
  190.     !_LazySubroutine #= !_LazySubroutine+1
  191.     !_LazySubroutineSizes += ,<size>
  192. endmacro
  193.  
  194. .Subroutines
  195.     %_LazySubroutine(LongPtr, 2)
  196.     %_LazySubroutine(BG, 3)
  197.     %_LazySubroutine(BGDouble, 3)
  198.     %_LazySubroutine(CGRAM, 3)
  199.     %_LazySubroutine(Brightness, 3)
  200. if !IncludeScrollingGradientCode
  201.     %_LazySubroutine(ScrollGradient, 4)
  202. else
  203.     %_LazySkip(4)
  204. endif
  205.     %_LazySubroutine(HDMA, 5)
  206.     %_LazySubroutine(BGFill, 3)
  207.  
  208. if !IncludeScrollingGradientCode
  209.     .SubroutineSizes db !_LazySubroutineSizes
  210. endif
  211.  
  212. !LazyHDMA_Invalid = !_LazySubroutine
  213.  
  214. .SetLongPtr
  215.     SEP #$20    ; \ 8-bit A
  216.     LDA [$00]   ; | \ Set the source bank number
  217.     STA $03     ; | /
  218.     REP #$20    ; / 16-bit A
  219.     INC $00     ; Next
  220.     RTS
  221.  
  222. .SetBGFill
  223.     LDA [$00]
  224.     STA $0701
  225.     INC $00
  226.     INC $00
  227.     RTS
  228.  
  229. .SetBG
  230.     LDA.w #!HDMA_ColorData<<8
  231. .SimpleCommon
  232.     LDX $04
  233.     STA $4300,X
  234.     LDA [$00]
  235.     STA $4302,X
  236.     SEP #$20 ; 8-bit A
  237.     LDA $03
  238.     STA $4304,X
  239.     TXA
  240.     LSR #4
  241.     TAX
  242.     LDA .Bits,X
  243.     TSB $0D9F
  244.     REP #$20 ; 16-bit A
  245.     INC $00
  246.     INC $00
  247.     LDX $02 ; \ Restore the data table bank
  248.     STX $03 ; / to the same bank as the descriptor
  249.     RTS
  250.  
  251. .SetBGDouble
  252.     LDA.w #(!HDMA_ColorData<<8)|2
  253.     BRA .SimpleCommon
  254. .SetCGRAM
  255.     LDA.w #(!HDMA_CGRAM<<8)|3
  256.     BRA .SimpleCommon
  257. .SetBrightness
  258.     LDA.w #!HDMA_Brightness<<8
  259.     BRA .SimpleCommon
  260. .SetHDMA
  261.     LDA [$00]
  262.     INC $00
  263.     INC $00
  264.     BRA .SimpleCommon
  265.  
  266. .Bits   db %00000001,%00000010,%00000100,%00001000,%00010000,%00100000,%01000000,%10000000
  267.  
  268. if !IncludeScrollingGradientCode
  269. .SetScrollGradient
  270.     LDY #$02    ; \
  271.     LDA [$00],Y ; | Load the second HDMA channel
  272.     TAX     ; | number and store it to scratch RAM
  273.     STX $05     ; /
  274.  
  275.     LDA $04     ; \
  276.     PHA     ; |
  277.     LDX $02     ; |
  278.     PHX     ; |
  279.     LDA $00     ; | Preserve scratch RAM
  280.     INC A       ; | \
  281.     INC A       ; | | Advance the command pointer
  282.     INC A       ; | /
  283.     PHA     ; /
  284.     LDA [$00]   ; Load table pointer
  285.     PHB     ; Preserve data bank
  286.     LDX $03     ; \
  287.     PHX     ; | Set data bank
  288.     PLB     ; /
  289.  
  290.     REP #$30    ; 16-bit A, X, Y
  291.     STA $02
  292.     INC
  293.     STA $04
  294.     INC
  295.     STA $06
  296.     INC
  297.     STA $08
  298.     LDA.w #!ScrollingFreeRAM_AB
  299.     STA $0A
  300.     LDA.w #!ScrollingFreeRAM_C
  301.     STA $0D
  302.     SEP #$20    ; 8-bit A
  303.     LDA #!ScrollingFreeRAM_AB>>16
  304.     STA $0C
  305. if !ScrollingFreeRAM_AB>>16 != !ScrollingFreeRAM_C>>16
  306.     LDA #!ScrollingFreeRAM_C>>16
  307. endif
  308.     STA $0F
  309. -   LDA ($02)
  310.     BEQ +
  311.     STA $00
  312. --  LDA #$01
  313.     STA [$0A]
  314.     STA [$0D]
  315.     LDY #$0001
  316.     LDA ($04)
  317.     STA [$0A],y
  318.     LDA ($08)
  319.     STA [$0D],y
  320.     INY
  321.     LDA ($06)
  322.     STA [$0A],y
  323.     REP #$20
  324.     INC $0A
  325.     INC $0A
  326.     INC $0A
  327.     INC $0D
  328.     INC $0D
  329.     SEP #$20
  330.     DEC $00
  331.     BPL --
  332.     REP #$20
  333.     LDA $02
  334.     CLC
  335.     ADC #$0004
  336.     STA $02
  337.     INC
  338.     STA $04
  339.     INC
  340.     STA $06
  341.     INC
  342.     STA $08
  343.     SEP #$20
  344.     BRA -
  345.  
  346. +   PLB     ; Restore previous data bank number
  347.     SEP #$10    ; Restore 8-bit X, Y
  348.     REP #$20    ; Restore 16-bit A
  349.     PLA     ; \
  350.     STA $00     ; |
  351.     PLX     ; |
  352.     STX $02     ; | Restore scratch RAM
  353.     STX $03     ; | | Restore the data source bank
  354.     PLA     ; |
  355.     STA $04     ; /
  356.  
  357.     TAX     ; \ Load the HDMA indexes
  358.     LDY $05     ; /
  359.  
  360.     LDA.w #(!HDMA_ColorData<<8)|2   ; \
  361.     STA $4300,X         ; | Set HDMA channel types
  362.     LDA.w #!HDMA_ColorData<<8   ; |
  363.     STA $4300,Y         ; /
  364.  
  365.     SEP #$20    ; 8-bit A
  366.     TXA     ; \
  367.     LSR #4      ; |
  368.     TAX     ; | Enable gradient A
  369.     LDA .Bits,X ; |
  370.     TSB $0D9F   ; /
  371.     TYA     ; \
  372.     LSR #4      ; |
  373.     TAX     ; | Enable gradient B
  374.     LDA .Bits,X ; |
  375.     TSB $0D9F   ; /
  376.     REP #$20    ; 16-bit A
  377.  
  378. .ScrollGradient:
  379.     LDA $20     ; \ Load the Y-position of BG2
  380.     LDX $1414   ; | \ Check how much the gradient should be shifted upward
  381.     CPX #$01    ; | | \
  382.     BEQ .Const  ; | | / #$01: Constant
  383.     CPX #$02    ; | | \
  384.     BEQ .Var    ; | | / #$02: Variable
  385.     CPX #$03    ; | | \
  386.     BEQ .Slow   ; | | / #$03: Slow
  387.             ; | |
  388. .None           ; | | \ No scrolling (consider using fixed HDMA)
  389.     SEC     ; | | |
  390.     SBC #$00C0  ; | | | shift 192 pixels downward
  391.     BRA .Const  ; | | / Continue
  392.             ; | |
  393. .Slow           ; | | \ Slow scrolling (consider using fixed HDMA)
  394.     SEC     ; | | |
  395.     SBC #$00A8  ; | | | shift 168 pixels downward
  396.     BRA .Const  ; | | /
  397.             ; | |
  398. .Var            ; | | \ Variable scrolling
  399.     SEC     ; | | |
  400.     SBC #$0060  ; | | / shift 96 pixels downward
  401.             ; | |
  402. .Const          ; | / < Constant scrolling (BG2:Camera = 1:1)
  403.             ; |
  404.             ; | \ Put an LSR/ASL or two here to change the rate at which
  405.             ; | / the gradient scrolls.
  406.             ; |
  407.     STA $06     ; / and store it to scratch RAM.
  408.  
  409.     LDX $04     ; \ Load the HDMA indexes
  410.     LDY $05     ; /
  411.  
  412.     LDA $06
  413.     ASL     ; \
  414.     CLC     ; | This transforms the Y-pos of BG2
  415.     ADC $06     ; | into the address at which the HDMA
  416.     CLC     ; | gradient should start
  417.     ADC.w #!ScrollingFreeRAM_AB
  418.     STA $4302,X ; HDMA Channel A table starting address.
  419.  
  420.     LDA $06     ; \
  421.     ASL     ; | Y-pos of BG2 to
  422.     CLC     ; | HDMA table offset
  423.     ADC.w #!ScrollingFreeRAM_C
  424.     STA $4302,Y ; HDMA Channel B table starting address.
  425.  
  426.     SEP #$20    ; 8-bit A
  427.     LDA.b #!ScrollingFreeRAM_AB>>16
  428.     STA $4304,X
  429. if !ScrollingFreeRAM_AB>>16 != !ScrollingFreeRAM_C>>16
  430.     LDA.b #!ScrollingFreeRAM_C>>16
  431. endif
  432.     STA $4304,Y
  433.  
  434.     RTS
  435.  
  436. .RunEffect:
  437.     %_LazyHDMA_LoadArgs()
  438.  
  439.  -  SEP #$30    ; 8-bit A, X, Y
  440.     LDA [$00]
  441.     AND #!LazyHDMA_CommandMask
  442.     BEQ +
  443.     CMP.b #!LazyHDMA_ScrollGradient
  444.     BEQ ++
  445.     TAX
  446.     LDA .SubroutineSizes,X
  447.     CLC
  448.     REP #$20    ; 16-bit A
  449.     AND #$00FF
  450.     ADC $00
  451.     STA $00
  452.     BRA -       ; Repeat
  453.  
  454.  ++ LDA [$00]
  455.     AND #!LazyHDMA_ChannelMask
  456.     LSR
  457.     STA $04
  458.  
  459.     LDY #$04    ; \
  460.     LDA [$00],Y ; | Load the second channel number
  461.     STA $05     ; /
  462.  
  463.     REP #$20    ; 16-bit A
  464.     INC $00
  465.     JSR .ScrollGradient
  466.     REP #$20    ; 16-bit A
  467.     INC $00
  468.     INC $00
  469.     INC $00
  470.     BRA -
  471.  
  472.  +  !LazyHDMA_Return
  473. endif
  474.  
  475. macro LazyBaseBG(color)
  476.     assert <color> >= 0 && <color> < $8000, "Invalid color"
  477.     db !LazyHDMA_BGFill
  478.     dw <color>
  479. endmacro
  480.  
  481. function rgb(r, g, b) = r|(g<<5)|(b<<10)
  482.  
  483. macro LazyHDMA(channel, params, register, address)
  484.     assert <channel> >= 0 && <channel> < 8, "Invalid HDMA channel"
  485.     assert <params> >= 0 && <params> < $100, "Invalid HDMA parameters"
  486.     if <register> >= $00 && <register> < $100
  487.     elseif <register> >= $2100 && <register> < $2200
  488.     else
  489.         error "Invalid HDMA target register"
  490.     endif
  491.     db !LazyHDMA_HDMA|(<channel><<5)
  492.     db <params>, <register>
  493.     dw <address>
  494. endmacro
  495.  
  496. macro LazyHDMA_Long(channel, params, register, address)
  497.     db !LazyHDMA_LongPtr, (<address>>>16)
  498.     %LazyHDMA(channel, params, register, address)
  499. endmacro
  500.  
  501. macro LazySimple(type, channel, address)
  502.     assert <type> > 0 && <type> < !LazyHDMA_Invalid, "Invalid channel type"
  503.     assert <channel> >= 0 && <channel> < 8, "Invalid HDMA channel"
  504.     db <type>|(<channel><<5)
  505.     dw <address>
  506. endmacro
  507.  
  508. macro LazyBGSingle(channel, address)
  509.     %LazySimple(!LazyHDMA_BG, <channel>, <address>)
  510. endmacro
  511. macro LazyBGDouble(channel, address)
  512.     %LazySimple(!LazyHDMA_BGDouble, <channel>, <address>)
  513. endmacro
  514. macro LazyCGRAM(channel, address)
  515.     %LazySimple(!LazyHDMA_CGRAM, <channel>, <address>)
  516. endmacro
  517. macro LazyBrightness(channel, address)
  518.     %LazySimple(!LazyHDMA_Brightness, <channel>, <address>)
  519. endmacro
  520.  
  521. macro LazySimple_Long(type, channel, address)
  522.     db !LazyHDMA_LongPtr, (<address>>>16)
  523.     %LazySimple(<type>, <channel>, <address>)
  524. endmacro
  525.  
  526. macro LazyBGSingle_Long(channel, address)
  527.     %LazySimple_Long(!LazyHDMA_BG, <channel>, <address>)
  528. endmacro
  529. macro LazyBGDouble_Long(channel, address)
  530.     %LazySimple_Long(!LazyHDMA_BGDouble, <channel>, <address>)
  531. endmacro
  532. macro LazyCGRAM_Long(channel, address)
  533.     %LazySimple_Long(!LazyHDMA_CGRAM, <channel>, <address>)
  534. endmacro
  535. macro LazyBrightness_Long(channel, address)
  536.     %LazySimple_Long(!LazyHDMA_Brightness, <channel>, <address>)
  537. endmacro
  538.  
  539. if !IncludeScrollingGradientCode
  540.     macro LazyScroll(channel, secondchannel, address)
  541.         %LazySimple(!LazyHDMA_ScrollGradient, <channel>, <address>)
  542.         db <secondchannel><<4
  543.     endmacro
  544.     macro LazyScroll_Long(channel, secondchannel, address)
  545.         %LazySimple_Long(!LazyHDMA_ScrollGradient, <channel>, <address>)
  546.         db <secondchannel><<4
  547.     endmacro
  548. endif
  549.  
  550. macro LazyEnd()
  551.     db $00
  552. endmacro
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement