View difference between Paste ID: zGTVyvpJ and k0bAjxkX
SHOW: | | - or go back to the newest paste.
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