-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgame.asm
2992 lines (2500 loc) · 55.8 KB
/
game.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
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
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
PROCESSOR 6502
include "vcs.h"
include "macro.h"
MAPHEIGHT = 6
MAPWIDTH = 12
PLAYERHEIGHT = 9
LADDERHEIGHT = 11
LINESPERCELL = 9
MAP_CELL_WIDTH = 12
DIGITS_PTR_COUNT = 12
X_OFFSET_TO_RIGHT_FOR_MINING = 7
MIN_PLAYER_Y = 9
MAX_PLAYER_Y = 54
MAX_PLAYER_X = 140
INITIAL_PLAYER_LIVES = 3
MAX_PLAYER_LIVES = 8
LAVA_START_POS_LEFT = $05 ; x=0; y=5
LAVA_START_POS_RIGHT = $B5
INITIAL_LAVA_SLEEP = 8
LAVA_SLEEP_AFTER_PRIZE = 10
INITIAL_LAVA_DELAY = 29
MINIMUM_LAVA_DELAY = 10
MAX_LAVA_X = 11
;Main goals
GOALX1 = 2
GOALX2 = 130
GOALY = 12
;Colors
LIVES_BG = $80
SCORE_COLOR = 15
LADDERS_COLOR = $C6
GROUND_COLOR = $93
LAVA_COLOR_BEFORE = $34
LAVA_COLOR_AFTER = $14
LAVA_FROZEN_COLOR = $9A
SCORE_FOR_PRIZE = 10
SCORE_FOR_BRICK = 2
SCORE_FOR_LAVA = 48
MIN_DISTANCE_FROM_PRIZE = 18
DEATH_INTERVAL = 64
NO_ILLEGAL_OPCODES = 1 ; DASM needs it
;----------------------------------------------------
; RAM
;-----------------------------------------------------
SEG.U VARS
ORG $80
GAMEMAP0 ds MAPHEIGHT ;6 columns of the GameMap,
GAMEMAP1 ds MAPHEIGHT ;single cells are represented as bits
GAMEMAP2 ds MAPHEIGHT
GAMEMAP3 ds MAPHEIGHT
GAMEMAP4 ds MAPHEIGHT
GAMEMAP5 ds MAPHEIGHT
LAVAMAP0 ds MAPHEIGHT
LAVAMAP1 ds MAPHEIGHT
LAVAMAP2 ds MAPHEIGHT
LAVAMAP3 ds MAPHEIGHT
LAVAMAP4 ds MAPHEIGHT
LAVAMAP5 ds MAPHEIGHT
LADDER1X ds 1 ;Ladder X positions
LADDER2X ds 1
LADDER3X ds 1
LADDER4X ds 1
LADDER5X ds 1
PLAYERY ds 1 ; Player's Y position
PLAYERX ds 1 ; Player's X position
LAVA_POS ds 1 ;4 bits X, 4 bits Y
LAVA_TIMER ds 1 ;Hazzard's delay
LAVA_DELAY ds 1 ;Limit for the timer to increment
LAVA_SLEEP ds 1 ;Makes lava inactive
OLDPLAYERY ds 1 ;Fallback data when player colides with a wall
OLDPLAYERX ds 1
OLDPLAYER_FRAME ds 1
PLAYER_FLIP ds 1
RANDOM ds 1 ;random 8bit number
PLAYERPTR ds 2 ;16bit address of the active sprites's frame graphics
PLAYER_FRAME ds 1 ;frame index
PRIZE_SOUND_INTERVAL ds 1
DEATH_SOUND_INTERVAL ds 1
CURRENT_LAVA_COLOR ds 1
PRIZEX ds 1 ;hidden prize's location
CURRENT_PRIZE_Y ds 1
ROOMS_COMPLETED ds 1
GAME_STATE ds 1
SCORE_DIGITS_IDX ds 3 ;indexes of highscore digits, 4 bits - one digit
BUTTON_PRESSED ds 1 ;Is joystick button being pressed right now?
GENERATING ds 1 ;Is the map being generared at the moment?
SCREEN_FRAME ds 1
TEMPVARS ds 6
SCORE_PTR ds DIGITS_PTR_COUNT ; pointers to digit graphics
;-----------------------
; Overlays
;
ORG TEMPVARS
TMPNUM ds 1
TMPNUM1 ds 1
TEMPY ds 1
TEMP_X_INDEX ds 1 ; Temp variable used in drawing, and in input checking
LADDER_LINE_IDX ds 1
LINE_IDX ds 1 ; line counter for a map cell
;reusing gamemap0's empty 4 bits
ORG GAMEMAP0
;4 bit variables (max 16 values)
LAVA_DIR ds 1
PLAYER_LIVES ds 1
PRIZEY ds 1 ;randomly generated row number where the prize is located (1..4)
LAVA_ACCEL ds 1 ;timer for lava acceleration
ORG GAMEMAP3 ;these are used to hide ladders, 0 height - ladder is hidden, non zero, we're going to draw that amount of lines
LADDERHEIGHT1 ds 1
LADDERHEIGHT2 ds 1
LADDERHEIGHT3 ds 1
LADDERHEIGHT4 ds 1
LADDERHEIGHT5 ds 1
ORG LAVAMAP0
CURRENT_LADDER_Y ds 1
ORG LAVAMAP3
LAVA_STUCK ds 1 ;0 - lava is not stuck
MAP_ORIENTATION ds 1
;------------------------------------------------------
; 123 | 5 bytes free
;------------------------------------------------------
; ROM
SEG
ORG $F000 ;4K Rom , F8000 = 2K
Reset:
CLEAN_START ; from macro.h
lda #1
sta RANDOM
lda #%00010100 ;make thin ball-ray and the playfield on top of everything
sta CTRLPF
lda #0
sta SCREEN_FRAME
sta COLUBK ;black background everywhere
sta GAME_STATE
Main:
jsr Vsync
jsr VBlank
jsr Kernel
jsr Overscan
jmp Main
;--------------------------
EnterNewMap:
lda ROOMS_COMPLETED
lsr
sta TMPNUM
lda #INITIAL_LAVA_DELAY
cmp TMPNUM
bcc SetMinimumDelay
sec
sbc TMPNUM
jmp storeLavaDelay
SetMinimumDelay:
lda #MINIMUM_LAVA_DELAY
storeLavaDelay:
sta LAVA_DELAY
lda MAP_ORIENTATION
and #$0F
sta TMPNUM
;set player coordinates
lda #MAX_PLAYER_Y
sta PLAYERY
sta OLDPLAYERY
lda TMPNUM
beq heroOnLeft
lda #130
jmp storePlayerPos
heroOnLeft:
lda #3
storePlayerPos:
sta PLAYERX
sta OLDPLAYERX
lda #0
sta LAVA_TIMER
lda TMPNUM
sta LAVA_DIR
lda #INITIAL_LAVA_SLEEP
sta LAVA_SLEEP
sta GENERATING
sta TMPNUM1
lda TMPNUM
beq PutLavaOnLeft
lda #LAVA_START_POS_RIGHT
jmp StoreLavaPosition
PutLavaOnLeft:
lda #LAVA_START_POS_LEFT
StoreLavaPosition:
sta LAVA_POS
lda #1
sta GENERATING
jsr UpdateRandomNumber
and #11
tax
stx TEMP_X_INDEX ; saves the X of prize
lda PRIZE_X_POSSITIONS,x ; gets an appropriate position for the missile based on X
sta PRIZEX
jsr UpdateRandomNumber
and #3
clc
adc #1
sta PRIZEY
lda #255
sta CURRENT_PRIZE_Y
ldx #0
genloop:
lda GAMEMAP0,x
ora #128
sta GAMEMAP0,x
lda #$FF
sta GAMEMAP1,x
sta GAMEMAP2,x
sta GAMEMAP4,x
lda #$F0
sta GAMEMAP3,x
lda #%01111111
sta GAMEMAP5,x
lda #0
sta LAVAMAP0,x
sta LAVAMAP1,x
sta LAVAMAP2,x
sta LAVAMAP3,x
sta LAVAMAP4,x
sta LAVAMAP5,x
inx
cpx #MAPHEIGHT
bne genloop
lda TMPNUM
beq ClearMapOnLeft
;Clearing map on right
ldx #5
lda #%00000001
sta GAMEMAP5,x
jmp startGenerateLadders
ClearMapOnLeft:
ldx #5
lda #0
sta GAMEMAP0,x
lda #%00000111
sta GAMEMAP1,x
startGenerateLadders:
lda #4 ;inverted first y position
sta TEMPY
;----------
ladderLoop: ; let's generate a ladder for each of the map rows
jsr UpdateRandomNumber
and #11 ; limit to 0..11 range
tax ; and transfer to X register
ldy TEMPY
cpy #4
beq secondRowCheck
jmp compareLastRow
secondRowCheck:
cmp #2 ; don't put ladder in first two cells
bcc ladderLoop
compareLastRow:
cpy #0
beq lastRowCheck
jmp compareToPrev
lastRowCheck:
cmp #9 ;don't let place ladders near the exit point
bcs ladderLoop
cmp #2
bcc ladderLoop
compareToPrev:
cmp TMPNUM1
beq ladderLoop
stx TMPNUM1
cpx TEMP_X_INDEX ;compare ladder x with prize x
beq checkIfLadderYIsTheSame
jmp saveLadderPostionToRam
checkIfLadderYIsTheSame:
lda PRIZEY
and #$0F
cmp TEMPY
beq ladderLoop ;generate ladder one more time
saveLadderPostionToRam:
lda LADDER_X_POSSITIONS,x
ldy TEMPY
sta LADDER1X,y ; store sprite position to ram variable
nextLadder:
dec TEMPY
bpl ladderLoop
rts
;------------------------------------------
;X - ladder x
;TEMPY - ladder y
RemoveGroundForLadders:
lda MAP_3CELLS_LOOKUP,x
clc
adc TEMPY
tay
lda MAP_3CELLS_INTERSECTIONS,x
stx TMPNUM ;store x
cmp #1
beq onlyOneSegmentUsed
;two segments used for a map tile
lda GAMEMAP0,y + MAPHEIGHT
and MAP_CLEAR_PATTERN_BY_X_SEG2,x
sta GAMEMAP0,y + MAPHEIGHT
onlyOneSegmentUsed:
lda GAMEMAP0,y
and MAP_CLEAR_PATTERN_BY_X_SEG1,x
sta GAMEMAP0,y
rts
;------------------------------------------
; Fake subroutine
drawPlayfield:
sta COLUPF ;3 5
stx TEMP_X_INDEX ;3 8 save scanline index
ldx TMPNUM ;3 11
lda GAMEMAP0,x ;4 15
sta PF0 ;3 18
lda GAMEMAP1,x ;4 22
sta PF1 ;3 25
lda GAMEMAP2,x ;4 29
sta PF2 ;3 32
;------right side of the screen
lda GAMEMAP3,x ;4 36
sta PF0 ;3 39
lda GAMEMAP4,x ;4 46
sta PF1 ;3 49
lda GAMEMAP5,x ;4 55
sta PF2 ;3 58
;enable missile if a map row matches prize Y
lda #LADDERHEIGHT ;has nothing to do with ladders, just like this number
sbc LINE_IDX ; subtract current map tile line index
lsr ; A / 2
lsr ; A / 2
;A needs to be 2 for missile to be enabled
cpx CURRENT_PRIZE_Y ;3
beq enableMissile ;3
lda #0 ;2
enableMissile:
;---------------------------------------------
sta WSYNC ;finish the scanline
;---------------------------------------------
nop
nop
sta ENAM0 ;3 6 ; enables or disables missile depending on A
lda CURRENT_LAVA_COLOR ;3 9
sta COLUPF ;3 12
lda LAVAMAP0,x ;4 16
sta PF0 ;3 19
lda LAVAMAP1,x ;4 23
sta PF1 ;3 26
lda LAVAMAP2,x ;4 30
sta PF2 ;3 33
;------right side of the screen
lda LAVAMAP3,x ;4 37
sta PF0 ;3 40
lda LAVAMAP4,x ;4 44
sta PF1 ;3 47
nop ;2 49
lda LAVAMAP5,x ;4 53
sta PF2 ;3 56
lda #0 ;2 58 Lets turn off the playfield for one scanline
sta PF0 ;3 61
sta PF1 ;3 64
jmp exitDrawPlayfield ;3 67
;--------------------------------------------------
Kernel:
sta WSYNC
lda INTIM
bne Kernel ; wait for vsync timer
sta VBLANK
;------------
lda GAME_STATE
cmp #0
beq drawTitle
jmp drawGame
drawTitle:
jsr TitleScreen
jmp endofKernel
drawGame:
;--------------
sta WSYNC
;--------------
lda #4 ;2 2
sta TEMPY ;3 5 index for the second ladder
ldy #PLAYERHEIGHT ;2 7
sty TMPNUM1 ;3 10 store player scanline index
lda #MAPHEIGHT-1 ;2 12
sta TMPNUM ;3 15 bottom of the screenmap
lda #LINESPERCELL ;2 17
sta LINE_IDX ;3 20
ldy #0 ;2 22
sty LADDER_LINE_IDX ;3 25
lda PLAYER_FLIP ;3 33
sta REFP0 ;3 36
ldx #54 ;2 38 scanlines, max scanlines / 3
KERNEL_LOOP:
;------------------------------------------------------------------------
cpx PLAYERY ;3 13
bcs drawThePlayer ;3 16
lda LADDER_GFX,y ;4 20
sta GRP1 ;3 23
dey ;2 25
sty LADDER_LINE_IDX ;3 28
drawThePlayer:
ldy TMPNUM1 ;3 31
beq nope ;2 33 PLAYER_LINE_IDX == 0
cpx PLAYERY ;3 36 can we draw the player sprite?
bcs nope ;3 39 < PLAYERY
lda PLAYERCOLORS,y ;4 43 sets the player colors
sta COLUP0 ;3 47
lda (PLAYERPTR),y ;5 53 let's load a line from a sprite frame
sta GRP0 ;3 56 and store it to the Player0 sprite
dec TMPNUM1 ;5 61
nope:
ldy LADDER_LINE_IDX ;3 64
lda #GROUND_COLOR ;2 66
;----------------------------------------------------------------
sta WSYNC ;wait for the scanline to be drawn
;----------------------------------------------------------------
jmp drawPlayfield ;3 3; faking subroutine
;----------------------------
; 67
exitDrawPlayfield:
ldx LINE_IDX ;3 70 decrement current line count for one map cell
dex ;2 72
;---------------------------------------------
sta WSYNC
;---------------------------------------------
sta PF2 ;3 3 clearing the remaining playfield register
bne cont ;2 5 not all lines for a cell have been drawn, continue
ldx TEMPY ;3 8 load ladder index
lda LADDERHEIGHT1,x ;4 12 reset the ladder sprite
and #$0F ;2 14
tay ;2 16
dec TEMPY ;5 21 let's position next ladder, decrease ladder index
dec TMPNUM ;5 26 move to next map cell
ldx #LINESPERCELL ;2 28 reset line count
;---------------------------------------------
sta WSYNC
;---------------------------------------------
cont:
stx LINE_IDX ;3 3 save current line count
ldx TEMP_X_INDEX ;3 6 restore X (scanline index)
;---------------------------------------------
dex ;2 8
bne KERNEL_LOOP ; ;2 10
;==================================================
doneDrawing:
jsr DrawScore
sta WSYNC ;let's draw an empty line
sta HMOVE ;3 3
lda PLAYER_LIVES
and #$0F
tax
lda LIVES_LOOKUP,x;2 5
sta NUSIZ0 ;3 8
sta NUSIZ1 ;3 11
lda #LIVES_BG ;2 13
sta COLUBK ;3 16
sta HMCLR ;3 let's clear HM
ldy #PLAYERHEIGHT
lives_bar_loop:
sta WSYNC
sta HMOVE ;3 3
cpx #2
bcc continueLives2
lda DWARF_GFX_0,y ;4 7
sta GRP0 ;3 10
cpx #3
bcc continueLives2
sta GRP1 ;3 17
cpx #6
bne continueLives
;6 lives
SLEEP 22
lda #0
sta GRP1
continueLives:
cpx #4
bne continueLives2
;4 lives
SLEEP 12
lda #0
sta GRP1
continueLives2:
dey ;2 35
bne lives_bar_loop ;3
endofKernel:
rts
;--------------------------------------------------------------
DrawScore:
lda #0
sta GRP0
sta GRP1
sta REFP0 ;3 turn off mirroring
sta REFP1
lda #%00000011 ;2
sta NUSIZ0 ;3
sta NUSIZ1 ;3
sta WSYNC ;let's draw an empty line
SLEEP 36
sta RESP0 ;2 reset sprite pos
sta RESP1
sta HMCLR
lda #$10 ;2 move p2 sprite left a bit
sta HMP1 ;3
lda #SCORE_COLOR ;2 47
sta COLUP1 ;3 50
sta COLUP0 ;3 53
sta WSYNC
sta HMOVE ;3 3
SLEEP 27 ;27 30
lda #%00000011 ;2 32
sta NUSIZ0 ;3 35
sta NUSIZ1 ;3 38
sta VDELP0 ;3 41
sta VDELP1 ;3 44
ldy #PLAYERHEIGHT - 1 ;2 46
sty TEMP_X_INDEX ;3 49
sta HMCLR ;3 51
score_line_loop:
lda (SCORE_PTR+2),y ;5 56
tax ;2 58
lda (SCORE_PTR),y ;5 63
sta WSYNC
nop
sty TEMP_X_INDEX ;3 6
sta TMPNUM ;3 9
lda (SCORE_PTR+10),y ;5 14
sta GRP0 ;3 17
lda (SCORE_PTR+8),y ;5 22
sta GRP1 ;3 25
lda (SCORE_PTR+6),y ;5 30
sta GRP0 ;3 33
lda (SCORE_PTR+4),y ;5 38
ldy TMPNUM ;3 41
sta GRP1 ;3 44
stx GRP0 ;3 47
sty GRP1 ;3 50
sta GRP0 ;3 53
ldy TEMP_X_INDEX ;3
dey ;2
bpl score_line_loop ;2
lda #0 ;2
sta VDELP0 ;3
sta VDELP1 ;3
sta HMCLR
rts
;---------------------------------------------------------------
TitleScreen:
sta WSYNC
lda #15 ;15 * 8 = 120
sta TMPNUM
ldy #7
titleLoop:
sta WSYNC ;finish the scanline
;---------------------------------------------
lda TMPNUM ;3 3
adc TMPNUM1 ;3 6
sta COLUPF ;3 9
lda TITLE0,y ;4 13
sta PF0 ;3 16
lda TITLE1,y ;4 20
sta PF1 ;3 23
lda TITLE2,y ;4 27
sta PF2 ;3 30
;------right side of the screen
lda TITLE3,y ;4 34
sta PF0 ;3 37
lda TITLE4,y ;4 41
sta PF1 ;3 44
lda TITLE5,y ;4 48
sta PF2 ;3 51
ldx TMPNUM
dex
stx TMPNUM
beq decreaseIdx
jmp titleLoop
decreaseIdx:
lda #15
sta TMPNUM
dey
bpl titleLoop
lda #0 ;2 58 Lets turn off the playfield for one scanline
sta PF0 ;3 61
sta PF1 ;3 64
sta PF2
sta WSYNC
ldx #20
emptyLoop:
sta WSYNC
dex
bne emptyLoop
jsr DrawScore
ldx #21 ;remaining scanlines
emptyLoop1:
sta WSYNC
dex
bne emptyLoop1
sta WSYNC
sta HMOVE ;3 3
lda #%00000011 ;2 35
sta NUSIZ0 ;3 38
sta NUSIZ1 ;3 41
sta VDELP0 ;3 44
sta VDELP1 ;3 47
ldy #12 ;2 49
sty TEMP_X_INDEX ;3 51
lda #$09
sta COLUP0
sta COLUP1
bitmap_line_loop:
ldy TEMP_X_INDEX ;3 57
lda CPR_6,y
sta TMPNUM
sta WSYNC
lda CPR_1,y ;4 61
sta GRP0 ;3 64
nop
lda CPR_2,y ;4 68
sta GRP1 ;3 71
lda CPR_3,y ;4 13
sta GRP0 ;3 16
nop
nop
nop
ldx CPR_5,y ;4 27
lda CPR_4,y ;4 31
ldy TMPNUM ;3 34
sta GRP1 ;3 37
stx GRP0 ;3 40
sty GRP1 ;3 43
sta GRP0 ;3 46
dec TEMP_X_INDEX ;5 51
bpl bitmap_line_loop ;2 53
lda #0 ;2
sta VDELP0 ;3
sta VDELP1 ;3
rts
;-------------------------------------------------
;TMPNUM1 - hundreds and thousands
;TEMPY - tens and hundreds of thousands
CheckScoreForBonuses:
lda TMPNUM1
and #$0F
sta TMPNUM
lda SCORE_DIGITS_IDX+1
and #$0F
cmp TMPNUM
bne scoreHasChanged
jmp noBonuses
scoreHasChanged:
cmp #5 ;500,1500,2500 etc.
beq addLife
jmp noBonuses
addLife:
lda PLAYER_LIVES
and #$0F
tax
inx
cpx #MAX_PLAYER_LIVES ;max lives
bcs noBonuses
;save lives to ram
stx TMPNUM
lda PLAYER_LIVES
and #$F0
ora TMPNUM
sta PLAYER_LIVES
lda #32
sta PRIZE_SOUND_INTERVAL
noBonuses:
rts
;---------------------------------------------------------------
Overscan:
sta WSYNC
lda #2
sta VBLANK
lda #34
sta TIM64T
;some game logic here
lda GENERATING
cmp #1
beq notColliding
;----------
lda DEATH_SOUND_INTERVAL
bne notColliding ;if the character dies
jsr LadderCollision
;Let's check PLAYER-PLAYFIELD collision
bit CXP0FB
bpl notColliding
;so the player is colliding with the playfield
lda LAVA_SLEEP
bne dealWithMining
;let's check if the player collides with the lava
jsr CalcLavaCollision
dealWithMining:
lda PLAYER_FRAME
cmp #%00011111
bne notMining
;player is coliding with the playfield and swings his axe
lda PLAYER_FLIP
cmp #0 ; facing right
bne checkCellCollision
lda PLAYERX
adc #X_OFFSET_TO_RIGHT_FOR_MINING ;need to add a bit to player x, when it's facing right
sta PLAYERX
checkCellCollision:
lda PLAYERX
ldx #0
divx:
inx
sbc #MAP_CELL_WIDTH
bcs divx
dex ;playerX / 12 - 1
cpx #MAPWIDTH
bcs doneMining ; nope, the x >= MAPWIDTH
stx TMPNUM;
lda PLAYERY
ldx #0
divy:
cmp #10
bcc doneDividing
sec
sbc #10
inx
jmp divy
doneDividing:
lda PLAYERY
cmp Y_POSITIONS_WHERE_YOU_CAN_MINE,x
bne notMining ;don't let mine while climbing the ladders
stx TEMPY
jsr Mine
lda SCORE_DIGITS_IDX+1
sta TMPNUM1
lda SCORE_DIGITS_IDX+2
sta TEMPY
lda TEMP_X_INDEX ;score is stored here
ldx #0
ldy #0
jsr IncrementScore
jsr CheckScoreForBonuses
doneMining:
;---- Let's restore the X
lda PLAYER_FLIP
cmp #0 ; facing right
bne notColliding ;let's not reset the animation frame
lda PLAYERX
clc
sbc #X_OFFSET_TO_RIGHT_FOR_MINING
sta PLAYERX
jmp notColliding
notMining: ; some kind of collision
lda OLDPLAYERX ; let's restore previous player state before the collision
sta PLAYERX
lda OLDPLAYERY
sta PLAYERY
lda OLDPLAYER_FRAME
sta PLAYER_FRAME
notColliding:
bit CXM0P ;player vs missile(prize)
bvs hideDemPrize ;the 6th bit is set
jmp OverscanLoop
hideDemPrize:
lda #32 ;some other value than 255
sta CURRENT_PRIZE_Y
sta PRIZE_SOUND_INTERVAL
lda ROOMS_COMPLETED
lsr
clc
adc #LAVA_SLEEP_AFTER_PRIZE
sta LAVA_SLEEP ;freeze lava
;--
lda SCORE_DIGITS_IDX+1
sta TMPNUM1
lda SCORE_DIGITS_IDX+2
sta TEMPY
lda #SCORE_FOR_PRIZE
ldy #0
ldx #0
jsr IncrementScore
jsr CheckScoreForBonuses
;checkLadderCollision:
OverscanLoop:
sta WSYNC
lda INTIM
bne OverscanLoop