-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsprite.s
490 lines (461 loc) · 7.93 KB
/
sprite.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
.include "global.inc"
.export update_sprites
.segment "ZEROPAGE"
mob_tile: .res 1
mob: .res 1 ; current mob index
.segment "CODE"
; todo add case for >= 255 sprites, that way we can increase maxmobs
; todo add flicker for >= 8 sprites per scan line
.proc update_sprites
ldx #$00
; sprite zero for split-scrolling
sprite_zero:
lda #$18
sta $0200, x
lda #$0e
sta $0201, x
lda #$00
sta $0202, x
lda #$FC
sta $0203, x
inx
inx
inx
inx
render_mobs:
lda #$00
sta mob
render_mob:
; todo ensure we can see mob first, will need to clear OAM data after
;ldy mob
;jsr can_player_see
;bne next_mob
; get mob start tile
jsr get_mob_tile
sta mob_tile
ldy #$00
render_mob_loop:
; update sprite y pos
jsr get_mob_y
sta $0200, x
set_mob_tile:
lda mob_tile
sta $0201, x
jsr get_mob_attribute
sta $0202, x
; update sprite x pos
jsr get_mob_x
sta $0203, x
; add 4 to sprite index
txa
clc
adc #$04
tax
; finish loop if we've rendered 4 tiles (16x16 sprite)
iny
cpy #4
beq next_mob
continue_loop:
; increment mob tile
cpy #2
beq next_tile_row
inc mob_tile
jmp render_mob_loop
next_tile_row:
; increment to next row
lda mob_tile
clc
adc #$F ; add 15 to get to next row
sta mob_tile
jmp render_mob_loop
next_mob:
lda mob
clc
adc #mob_size
sta mob
cmp #mobs_size
bne render_mob
rts
.proc clear_mob
; dead - Y to 0, todo anything *but* zero doesn't work here...
ldy a3
lda #$00
rts
.endproc
; getters for mob x & y based on screen pos
.proc get_mob_y
; clear mob if player and not playing
tya
bne continue
lda gamestate
cmp #GameState::playing
beq continue
jmp clear_mob
continue:
sty a3
ldy mob
; ensure mob is within screen bounds
jsr can_player_see_mob
bne clear_mob
jsr is_alive
beq adjust_mob_y
adjust_mob_y:
lda mobs + Mob::direction, y
ldy a3
; increment based on y value
cmp #Direction::down
beq adjust_mob_y_inverse
cpy #2
beq increase_y
cpy #3
beq increase_y
; get offset unchanged
ldy mob
jsr get_mob_yoffset
; restore original y
ldy a3
rts
increase_y:
; get offset
ldy mob
jsr get_mob_yoffset
; increase sprite row
clc
adc #$08
; restore original y
ldy a3
rts
adjust_mob_y_inverse:
cpy #0
beq increase_y
cpy #1
beq increase_y
; get offset unchanged
ldy mob
jsr get_mob_yoffset
; restore original y
ldy a3
rts
.endproc
.proc get_mob_x
; clear mob if player and not playing
tya
bne continue
lda gamestate
cmp #GameState::playing
beq continue
jmp clear_mob
continue:
sty a3
ldy mob
; ensure mob is within screen bounds
jsr can_player_see_mob
bne clear_mob
jsr is_alive
beq adjust_mob_x
jmp clear_mob
adjust_mob_x:
; increment based on x value
lda mobs + Mob::direction, y
ldy a3
cmp #Direction::left
beq adjust_mob_x_inverse
cpy #1
beq increase_x
cpy #3
beq increase_x
; get offset unchanged
ldy mob
jsr get_mob_xoffset
; restore original y
ldy a3
rts
increase_x:
; get offset unchanged
ldy mob
jsr get_mob_xoffset
; increase sprite row
clc
adc #$08
; restore original y
ldy a3
rts
adjust_mob_x_inverse:
cpy #0
beq increase_x
cpy #2
beq increase_x
; get offset unchanged
ldy mob
jsr get_mob_xoffset
; restore original y
ldy a3
rts
.endproc
.proc get_mob_attribute
sty a3
ldy mob
lda mobs + Mob::type, y
cmp #Mobs::player
beq normal
cmp #Mobs::goblin
beq green
cmp #Mobs::orc
beq dark
cmp #Mobs::ogre
beq dark
; dark + red
lda #3
sta a2
jmp get_dir_attr
normal:
lda #0
sta a2
jmp get_dir_attr
green:
lda #1
sta a2
jmp get_dir_attr
dark:
lda #2
sta a2
get_dir_attr:
ldy mob
lda mobs + Mob::direction, y
ldy a3
cmp #Direction::up
beq get_normal_attribute
cmp #Direction::right
beq get_normal_attribute
cmp #Direction::down
beq flip_vertical_attribute
; left - flip horizontal
lda #%01000000
ora a2
rts
get_normal_attribute:
lda #%00000000
ora a2
rts
flip_vertical_attribute:
lda #%10000000
ora a2
rts
.endproc
.endproc
; display sprites on bottom of screen debugging current PPUADDR
; y = offset from DEBUG_Y
; x = offset from DEBUG_SPRITE
.proc debug
DEBUG_Y = 200
DEBUG_X = 210
DEBUG_SPRITE = 100
tya
clc
adc #DEBUG_Y
tay
txa
clc
adc #DEBUG_SPRITE
tax
; ppu high
lda ppu_addr
; get high place tile
lsr
lsr
lsr
lsr
jsr get_hex_tile
; update sprite
sta $0201, x
tya
sta $0200, x
lda #0
sta $0202, x
lda #DEBUG_X
sta $0203, x
inx
inx
inx
inx
; ppu high
lda ppu_addr
; get low place tile
and #%00001111
jsr get_hex_tile
; update sprite
sta $0201, x
tya
sta $0200, x
lda #0
sta $0202, x
lda #DEBUG_X + 8
sta $0203, x
inx
inx
inx
inx
; ppu high
lda ppu_addr + 1
; get high place tile
lsr
lsr
lsr
lsr
jsr get_hex_tile
; update sprite
sta $0201, x
tya
sta $0200, x
lda #0
sta $0202, x
lda #DEBUG_X + 16
sta $0203, x
inx
inx
inx
inx
; ppu high
lda ppu_addr + 1
; get low place tile
and #%00001111
jsr get_hex_tile
; update sprite
sta $0201, x
tya
sta $0200, x
lda #0
sta $0202, x
lda #DEBUG_X + 24
sta $0203, x
inx
inx
inx
inx
rts
.endproc
; display sprites on bottom of screen debugging current player y
; y = offset from DEBUG_Y
; x = offset from DEBUG_SPRITE
.proc debug_ypos
DEBUG_Y = 200
DEBUG_X = 210
DEBUG_SPRITE = 100
tya
clc
adc #DEBUG_Y
tay
txa
clc
adc #DEBUG_SPRITE
tax
; ppu high
lda mobs + Mob::coords + Coord::ycoord
jsr get_hex_tile
; update sprite
sta $0201, x
tya
sta $0200, x
lda #0
sta $0202, x
lda #DEBUG_X
sta $0203, x
inx
inx
inx
inx
rts
.endproc
; get mob offset from left edge
;
; y: mob index to calculate
.proc get_mob_xoffset
; calculate offset based on xpos & screen_width
get_offset_xpos:
lda mobs + Mob::coords + Coord::xcoord, y
asl ; multiply by 2
sec
sbc xoffset
; multiply by 8 for pixels
asl
asl
asl
rts
.endproc
; get mob offset from top edge
;
; y: mob index to calculate
.proc get_mob_yoffset
; calculate offset based on xpos & screen_width
get_offset_ypos:
lda mobs + Mob::coords + Coord::ycoord, y
asl ; multiply by 2
sec
sbc yoffset
; multiply by 8 for pixels
asl
asl
asl
; offset for statusbar
clc
adc #8*4 - 2
rts
.endproc
.proc can_player_see_mob
; don't clobber x and y
tya
pha
txa
pha
lda mobs + Mob::coords + Coord::ycoord, y
asl
cmp yoffset
bcc failure
lda yoffset
clc
adc #screen_height
sta a2
lda mobs + Mob::coords + Coord::ycoord, y
asl
cmp a2
bcs failure
lda mobs + Mob::coords + Coord::xcoord, y
asl
cmp xoffset
bcc failure
lda xoffset
clc
adc #screen_width
sta a2
lda mobs + Mob::coords + Coord::xcoord, y
asl
cmp a2
bcs failure
; ensure player has seen tile before displaying mob
lda mobs + Mob::coords + Coord::xcoord, y
sta xpos
lda mobs + Mob::coords + Coord::ycoord, y
sta ypos
jsr was_seen
bne failure
; check player line of sight
ldy #0
jsr line_of_sight
bne failure
; success
pla
tax
pla
tay
lda #0
rts
failure:
pla
tax
pla
tay
lda #1
rts
.endproc
.segment "RODATA"
txt_hp: .asciiz "HP"