-
Notifications
You must be signed in to change notification settings - Fork 0
/
enemy_handler.dasm
507 lines (439 loc) · 10.2 KB
/
enemy_handler.dasm
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
;;;; Constants
ENEMY_HIT_PALETTE_FRAMES EQM $05
oam_ram_x = $0203
oam_ram_y = $0200
oam_ram_spr = $0201
oam_ram_att = $0202
oam_enemy_sprites = $0220
enemy_ram_type = $0300
enemy_ram_hp = $0301
enemy_ram_x = $0302
enemy_ram_y = $0303
enemy_ram_pc = $0304
enemy_ram_ac = $0305
enemy_ram_hc = $0306
enemy_ram_ex = $0307
enemy_spawn_delegator: subroutine
; a = enemy type id
; x = enemy ram offset
sta enemy_ram_type,x
tay
sty temp00 ; enemy type
; do hit point maths
; hp * (game difficulty + 1)
lda enemy_hitpoints_table,y
sta temp01 ; enemy hp
lda #$01
clc
adc game_difficulty
tay
lda #$00
.enemy_hp_loop
adc temp01
dey
bne .enemy_hp_loop
; save hp result
sta enemy_ram_hp,x
; jump to enemy type spawner
lda temp00 ; enemy type
clc
adc #enemy_spawn_jump_table_offset
jmp jump_to_subroutine
enemy_do_nothing: subroutine
jmp update_enemies_handler_next
sprite_4_set_palette: subroutine
; a = palette id
; x = enemy ram offset
; y = oam ram offset
jsr enemy_set_palette
sta oam_ram_att+$04,y
sta oam_ram_att+$08,y
sta oam_ram_att+$0c,y
rts
sprite_4_set_palette_no_process: subroutine
; a = palette id
; y = oam ram offset
sta oam_ram_att+$00,y
sta oam_ram_att+$04,y
sta oam_ram_att+$08,y
sta oam_ram_att+$0c,y
rts
sprite_4_set_sprite: subroutine
; a = top left tile id
; y = oam ram offset
sta oam_ram_spr,y
clc
adc #$01
sta oam_ram_spr+$04,y
adc #$0f
sta oam_ram_spr+$08,y
adc #$01
sta oam_ram_spr+$0c,y
rts
sprite_4_set_sprite_flip: subroutine
; a = top left tile id
; y = oam ram offset
sta oam_ram_spr+$08,y
clc
adc #$01
sta oam_ram_spr+$0c,y
adc #$0f
sta oam_ram_spr,y
adc #$01
sta oam_ram_spr+$04,y
rts
sprite_4_set_x: subroutine
; a = x pos
; y = oam ram offset
sta oam_ram_x,y
sta oam_ram_x+$08,y
clc
adc #$08
sta oam_ram_x+$04,y
sta oam_ram_x+$0c,y
rts
sprite_4_set_y: subroutine
; a = y pos
; y = oam ram offset
sta oam_ram_y,y
sta oam_ram_y+$04,y
clc
adc #$08
sta oam_ram_y+$08,y
sta oam_ram_y+$0c,y
rts
enemy_fix_y_visible: subroutine
; a = y position to check
; returns new y position in a
cmp #255-8
bcc .not_wrapped_from_top
sta temp00
lda #255
sec
sbc #sprite_0_y
sta temp01
lda temp00
sec
sbc temp01
rts
.not_wrapped_from_top
cmp #sprite_0_y
bcc .not_wrapped_from_bottom
sec
sbc #sprite_0_y
.not_wrapped_from_bottom
rts
enemy_spawn_set_x_y_rng: subroutine
; x = enemy_ram_offset
jsr get_oam_offset_from_ram_offset
jsr get_next_random
bmi .rng_y
.rng_x
lda rng1
sta oam_ram_x,y
lda #$00
sta oam_ram_y,y
rts
.rng_y
lda #$00
sta oam_ram_x,y
jsr enemy_spawn_random_y_pos
sta oam_ram_y,y
rts
enemy_slot_offset_to_oam_offset:
; slots leftshift 3 times to get enemy_ram_offset
; 1 sprite slots : start at $300
; 16 slots using 1 sprite
byte $20,$24,$28,$2c,$30,$34,$38,$3c
byte $40,$44,$48,$4c,$50,$54,$58,$5c
; 2 sprite slots : start at $380
; 4 slots using 2 sprites
byte $60,$68,$70,$78
; 4 sprite slots : start at $3a0
; 8 slots using 4 sprites
byte $80,$90,$a0,$b0,$c0,$d0,$e0,$f0
; null terminater
byte $00
enemies_update_all: subroutine
lda boss_death_happening
bne .done
; set max darts launched per frame
lda #$03
sta dart_frame_max
; if player is dead despawn
lda player_health
bne .player_alive
beq player_dead_enemies_despawn
.player_alive
update_enemies_reset:
; set vars for processing
ldx #$00
stx enemy_slot_id
stx enemy_ram_offset
ldy enemy_slot_offset_to_oam_offset,x
sty enemy_oam_offset
; cycle through all the slots
.handler_loop
ldx enemy_ram_offset
; get enemy type
lda enemy_ram_type,x
; not defined go next slot
beq .handler_next
tax
lda enemy_update_jump_table_lo,x
sta temp00
lda enemy_update_jump_table_hi,x
sta temp01
; setup collision detection enemy origin pos
ldx enemy_ram_offset
ldy enemy_oam_offset
lda oam_ram_x,y
sta collision_0_x
lda oam_ram_y,y
sta collision_0_y
jmp (temp00)
update_enemies_handler_next:
.handler_next
; go to next enemy slot
inc enemy_slot_id
lda enemy_slot_id
asl
asl
asl
sta enemy_ram_offset
ldx enemy_slot_id
ldy enemy_slot_offset_to_oam_offset,x
sty enemy_oam_offset
bne .handler_loop
.done
rts
player_dead_enemies_despawn: subroutine
; enemies slide off left side of screen
; after player dies
ldx #$df
.loop
lda oam_enemy_sprites,x
beq .next
sec
sbc player_death_flag
sta oam_enemy_sprites,x
cmp #$f0
bcc .next
.despawn
lda #$00
sta oam_enemy_sprites,x
lda #$ff
sta oam_enemy_sprites-3,x
.next
dex
dex
dex
dex
cpx #$ff
bne .loop
lda wtf
and #$01
bne .dont_increase_velocity
inc player_death_flag
.dont_increase_velocity
rts
enemy_spawn_random_y_pos: subroutine
jsr get_next_random
lsr
clc
adc #$10
rts
game_difficulty_damage_table:
;hits to die 17 10 7 6
byte #15, #26, #37, #48
;hits to die 13 10 7 5
;byte #20, #26, #37, #58
;hits to die 23 17 11 5
;byte #11, #15, #25, #58
;hits to die 5 4 3 2
;byte #58, #77, #109, #191
enemy_gives_damage: subroutine
ldy game_difficulty
lda game_difficulty_damage_table,y
sta player_damage
jsr player_take_damage
jsr sfx_player_damage
rts
enemy_handle_damage_and_death: subroutine
; x = enemy ram offset
; y = oam ram offset
lda #$00
sta enemy_dmg_accumulator
; handle bullet collisions
jsr player_bullet_collision_handler
jsr player_collision_detect
beq .no_collision
; handle player collision
; player damage
jsr enemy_gives_damage
; enemy damage
lda enemy_dmg_accumulator
clc
adc #$02
sta enemy_dmg_accumulator
.no_collision
; handle bomb explosion
lda bomb_counter
beq .no_bomb_damage
lda wtf
and #1
beq .no_bomb_damage
inc enemy_dmg_accumulator
.no_bomb_damage
; fix y register
ldy enemy_oam_offset
; handle damage accumulated
lda enemy_dmg_accumulator
bne .hit
rts
.hit
lda enemy_ram_hp,x
sec
sbc enemy_dmg_accumulator
sta enemy_ram_hp,x
bcc .dead
lda #ENEMY_HIT_PALETTE_FRAMES
sta enemy_ram_hc,x
jsr sfx_enemy_damage
rts
.dead
; boss death check
lda boss_dmg_handle_true
beq .not_boss_death
inc boss_death_happening
inc boss_heart_stars
rts
.not_boss_death
jsr enemy_death_handler
; return to enemy handler not cycle
pla
pla
jmp update_enemies_handler_next
enemy_set_palette: subroutine
; checks/handles hit palette counter
; a = enemy normal palette
; x = enemy ram offset
; y = oam ram offset
; leaves correct palette id in a
; can be applied to extra sprites of larger enemy
clc ; set carry for branching on return
sta temp00
lda enemy_ram_hc,x
beq .use_enemy_palette
.use_hit_palette
dec enemy_ram_hc,x
lda temp00
and #%11111100
sta oam_ram_att,y
rts
.use_enemy_palette
lda temp00
sta oam_ram_att,y
rts
; 16 1 sprite enemies
; 4 2 sprite enemies
; 8 4 sprite enemies
; 28 total on screen enemies / entities
; 1 sprite can occupy all slots
; 2 sprite can occupy 12 slots
; 4 sprite restricted to their 8 slots
get_oam_offset_from_ram_offset: subroutine
; x = slot offset
; returns oam offset in y
stx temp00
txa
lsr
lsr
lsr
tax
ldy enemy_slot_offset_to_oam_offset,x
ldx temp00
rts
get_enemy_slot_next: subroutine
; returns enemy_ram_offset in x
; works from the top down
lda #$d8
sec
.slot_loop
tax
stx temp00
lda $0300,x
beq .slot_found
lda temp00
sbc #$08
bcs .slot_loop
.no_slot
clc
.slot_found
rts
enemy_slot_from_type: subroutine
; y = enemy type id
; returns slot offset in x
ldx enemy_size_table,y
cpx #1
bne .not_size_1
jmp get_enemy_slot_1_sprite
.not_size_1
cpx #2
bne .not_size_2
jmp get_enemy_slot_2_sprite
.not_size_2
jmp get_enemy_slot_4_sprite
get_enemy_slot_1_sprite: subroutine
; returns enemy_ram offset in x
; carry cleared if found
; carry set if unfound
lda #$00
clc
.slot_loop
tax
stx temp00
lda $0300,x
beq .slot_found
lda #$08
adc temp00
cmp #$80
bne .slot_loop
.no_available_slot
sec
.slot_found
rts
get_enemy_slot_2_sprite: subroutine
; returns enemy_ram offset in x
lda #$80
clc
.slot_loop
tax
stx temp00
lda $0300,x
beq .slot_found
lda #$08
adc temp00
cmp #$a0
bne .slot_loop
.no_available_slot
sec
.slot_found
rts
get_enemy_slot_4_sprite: subroutine
; returns enemy_ram offset in x
lda #$a0
clc
.slot_loop
tax
stx temp00
lda $0300,x
beq .slot_found
lda #$08
adc temp00
cmp #$e0
bne .slot_loop
.no_available_slot
sec
.slot_found
rts