-
Notifications
You must be signed in to change notification settings - Fork 27
/
invaders.asm
445 lines (343 loc) · 8.52 KB
/
invaders.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
441
442
443
; Troy's HBC-56 - 6502 - Invaders
;
; Copyright (c) 2021 Troy Schrapel
;
; This code is licensed under the MIT license
;
; https://github.com/visrealm/hbc-56
;
;
!src "hbc56kernel.inc"
!src "zeropage.asm"
;
; contants
;
SPRITE_PLAYER = 0
SPRITE_BULLET = 4
SPRITE_BOMB1 = 5
SPRITE_SPLAT = 3
SPRITE_LAST_LIFE = 1
SPRITE_HIDDEN_X = $C0
SPRITE_HIDDEN_Y = $00
BULLET_Y_LOADED = $D1
BULLET_SPEED = 3
BOMB_SPEED = 2
PLAYER_POS_Y = 153
LIVES_POS_Y = 170
BOMB_END_POS_Y = 152
FRAMES_PER_ANIM = 12
MAX_X = 6
!src "gamefield.asm"
!src "tile.asm"
!src "score.asm"
!src "audio.asm"
!src "shield.asm"
!src "bunker.asm"
!src "aliens.asm"
hbc56Meta:
+setHbcMetaTitle "HBC-56 INVADERS"
+setHbcMetaNES
rts
; -----------------------------------------------------------------------------
; main entry point
; -----------------------------------------------------------------------------
hbc56Main:
; any single-time setup?
restartGame:
+tmsDisableOutput
sei
+tmsDisableInterrupts
jsr audioInit
jsr tmsInitTextTable
+memcpy GAMEFIELD, initialGameField, 5 * 16
lda #9
sta GAMEFIELD_LAST_ROW
lda #10
sta GAMEFIELD_LAST_COL
lda #0
sta GAMEFIELD_FIRST_COL
lda #BULLET_Y_LOADED
sta BULLET_Y
sta INVADER_BOMB1_Y
lda #0
sta ANIM_FRAME
sta MOVE_FRAME
sta FRAMES_COUNTER
sta Y_DIR
sta TONE0
lda #0
sta INVADER_PIXEL_OFFSET
lda #1
sta GAMEFIELD_OFFSET_X
sta X_DIR
lda #4
sta GAMEFIELD_OFFSET_Y
lda #TMS_R1_SPRITE_MAG2
jsr tmsReg1ClearFields
lda #TMS_R1_SPRITE_16
jsr tmsReg1SetFields
+tmsCreateSpritePatternQuad 0, playerSprite
+tmsCreateSprite SPRITE_PLAYER, 0, 124, PLAYER_POS_Y, COLOR_SHIP
+tmsCreateSpritePatternQuad 1, bulletSprite
+tmsCreateSprite SPRITE_BULLET, 4, 124, BULLET_Y_LOADED, COLOR_BULLET
+tmsCreateSpritePatternQuad 2, explodeSprite
+tmsCreateSprite SPRITE_SPLAT, 8, SPRITE_HIDDEN_X, SPRITE_HIDDEN_Y, TMS_TRANSPARENT
+tmsCreateSpritePatternQuad 3, invaderBomb
+tmsCreateSprite SPRITE_BOMB1, 12, 124, BULLET_Y_LOADED, COLOR_BOMB
+tmsCreateSprite SPRITE_LAST_LIFE, 0, 48, LIVES_POS_Y, COLOR_LIVES
+tmsCreateSprite SPRITE_LAST_LIFE + 1, 0, 72, LIVES_POS_Y, COLOR_LIVES
lda #(TMS_GFX_PIXELS_X - TMS_SPRITE_SIZE2X) / 2 + 4
sta PLAYER_X
+tmsSetAddrColorTable
+tmsSendData COLORTAB, 32
+tmsColorFgBg TMS_WHITE, TMS_BLACK
jsr tmsSetBackground
jsr setupAliens
jsr setupScore
jsr setupShield
jsr setupBunker
jsr renderGameField
+tmsEnableOutput
+hbc56SetVsyncCallback gameLoop
+tmsEnableInterrupts
cli
@waitForExit
+nes1BranchIfNotPressed NES_SELECT, @waitForExit
+tmsDisableInterrupts
rts
nextFrame:
+tmsEnableInterrupts
rts
gameLoop:
+tmsDisableInterrupts
+nes1BranchIfNotPressed NES_B, skipFire
lda BULLET_Y
cmp #BULLET_Y_LOADED
bne skipFire
jsr audioFireBullet
lda PLAYER_X
clc
adc #4
tax
stx BULLET_X
ldy #PLAYER_POS_Y
sty BULLET_Y
+tmsSpritePosXYReg SPRITE_BULLET
skipFire
+nes1BranchIfNotPressed NES_LEFT, skipMoveLeft
dec PLAYER_X
dec PLAYER_X
skipMoveLeft
+nes1BranchIfNotPressed NES_RIGHT, skipMoveRight
inc PLAYER_X
inc PLAYER_X
skipMoveRight
ldx INVADER_BOMB1_X
clc
lda #BOMB_SPEED
adc INVADER_BOMB1_Y
sta INVADER_BOMB1_Y
tay
cpy #BOMB_END_POS_Y
bcc afterBombEnded
ldy #BULLET_Y_LOADED
sty INVADER_BOMB1_Y
afterBombEnded
+tmsSpritePosXYReg SPRITE_BOMB1
; set position to the bottom of the bomb
tya
clc
adc #14
tay
jsr pixelToTileXy
jsr tmsSetPosRead
+tmsGet
cmp #0
beq shieldNotBombed
cmp #32
bcs shieldNotBombed
; shield tile hit
jsr testShieldBombed
bcc shieldNotBombed
jsr audioBombHit
shieldNotBombed
lda BULLET_Y
cmp #BULLET_Y_LOADED
beq +
sec
sbc #BULLET_SPEED
tay
sty BULLET_Y
ldx BULLET_X
+tmsSpritePosXYReg SPRITE_BULLET
jsr pixelToTileXy
jsr tmsSetPosRead
+tmsGet
cmp #0
beq +
cmp #32
bcs ++
; shield tile hit
jsr testShieldPlayerBullet
+
-
jmp .testBulletPos
++
cmp #INVADER1_PATT ; is it an alien?
bcc -
; pixel-level collision with invader?
ldy HIT_TILE_PIX_Y
sta TEMP1
jsr tmsSetPatternRead
; load the pattern row to test
+tmsGet
; was an invader pixel hit?
jsr patternHitTest
beq -
; hit an invader tile
ldx HIT_TILE_X
ldy HIT_TILE_Y
jsr tileXyToGameFieldXy
stx TMP_X_POSITION
sty TMP_Y_POSITION
jsr gameFieldXyToPixelXy
+tmsSpritePosXYReg SPRITE_SPLAT
+tmsSetAddrSpriteColor SPRITE_SPLAT
lda TEMP1
jsr alienColor
+tmsPut
jsr killObjectAt ; returns score for hit object
jsr addScore
jsr updateScoreDisplay
jsr audioAlienHit
; make sure he disappears.. now
jsr renderGameField
ldy #0
sty BULLET_Y
.testBulletPos
ldy BULLET_Y
cpy #16
bcs +
ldy #BULLET_Y_LOADED
sty BULLET_Y
+tmsSpritePosXYReg SPRITE_BULLET
jsr audioBulletStop
+
.afterBulletCheck:
ldx PLAYER_X
ldy #PLAYER_POS_Y
+tmsSpritePosXYReg SPRITE_PLAYER
jsr audioBulletIncreasePitch
inc FRAMES_COUNTER
lda FRAMES_COUNTER
cmp #FRAMES_PER_ANIM
beq +
jmp nextFrame
+
+tmsSpriteColor SPRITE_SPLAT, TMS_TRANSPARENT
+tmsSpritePos SPRITE_SPLAT, SPRITE_HIDDEN_X, SPRITE_HIDDEN_Y
inc TONE0
lda TONE0
and #$03
cmp #0
bne +
jsr audioAlienToneLeft
jmp ++
+
cmp #2
bne +
jsr audioAlienToneRight
jmp ++
+
jsr audioAlienTonePause
bne ++
++
lda #0
sta FRAMES_COUNTER
lda ANIM_FRAME
clc
adc X_DIR
sta ANIM_FRAME
and #$03
bne +
jsr aliensSetTiles0
lda X_DIR
bpl .moveRight
-
jmp .endLoop
.moveRight
inc GAMEFIELD_OFFSET_X
lda GAMEFIELD_OFFSET_X
cmp #8
bne -
lda #-1
sta X_DIR
inc GAMEFIELD_OFFSET_Y
jmp .endLoop
+
cmp #1
bne +
jsr aliensSetTiles1
jmp .endLoop
+
cmp #2
bne +
jsr aliensSetTiles2
jmp .endLoop
+
jsr aliensSetTiles3
lda X_DIR
bmi .moveLeft
.endLoop:
lda INVADER_BOMB1_Y
cmp #BULLET_Y_LOADED
bne +
jsr randomBottomRowInvader
jsr gameFieldXyToPixelXy
stx INVADER_BOMB1_X
sty INVADER_BOMB1_Y
+
jsr renderGameField
jmp nextFrame
.moveLeft
dec GAMEFIELD_OFFSET_X
lda GAMEFIELD_OFFSET_X
cmp #1
bne .endLoop
lda #1
sta X_DIR
inc GAMEFIELD_OFFSET_Y
bne +
jmp restartGame
+
jmp .endLoop
testjumpOut3:
LDA #14
rts
testjumpOut2:
LDA #13
jsr testjumpOut3
rts
testjumpOut:
LDA #12
jsr testjumpOut2
rts
COLOR_TEXT = TMS_WHITE << 4 | TMS_BLACK
COLOR_SHIP = TMS_CYAN
COLOR_BULLET = TMS_WHITE
COLOR_BOMB = TMS_MAGENTA
COLOR_LIVES = TMS_DK_BLUE
COLORTAB:
!byte $00
!byte COLOR_SHIELD, COLOR_SHIELD, COLOR_SHIELD, $00 ; SHIELDS
!byte COLOR_TEXT, COLOR_TEXT ; NUMBERS
!byte COLOR_TEXT, COLOR_TEXT, COLOR_TEXT, COLOR_TEXT ; LETTERS
!byte $00,$00,$00,$00,$00
!byte $00 ; INVADER 1
!byte $00 ; INVADER 2
!byte $00 ; INVADER 3
!byte $00,$00,$00
!byte COLOR_BUNKER,$00 ; BOTTOM SCREEN
!byte $00,$00,$00,$00 ; TOP SCREEN
!byte $00,$00 ; TOP SCREEN
!src "patterns.asm"