-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
animation.asm
440 lines (423 loc) · 7.44 KB
/
animation.asm
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
; step 0
led_on:
; turn LED ON - writing
bit PPUSTATUS
lda #$3F
sta PPUADDR
lda #$11
sta PPUADDR
lda <LED_COLORS
sta PPUDATA
lda <LED_COLORS + 1
sta PPUDATA
lda <LED_COLORS + 2
sta PPUDATA
jsr scroll_fix
; move to step 1
lda #LOW(write_game_name)
sta <ANIMATION_VECTOR
lda #HIGH(write_game_name)
sta <ANIMATION_VECTOR + 1
rts
; step 1
write_game_name:
lda <GAME_NAME_UPD
bne .end
inc <GAME_NAME_UPD
; write game code
PPU_to 10, 19
lda <TEXT_GAME_NAME
sta PPUDATA
lda <TEXT_GAME_NAME + 1
sta PPUDATA
lda <TEXT_GAME_NAME + 2
sta PPUDATA
jsr scroll_fix
.end:
; move to step 2
lda #LOW(write_disk_side)
sta <ANIMATION_VECTOR
lda #HIGH(write_disk_side)
sta <ANIMATION_VECTOR + 1
rts
; step 2
write_disk_side:
lda <DISK_SIDE_UPD
bne .end
inc <DISK_SIDE_UPD
; write side
PPU_to 21, 19
lda <TEXT_DISK_NUM
sta PPUDATA
PPU_to 23, 19
lda <TEXT_DISK_SIDE
sta PPUDATA
jsr scroll_fix
.end:
; move to step 3
lda #LOW(led_off)
sta <ANIMATION_VECTOR
lda #HIGH(led_off)
sta <ANIMATION_VECTOR + 1
rts
; step 3
led_off:
; turn LED OFF
bit PPUSTATUS
lda #$3F
sta PPUADDR
lda #$11
sta PPUADDR
lda #COLOR_REWIND_OFF
sta PPUDATA
lda #COLOR_READ_OFF
sta PPUDATA
lda #COLOR_WRITE_OFF
sta PPUDATA
jsr scroll_fix
; move to step 4
lda #LOW(write_read_block_counters)
sta <ANIMATION_VECTOR
lda #HIGH(write_read_block_counters)
sta <ANIMATION_VECTOR + 1
rts
; step 4
write_read_block_counters:
lda <READ_CNT_UPD
bne .end
inc <READ_CNT_UPD
; write block counters
PPU_to 8, 21
lda <TEXT_BLK_READ
sta PPUDATA
lda <TEXT_BLK_READ + 1
sta PPUDATA
PPU_to 11, 21
lda <TEXT_BLK_TOTAL
sta PPUDATA
lda <TEXT_BLK_TOTAL + 1
sta PPUDATA
jsr scroll_fix
.end:
; move to step 5
lda #LOW(write_written_block_counters)
sta <ANIMATION_VECTOR
lda #HIGH(write_written_block_counters)
sta <ANIMATION_VECTOR + 1
rts
; step 5
write_written_block_counters:
lda <WRITTEN_CNT_UPD
bne .end
inc <WRITTEN_CNT_UPD
; write block counters
PPU_to 19, 21
lda <TEXT_BLK_WRITTEN
sta PPUDATA
lda <TEXT_BLK_WRITTEN + 1
sta PPUDATA
PPU_to 22, 21
lda <TEXT_BLK_TOTAL
sta PPUDATA
lda <TEXT_BLK_TOTAL + 1
sta PPUDATA
jsr scroll_fix
.end:
; move to step 6
lda #LOW(animation_step_6)
sta <ANIMATION_VECTOR
lda #HIGH(animation_step_6)
sta <ANIMATION_VECTOR + 1
rts
; step 6
animation_step_6:
; move to step 7
lda #LOW(animation_step_7)
sta <ANIMATION_VECTOR
lda #HIGH(animation_step_7)
sta <ANIMATION_VECTOR + 1
rts
; step 7
animation_step_7:
; move to step 0
lda #LOW(led_on)
sta <ANIMATION_VECTOR
lda #HIGH(led_on)
sta <ANIMATION_VECTOR + 1
rts
precalculate_game_name:
; prepare write_game_name to update text during vblank
; all FDS code is located in the RAM,
; so we can patch it on the fly :>
lda <BLOCKS_READ
cmp #0
bne .not_0
lda #SPACE
sta <TEXT_GAME_NAME
sta <TEXT_GAME_NAME + 1
sta <TEXT_GAME_NAME + 2
sta <TEXT_DISK_NUM
sta <TEXT_DISK_SIDE
jmp .done
.not_0:
cmp #1
bne .end
; 3-letter game code
lda HEADER_CACHE + (55 - $10)
sec
sbc #$20
bmi .disk_number
tax
lda ascii, x
sta <TEXT_GAME_NAME
lda HEADER_CACHE + (55 - $11)
sec
sbc #$20
bmi .disk_number
tax
lda ascii, x
sta <TEXT_GAME_NAME + 1
lda HEADER_CACHE + (55 - $12)
sec
sbc #$20
bmi .disk_number
tax
lda ascii, x
sta <TEXT_GAME_NAME + 2
; disk number
.disk_number:
lda HEADER_CACHE + (55 - $16)
clc
adc #(SPACE + $11)
sta <TEXT_DISK_NUM
; side number
lda HEADER_CACHE + (55 - $15)
clc
adc #(SPACE + $21)
sta <TEXT_DISK_SIDE
.done:
lda #0
sta <GAME_NAME_UPD
sta <DISK_SIDE_UPD
.end:
rts
precalculate_block_counters:
; prepare write_block_counters to update text during vblank
; all FDS code is located in the RAM,
; so we can patch it on the fly :>
lda #0
sta READ_CNT_UPD
sta WRITTEN_CNT_UPD
lda <BLOCK_AMOUNT
beq .no_blocks
lda <BLOCKS_READ
jsr divide10
clc
adc #(SPACE + $10)
sta <TEXT_BLK_READ + 1
txa
clc
adc #(SPACE + $10)
sta <TEXT_BLK_READ
lda BLOCKS_WRITTEN
jsr divide10
clc
adc #(SPACE + $10)
sta <TEXT_BLK_WRITTEN + 1
txa
clc
adc #(SPACE + $10)
sta <TEXT_BLK_WRITTEN
lda BLOCK_AMOUNT
jsr divide10
clc
adc #(SPACE + $10)
sta <TEXT_BLK_TOTAL + 1
txa
clc
adc #(SPACE + $10)
sta <TEXT_BLK_TOTAL
rts
.no_blocks:
lda #SPACE
sta <TEXT_BLK_READ
sta <TEXT_BLK_READ + 1
sta <TEXT_BLK_WRITTEN
sta <TEXT_BLK_WRITTEN + 1
sta <TEXT_BLK_TOTAL
sta <TEXT_BLK_TOTAL + 1
rts
animation:
; check for vblank, do not wait for it
bit PPUSTATUS
bpl .end
.vblank:
; skip if PPU mode activated
lda <PPU_MODE_NOW
bne .end
; just to scheduled animation
jmp [ANIMATION_VECTOR]
.end:
rts
animation_init:
lda #LOW(led_on)
sta <ANIMATION_VECTOR
lda #HIGH(led_on)
sta <ANIMATION_VECTOR + 1
rts
animation_init_rewind:
jsr animation_init
lda #COLOR_REWIND_ON
sta <LED_COLORS
lda #COLOR_READ_OFF
sta <LED_COLORS + 1
lda #COLOR_WRITE_OFF
sta <LED_COLORS + 2
rts
animation_init_read:
jsr animation_init
lda #COLOR_REWIND_OFF
sta <LED_COLORS
lda #COLOR_READ_ON
sta <LED_COLORS + 1
lda #COLOR_WRITE_OFF
sta <LED_COLORS + 2
rts
animation_init_write:
jsr animation_init
lda #COLOR_REWIND_OFF
sta <LED_COLORS
lda #COLOR_READ_OFF
sta <LED_COLORS + 1
lda #COLOR_WRITE_ON
sta <LED_COLORS + 2
rts
blank_screen_on:
lda <PPU_MODE_NOW
beq .end
; disable rendering
jsr waitblank
; cache sprite coords
ldx #0
ldy #0
.sprites_cache_loop:
lda sprites, y
sta <SPRITES_Y_CACHE, x
iny
iny
iny
iny
inx
cpx #((sprites_end - sprites) / 4)
bne .sprites_cache_loop
; scroll
.scroll_loop:
ldx #4
.multi_loop:
inc <Y_OFFSET
; move every sprite
txa ; save X - line
pha
ldx #0
.move_sprite_loop:
txa ; save X - sprite #
pha
; sprite # -> sprite Y offset
asl A
asl A
tax
; need to move sprite?
lda SPRITES, x
cmp #$FF
beq .skip_sprite_move
; moving
dec SPRITES, x
.skip_sprite_move:
pla ; restore X - sprite #
tax
dec <SPRITES_Y_CACHE, x
inx
cpx #((sprites_end - sprites) / 4)
bne .move_sprite_loop
pla ; restore X - line
tax
; next line
dex
bne .multi_loop
; sync sprites
lda #0
sta OAMADDR
lda #HIGH(SPRITES)
sta OAMDMA
jsr waitblank
lda <Y_OFFSET
cmp #240
bne .scroll_loop
; blank screen
lda #%00000000
sta PPUMASK
jsr waitblank
bit PPUSTATUS
lda #(MEMORY_PPU_START >> 8)
sta PPUADDR
lda #(MEMORY_PPU_START & $FF)
sta PPUADDR
lda <OPERATION
cmp #OPERATION_WRITING
bne .end
; discarding byte when writing
lda PPUDATA
.end
rts
blank_screen_off:
lda <PPU_MODE_NOW
beq .end
; enable rendering
jsr waitblank
lda #%00011110
sta PPUMASK
; scroll
.scroll_loop:
ldx #4
.multi_loop:
dec <Y_OFFSET
; move every sprite
txa ; save X - line
pha
ldx #0
.move_sprite_loop:
txa ; save X - sprite #
pha
tay ; copy to Y too
; sprite # -> sprite Y offset
asl A
asl A
tax
; need to move sprite?
lda SPRITES, x
cmp SPRITES_Y_CACHE, y ; can't access as zero page
bne .skip_sprite_move
; moving
inc SPRITES, x
.skip_sprite_move:
pla ; restore X - sprite #
tax
inc <SPRITES_Y_CACHE, x
inx
cpx #((sprites_end - sprites) / 4)
bne .move_sprite_loop
pla ; restore X - line
tax
; next line
dex
bne .multi_loop
; sync sprites
lda #0
sta OAMADDR
lda #HIGH(SPRITES)
sta OAMDMA
jsr waitblank
lda <Y_OFFSET
bne .scroll_loop
.end
rts