-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtaki-effect.s
556 lines (491 loc) · 11.6 KB
/
taki-effect.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
.include "forthish.inc"
TAKI_INTERNAL=1
.include "taki-public.inc"
I_AM_TAKI_EFFECT=1
.include "taki-internal.inc"
.include "taki-effect.inc"
.include "taki-debug.inc"
.macpack apple2
.export _TakiVarActiveEffectsNum
_TakiVarActiveEffectsNum:
.byte $00
; alloc table: tracks the ENDs of allocation!
; Start of alloc for first effect is always
; start of the storage area itself.
.export _TakiEffectTablesStart
_TakiEffectTablesStart:
.export _TakiVarEffectAllocTable
_TakiVarEffectAllocTable = _TakiEffectTablesStart
.export _TakiVarEffectCounterTable
_TakiVarEffectCounterTable = _TakiEffectTablesStart + 2
.export _TakiVarEffectCounterInitTable
_TakiVarEffectCounterInitTable = _TakiEffectTablesStart + 4
.export _TakiVarEffectDispatchTable
_TakiVarEffectDispatchTable = _TakiEffectTablesStart + 6
.export _TakiEffectTablesEnd
_TakiEffectTablesEnd = _TakiEffectTablesStart + 8
; actual table of table addresses:
.res (_TakiEffectTablesEnd - _TakiEffectTablesStart)
; Setup zero page for effect actions.
; Set TakiEffectSetupFn to your fn addr
; before invoking
.export _TakiEffectSetupAndDo
_TakiEffectSetupAndDo:
; Save various things to stack
pha
txa
pha
tya
pha
ldy #kZpStart ; Save ZP items
@Lp:lda $00,y
pha
iny
cpy #kZpEnd
bne @Lp
; Copy CmdBuf location to ZP
lda #$00
sta kZpCmdBufL
lda TakiVarCommandBufferPage
sta kZpCmdBufH
; Copy effect tables to ZP
; (assumes we keep same order internally!)
ldy #$00
@LpZp:
lda _TakiEffectTablesStart,y
sta kZpEffTablesStart,y
iny
cpy #1 + kZpEffTablesEnd - kZpEffTablesStart
bne @LpZp
; Copy saved registers to ZP
;
;pick_ kZpEnd-kZpStart, 3
; ^ ca65 doesn't like, for some reason
pick_ $17, 3
pla
tay
sty kZpY
pla
tax
stx kZpX
pla
sta kZpAcc
; Copy status flags
lda _TakiVarStatusFlags
sta TakiVarStatusFlags
.export _TakiEffectSetupFn
_TakiEffectSetupFn = * + 1
jsr $1000
; Restore various things to stack
ldy #kZpEnd-1 ; Restore ZP items
@Lp:pla
sta $00,y
dey
cpy #kZpStart
bcs @Lp
; Restore registers
pla
tay
pla
tax
pla
rts
.export _TakiSetupForEffectY
_TakiSetupForEffectY:
; Set up effect storage start:
; if we're effect 0 it's start of storage
; otherwise it's prev element's
sty kZpCurEffect
sta TAKI_ZP_DSP_MODE
tya
asl ; y * 2
tay
@SetupEffStorage:
cpy #$00
bne @NotFirst ; if y != 0 then branch
sty TAKI_ZP_EFF_STORAGE_L ; storing y (== 0)
lda TakiVarEffectsAllocStartPage
sta TAKI_ZP_EFF_STORAGE_H
jmp @SetupEffStorageEnd
@NotFirst:
dey ; y now at preceding eff's high byte
lda (kZpEffAllocTbl),y
sta TAKI_ZP_EFF_STORAGE_H
dey
lda (kZpEffAllocTbl),y
sta TAKI_ZP_EFF_STORAGE_L
iny
iny ; y: back to cur eff
@SetupEffStorageEnd:
lda (kZpEffAllocTbl),y
sta TAKI_ZP_EFF_STORAGE_END_L
iny
lda (kZpEffAllocTbl),y
sta TAKI_ZP_EFF_STORAGE_END_H
ldy kZpCurEffect
lda TAKI_ZP_DSP_MODE
rts
.export _TakiClearNoneEffect
_TakiClearNoneEffect:
lda _TakiVarActiveEffectsNum
sec
sbc #1
asl ; doubled for count-by-words
tay
; Is the most-recent effect dispatch, the NONE
; dispatch handler?
lda (kZpEffDispatchTbl),y
cmp #<TE_NONE
bne @done
iny
lda (kZpEffDispatchTbl),y
cmp #>TE_NONE
bne @done
; Most recent effect is NONE - remove it!
; (no dispatching needed, since it's NONE)
dec _TakiVarActiveEffectsNum
@done:
rts
.export _TakiEffectInitialize
_TakiEffectInitialize:
tya
pha
jsr _TakiClearNoneEffect
lda _TakiVarActiveEffectsNum
sta kZpCurEffect
asl ; times 2 to count words
tay
;; Set values in tables:
; dispatch handler in table
lda _TakiEffectInitializeFn
sta (kZpEffDispatchTbl),y
iny
lda _TakiEffectInitializeFn+1
sta (kZpEffDispatchTbl),y
; y is now 1 past
; end of allocation - initialize with
; start of storage area if eff.num == 0,
; otherwise with whatever the end of
; allocation was for the previous effect
; (which is also the start of the new
; effect's allocation, since it hasn't
; allocated anything yet)
cpy #1 ; y is one past, so 1 if we're at 0
bne @PrevEffAlloc
; we're effect 0, use start of storage
lda TakiVarEffectsAllocStartPage
sta TAKI_ZP_EFF_STORAGE_H
dey
lda #$00
sta TAKI_ZP_EFF_STORAGE_L
beq @FinishAlloc ; always
@PrevEffAlloc:
dey ; y -= 3, to get prev eff's end
dey
dey
lda (kZpEffAllocTbl),y
sta TAKI_ZP_EFF_STORAGE_L
iny
lda (kZpEffAllocTbl),y
sta TAKI_ZP_EFF_STORAGE_H
iny ; y at cur eff low byte
@FinishAlloc:
; Now actually store to effect's alloc entry
lda TAKI_ZP_EFF_STORAGE_L
sta TAKI_ZP_EFF_STORAGE_END_L
sta (kZpEffAllocTbl),y
iny
lda TAKI_ZP_EFF_STORAGE_H
sta TAKI_ZP_EFF_STORAGE_END_H
sta (kZpEffAllocTbl),y
; y is one past
; Initialize counter init and counter
lda TakiVarDefaultCountdown+1
sta (kZpEffCtrInitTbl),y
lda #$00
sta (kZpEffCtrValTbl),y
dey
sta (kZpEffCtrValTbl),y
lda TakiVarDefaultCountdown
sta (kZpEffCtrInitTbl),y
; y is at eff
tya ; save y to ZP
sta kZpCurEffect
; Increment number of effects
inc _TakiVarActiveEffectsNum
pla
tay
rts ; THE END
_TakiEffectInitializeFn:
.word $00
.export _TakiEffectInitializeFn
.export _TakiEffectDispatchCur
_TakiEffectDispatchCur:
ldy _TakiVarActiveEffectsNum
dey
jsr _TakiSetupForEffectY
tya
asl ; lookup by words
tay
lda (kZpEffDispatchTbl),y
sta @Dispatch+1
iny
lda (kZpEffDispatchTbl),y
sta @Dispatch+2
tya ; Y is at high byte
pha
lda TakiVarDispatchEvent
@Dispatch:
jsr $1000 ; OVERWRITTEN
pla
tay ; Y is at high byte
; save allocations
lda kZpCurEffStorageEndH
sta (kZpEffAllocTbl),y
dey
lda kZpCurEffStorageEndL
sta (kZpEffAllocTbl),y
rts
pvTickMode:
.byte TAKI_DSP_UNTICK
.export _TakiTick
_TakiTick:
TakiBranchUnlessFlag_ flagInTick, @NotInTick
rts
@NotInTick:
TakiSetFlag_ flagInTick
; Run all effect ticks
lda _TakiVarActiveEffectsNum
beq @TickLoopDone
; Mark animations as "in progress"
TakiSetFlag_ flagAnimationActive
ldy #0
inc TakiVarTickNum
@TickLoop:
; For each active effect, decrement the
; effect's timing counter, and send
; it a "tick" event if it should prepare
; to do a new frame, and an "untick" if
; it should not (the "untick" is primarily
; so that a similar amount of work is done
; for each effect, regardless of whether it
; "ticked" or not, so that animation
; jitter is mitigated.
jsr _TakiSetupForEffectY
tya
asl
tay ; y *= 2, for tables-of-addresses
; handle the counter
sec
lda (kZpEffCtrValTbl),y
sbc #1
sta (kZpEffCtrValTbl),y
bcs @NoTrip
iny ; borrow from high byte
lda (kZpEffCtrValTbl),y
sbc #0
sta (kZpEffCtrValTbl),y
dey
bcs @NoTrip
; counter underflowed!
; reset the counter
lda (kZpEffCtrInitTbl),y
sta (kZpEffCtrValTbl),y
iny
lda (kZpEffCtrInitTbl),y
sta (kZpEffCtrValTbl),y
dey
; mark tick (vs untick) event
lda #TAKI_DSP_TICK
sta pvTickMode
; also mark internal flag that a tick
; occurred (used by '+' in frame debug)
sta _TakiVarEffectFrameTicked
@NoTrip:
lda (kZpEffDispatchTbl),y
sta @pEffJsr+1
iny
lda (kZpEffDispatchTbl),y
sta @pEffJsr+2
ldy kZpCurEffect
lda pvTickMode
@pEffJsr:
jsr $1000 ; OVERWRITTEN
lda #TAKI_DSP_UNTICK
sta pvTickMode
ldy kZpCurEffect
iny
cpy _TakiVarActiveEffectsNum
bne @TickLoop
@TickLoopDone:
TakiUnsetFlag_ flagInTick
rts
.export _TakiVarEffectFrameTicked
_TakiVarEffectFrameTicked:
.byte 0
pDbgNoWordEnd:
scrcode "EFFECT NAME END NOT FOUND"
.byte 0
;; _TakiEffectFind
;;
;; Assumes running under TakiEffectDo_.
;;
;; Traverses available effects, looking for a name match
;; against the Taki command buffer starting at position
;; designated by register y.
;;
;; If successful: returns with carry unset,
;; y at next token, x pointing in
;; _TakiBuiltinEffectsTable at the
;; found dispath entry.
;;
;; If unsuccesful: returns with carry set,
;; y where it was on entry.
;;
;; Uses acc, x and y.
.export _TakiEffectFind
_TakiEffectFind:
sty @SavedY
; Find how long the command word is
jsr _TakiCmdFindWordEnd
cpy #0
bne @FoundEnd
; We never found the end of a word -
; yell and exit.
TakiDbgPrint_ pDbgNoWordEnd
jmp @NoEffFound
@FoundEnd:
; Save the found word length.
tya
sec
sbc @SavedY
sta @WordLn
; save start of word, for comparisons
lda kZpCmdBufL
clc
adc @SavedY
sta kZpEffSpecial2
lda kZpCmdBufH
adc #0 ; handle carry
sta kZpEffSpecial3
lda #$00
@FindEffLp:
cmp #.lobyte(_TakiNumBuiltinEffects)
beq @NoEffFound
asl ; double it so it points at words.
tax
; Get the effect's dispatch addr
; into the zero page
lda _TakiBuiltinEffectsTable,x
sta kZpEffSpecial0
inx
lda _TakiBuiltinEffectsTable,x
sta kZpEffSpecial1
; X is now at the high byte
; skip backwards, past words "flag" and "configAddr"
; to a tag name character count
lda kZpEffSpecial0
sec
sbc #$05
sta kZpEffSpecial0
bcs :+ ; need to borrow?
lda kZpEffSpecial1 ; handle borrow
sbc #$00
sta kZpEffSpecial1
:
ldy #$00 ; get the value there into y
lda (kZpEffSpecial0),y
cmp @WordLn ; does it match our word length?
bne @NextEffect ; no: try next effect
; YES: eff name same len as our word
; step back by that many bytes to start of eff name
lda kZpEffSpecial0
sec
sbc (kZpEffSpecial0),y
sta kZpEffSpecial0
bcs :+ ; need to borrow?
lda kZpEffSpecial1 ; handle borrow
sbc #$00
sta kZpEffSpecial1
:
ldy @WordLn ; y -> past end of word
@TagCmpLoop:
dey
bmi @EffFound ; checked all the chars? found it!
lda (kZpEffSpecial2),y
cmp (kZpEffSpecial0),y
bne @NextEffect
beq @TagCmpLoop
@NextEffect:
inx ; check next entry
txa
lsr ; halve it so it refers to number-of-entries
jmp @FindEffLp
@NoEffFound:
ldy @SavedY
sec
jmp @rts
@EffFound:
; -- X is at the high byte of dispatch handler
; so decrement it
dex
; set y to next token
lda @SavedY
clc
adc @WordLn
tay
@FindNxtTok:
lda (kZpCmdBufL),y
cmp #$A0 ; SPC
bne @AtNxtTok
iny
bne @FindNxtTok ; "always"
@AtNxtTok:
; clear carry to indicate success
clc
@rts:
rts
@SavedY:
.byte 0
@WordLn:
.byte 0
.export _TakiMySetCounter
_TakiMySetCounter:
; new value is in Y A
pha ; high
tya
pha ; low
lda kZpCurEffect
asl ; double for words
tay
pla ; low
sta (kZpEffCtrValTbl),y
iny
pla ; high
sta (kZpEffCtrValTbl),y
rts
.export _TakiMyGetCounter
_TakiMyGetCounter:
; value returned via Y A
; XXX
rts
.export _TakiMySetCounterInit
_TakiMySetCounterInit:
; new value is in Y A
pha ; high
tya
pha ; low
lda kZpCurEffect
asl ; double for words
tay
pla ; low
sta (kZpEffCtrInitTbl),y
iny
pla ; high
sta (kZpEffCtrInitTbl),y
rts
.export _TakiMyGetCounterInit
_TakiMyGetCounterInit:
; value returned via Y A
; XXX
rts