-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.asm
executable file
·8290 lines (6894 loc) · 190 KB
/
main.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
TMP_PTR EQU $0A ; 2 bytes
TMP EQU $1A
SCRATCH_5C EQU $5C
MATH_TMPL EQU $6F
MATH_TMPH EQU $70
TMP_LOOP_CTR EQU $88
SCRATCH_A1 EQU $A1
SPRITE_EMPTY EQU #$00
SPRITE_BRICK EQU #$01
SPRITE_STONE EQU #$02
SPRITE_LADDER EQU #$03
SPRITE_ROPE EQU #$04
SPRITE_TRAP EQU #$05
SPRITE_INVISIBLE_LADDER EQU #$06
SPRITE_GOLD EQU #$07
SPRITE_GUARD EQU #$08
SPRITE_PLAYER EQU #$09
SPRITE_ALLWHITE EQU #$0A
SPRITE_BRICK_FILL0 EQU #$37
SPRITE_BRICK_FILL1 EQU #$38
SPRITE_GUARD_EGG0 EQU #$39
SPRITE_GUARD_EGG1 EQU #$3A
BLOCK_DATA EQU $DF ; 33 bytes
ROW_COUNT EQU $1D
SPRITE_NUM EQU $1E
ROW_ADDR EQU $0C ; 2 bytes
ROW_ADDR2 EQU $0E ; 2 bytes
HGR_PAGE EQU $1F ; 0x20 for HGR1, 0x40 for HGR2
MAX_GAME_COL EQU #27 ; 0x1B
MAX_GAME_ROW EQU #15 ; 0x0F
ROWNUM EQU $1B
COLNUM EQU $1C
MASK0 EQU $50
MASK1 EQU $51
COL_SHIFT_AMT EQU $71
GAME_COLNUM EQU $85
GAME_ROWNUM EQU $86
SCREENS_DIFFER EQU $52
DRAW_PAGE EQU $87 ; 0x20 for page 1, 0x40 for page 2
SAVED_RET_ADDR EQU $10 ; 2 bytes
HUNDREDS EQU $89
TENS EQU $8A
UNITS EQU $8B
SCORE EQU $8E ; 4 bytes, BCD format, tens/units in first byte.
LEVELNUM EQU $A6
LIVES EQU $98
NOTE_INDEX EQU $54
SOUND_DURATION EQU $0E00 ; 128 bytes
SOUND_PITCH EQU $0E80 ; 128 bytes
ENABLE_SOUND EQU $99 ; If 0, do not click speaker.
SPKR EQU $C030 ; Access clicks the speaker.
FRAME_PERIOD EQU $8C ; initially 6
PADDLE0_VALUE EQU $65
PADDLE1_VALUE EQU $66
PADDL0 EQU $C064
PADDL1 EQU $C065
PTRIG EQU $C070
INPUT_MODE EQU $95 ; 0xCA = Joystick mode (J), 0xCB = Keyboard mode (K)
; initially set to 0xCA
JOYSTICK_MODE EQU #$CA
KEYBOARD_MODE EQU #$CB
BUTN0 EQU $C061 ; Or open apple
BUTN1 EQU $C062 ; Or solid apple
KBD EQU $C000
KBDSTRB EQU $C010
ORG $0000
ZERO_PAGE_INITIAL:
HEX 4C 00 28 00 C0 68 0D 00 60 10 00 40 D0 3F 00 10
HEX D4 B4 9C FA B0 FF 37 FB FE FE FC EC 76 D7 E6 20
HEX 00 28 00 4C 00 00 00 D5 00 04 18 60 20 0F 0C D6
HEX FC FA FF 73 FD 8D 50 8E B5 B7 04 FF FB B7 00 1F
HEX 00 18 01 60 00 00 14 D8 E8 B7 91 9A 04 02 00 08
HEX 00 FD 1C 3C EC AC B4 38 C4 E9 B6 FF BA BB 2A FE
HEX 86 3E 85 3A A6 3E 86 40 A0 00 A5 3A 84 3C 85 3D
HEX A6 08 20 AE 00 C5 00 D0 F9 20 AE 00 C5 01 D0 F5
HEX 20 AE 00 C5 02 D0 01 20 8C C0 10 FB 06 85 3F BD
HEX 8C C0 10 FB 25 CA 00 3C C8 FF EC 0E 00 C0 BD 8C
HEX C0 10 FB C5 03 D0 BD 00 3D C6 40 D0 DA 60 BD 8C
HEX C0 10 FB 60 A2 D4 86 00 E8 86 01 E8 86 02 E8 86
HEX 03 A9 04 AA 60 FF 2A 29 B1 FF 48 2A 09 01 8A 49
HEX FF C9 10 AA E8 09 AA EA FF A2 00 48 CA D0 FC A2
HEX 0F BD F0 04 9D 00 01 CA D0 F7 9A 60 18 69 05 29
HEX 07 69 01 00 EA E8 CA E8 CA E8 CA C8 88 C8 88 C8
ORG $0100
STACK_INITIAL:
HEX BE B9 B7 B4 7B 63 90 61 FF 8B FE 07 FF 03 FF 5F
HEX 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 7A
HEX 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 7A
HEX 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 7A
HEX 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 7A
HEX 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 5A 7A
HEX 1D 7C FE 31 29 12 2D 60 FB 5D F7 72 D9 ED D1 A8
HEX FC FC FE 7B F7 FF 5E FF 35 FE EC CD BF EF 3D DD
HEX DF EF FF DF F7 7B 7F BF 7F BF ED E5 BF DF ED D4
HEX 01 2E 00 10 4A 84 48 83 02 22 50 82 9A 0C 46 04
HEX D7 19 AD 7F 4C C7 DF BE FF 8F 7B CF DF FF B3 DA
HEX 00 08 02 F2 00 05 86 00 09 F3 00 63 08 00 43 02
HEX 7F DF FD CF EB BF AF BF D5 FF C7 E7 BD FF BF 7B
HEX C9 E4 61 06 19 07 04 56 01 63 42 0F 93 43 C2 46
HEX 89 4A 00 52 05 2F 22 A3 A0 37 00 84 0A 01 80 40
HEX 00 09 00 06 17 26 FC 00 26 FC 6F BE 66 BE C6 42
ORG $0200
RANDOM_INIT_DATA:
INCLUDE "random_init_data.asm"
ORG $0C00
MORE_RANDOM_INIT_DATA:
INCLUDE "more_random_init_data.asm"
ORG $1A85
ROW_TO_OFFSET_LO:
INCLUDE "row_to_offset_lo_table.asm"
ROW_TO_OFFSET_HI:
INCLUDE "row_to_offset_hi_table.asm"
ORG $1C05
CURR_LEVEL_ROW_SPRITES_PTR_OFFSETS:
HEX 00 1C 38 54 70 8C A8 C4 E0 FC 18 34 50 6C 88 A4
CURR_LEVEL_ROW_SPRITES_PTR_PAGES:
HEX 08 08 08 08 08 08 08 08 08 08 09 09 09 09 09 09
CURR_LEVEL_ROW_SPRITES_PTR_PAGES2:
HEX 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0B 0B 0B 0B 0B 0B
LADDER_LOCS_COL EQU $0C00 ; 48 bytes
LADDER_LOCS_ROW EQU $0C30 ; 48 bytes
ORG $1C35
HALF_SCREEN_COL_TABLE:
; 28 cols of 5 double-pixels each
HEX 00 05 0a 0f 14 19 1e 23 28 2d 32 37 3c 41 46 4b
HEX 50 55 5a 5f 64 69 6e 73 78 7d 82 87
SCREEN_ROW_TABLE:
; 17 rows of 11 pixels each
HEX 00 0B 16 21 2C 37 42 4D 58 63 6E 79 84 8F 9A A5
HEX B5
COL_BYTE_TABLE:
; Byte number
HEX 00 01 02 04 05 07 08 0A 0B 0C 0E 0F 11 12 14 15
HEX 16 18 19 1B 1C 1E 1F 20 22 23 25 26
COL_SHIFT_TABLE:
; Right shift amount
HEX 00 03 06 02 05 01 04 00 03 06 02 05 01 04 00 03
HEX 06 02 05 01 04 00 03 06 02 05 01 04
HALF_SCREEN_COL_BYTE_TABLE:
HEX 00 00 00 00 01 01 01 02 02 02 02 03 03 03 04 04
HEX 04 04 05 05 05 06 06 06 06 07 07 07 08 08 08 08
HEX 09 09 09 0A 0A 0A 0A 0B 0B 0B 0C 0C 0C 0C 0D 0D
HEX 0D 0E 0E 0E 0E 0F 0F 0F 10 10 10 10 11 11 11 12
HEX 12 12 12 13 13 13 14 14 14 14 15 15 15 16 16 16
HEX 16 17 17 17 18 18 18 18 19 19 19 1A 1A 1A 1A 1B
HEX 1B 1B 1C 1C 1C 1C 1D 1D 1D 1E 1E 1E 1E 1F 1F 1F
HEX 20 20 20 20 21 21 21 22 22 22 22 23 23 23 24 24
HEX 24 24 25 25 25 26 26 26 26 27 27 27
HALF_SCREEN_COL_SHIFT_TABLE:
HEX 00 02 04 06 01 03 05 00 02 04 06 01 03 05 00 02
HEX 04 06 01 03 05 00 02 04 06 01 03 05 00 02 04 06
HEX 01 03 05 00 02 04 06 01 03 05 00 02 04 06 01 03
HEX 05 00 02 04 06 01 03 05 00 02 04 06 01 03 05 00
HEX 02 04 06 01 03 05 00 02 04 06 01 03 05 00 02 04
HEX 06 01 03 05 00 02 04 06 01 03 05 00 02 04 06 01
HEX 03 05 00 02 04 06 01 03 05 00 02 04 06 01 03 05
HEX 00 02 04 06 01 03 05 00 02 04 06 01 03 05 00 02
HEX 04 06 01 03 05 00 02 04 06 01 03 05
ORG $1DB2
DISK_BOOT_SECTOR_DATA:
HEX 01 20 58 FC 20 93 FE 20 89 FE A0 00 B9 34 08 F0
HEX 0E 20 F0 FD C9 8D D0 04 A9 09 85 24 C8 D0 ED A6
HEX 2B 9D 88 C0 8A 4A 4A 4A 4A 09 C0 8D 33 08 20 0C
HEX FD 4C 00 C6 8D 8D 8D 8D 8D 8D 8D CC CF C4 C5 A0
HEX D2 D5 CE CE C5 D2 A0 C4 C1 D4 C1 A0 C4 C9 D3 CB
HEX BA 8D AD AD AD AD AD AD AD AD AD AD AD AD AD AD
HEX AD AD AD AD AD AD AD AD 8D 8D C4 C9 D3 CB C5 D4
HEX D4 C5 A0 D7 C9 CC CC A0 CE CF D4 A0 C2 CF CF D4
HEX 8D 8D A0 C9 CE D3 C5 D2 D4 A0 CE C5 D7 A0 C4 C9
HEX D3 CB A0 C1 CE C4 8D A0 C8 C9 D4 A0 C1 A0 CB C5
HEX D9 A0 D4 CF A0 D2 C5 C2 CF CF D4 8D 8D A0 A0 A0
HEX A0 A0 A0 A0 A0 A0 A0 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
GUARD_PATTERN_OFFSET EQU $97
ORG $1EB2
PADDING:
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00
; Sprite routines
ORG $1F00
HI_SCORE_DATA:
HEX D2 CC D0 06 00 03 10 75 A0 A0 A0 05 00 02 81 25
HEX A0 A0 A0 02 00 01 74 25 A0 A0 A0 01 00 00 54 25
HEX A0 A0 A0 01 00 00 19 75 A0 A0 A0 01 00 00 15 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 CC CF C4 C5 A0 D2 D5 CE CE C5 D2 FF
ORG $5F00
RELOCATE0_ALIAS:
SUBROUTINE
LDA #$64
STA $0800
LDA #$76
STA $0801
LDA #$0D
STA $0802
; Copy 0x8100 bytes from $0800-$88FF to $3F00-$BFFF
LDY #$88
BEQ RELOCATE1 ; Never happens
STY SRC_PTR+1
LDA #$BF
STA DEST_PTR+1
LDX #$81
LDY #$00
STY SRC_PTR
STY DEST_PTR
.loop:
LDA (SRC_PTR),Y
STA (DEST_PTR),Y
INY
BNE .loop
DEC SRC_PTR+1
DEC DEST_PTR+1
DEX
BNE .loop
JMP RELOCATE1
RELOCATE1:
SUBROUTINE
LDX #<RELOCATE_TABLE
.loop:
LDA RELOCATE_TABLE-<RELOCATE_TABLE,X
STA .rd_insn+2
INX
LDA RELOCATE_TABLE-<RELOCATE_TABLE,X
STA .cmp_insn+1
INX
LDA RELOCATE_TABLE-<RELOCATE_TABLE,X
STA .wr_insn+2
INX
LDY #$00
.loop2:
.rd_insn:
LDA $0800,Y ; address replaced above
.wr_insn:
STA $0800,Y ; address replaced above
INY
BNE .loop2
INC .rd_insn+2
INC .wr_insn+2
LDA .rd_insn+2
.cmp_insn:
CMP #$FF ; comparison value replaced above
BNE .loop2
DEC RELOCATE_SEGMENT_COUNT
BNE .loop
JMP MAIN
UNUSED:
SUBROUTINE
LDX #$A8
.loop:
LDA #$00
.loop2:
.wr_insn:
STA $2000,X
INX
BNE .loop2
INC .wr_insn+2
LDA .wr_insn+2
CMP #$40
BNE .loop
; Fall through to MAIN
ORG $5F7D
MAIN:
LDA ROMIN_RDROM_WRRAM2
LDA ROMIN_RDROM_WRRAM2
LDA TXTCLR
LDA MIXCLR
LDA TXTPAGE1
LDA HIRES
LDX #$07
TXS
CLC
LDA #$01
AND #$A4
BEQ .short_delay_mode
SEC
; fall through to .short_delay_mode
ORG $5F9A
.short_delay_mode:
LDX #$22 ; Number of times to check for keyboard press (34).
LDY #$02 ; Number of times to do X checks (2).
; GAME_ROWNUM was initialized to 1, so we do 34*2*1 checks.
LDA KBDSTRB
LDA #JOYSTICK_MODE
JMP CHECK_FOR_BUTTON_DOWN
ORG $5FA6
RELOCATE_SEGMENT_COUNT:
HEX 04
RELOCATE_TABLE:
HEX 3F 47 00
HEX 47 5F 08
HEX 60 8E 60
HEX 8E C0 8E
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HEX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ORG $6000
JSR DETECT_LACK_OF_JOYSTICK
LDA #$01
JSR ACCESS_HI_SCORE_DATA_FROM_DISK
; Fallthrough to RESET_GAME
ORG $6008
RESET_GAME:
SUBROUTINE
JSR CLEAR_HGR1
LDA #$FF
STA .rd_table+1
LDA #$0E
STA .rd_table+2 ; RD_TABLE = 0x0EFF
LDY #$00
STY GAME_ROWNUM
STY GAME_MODE
STY DISK_LEVEL_LOC ; GAME_ROWNUM = DISK_LEVEL_LOC = GAME_MODE = 0
LDA #$20
STA HGR_PAGE
STA DRAW_PAGE ; HGR_PAGE = DRAW_PAGE = 0x20
.draw_splash_screen_row:
JSR ROW_TO_ADDR ; ROW_ADDR = ROW_TO_ADDR(Y)
LDY #$00
.loop:
INC .rd_table+1
BNE .rd_table
INC .rd_table+2 ; RD_TABLE++
.rd_table:
LDA $1A84 ; A <- *RD_TABLE ($1A84 is just a dummy value)
BEQ .end_of_row ; if A == 0: break
BPL .is_row_offset ; if A > 0: A -> Y, .loop
STA (ROW_ADDR),Y ; *(ROW_ADDR+Y) = A
INY ; Y++
BPL .loop ; While Y < 0x80 (really while not 00)
.is_row_offset:
TAY
BPL .loop ; Unconditional jump
.end_of_row:
INC GAME_ROWNUM
LDY GAME_ROWNUM
CPY #192
BCC .draw_splash_screen_row
STA TXTPAGE1
STA HIRES
STA MIXCLR
STA TXTCLR
JMP LONG_DELAY
ORG $6056
INIT_GAME_DATA:
LDA #0
STA SCORE
STA SCORE+1
STA SCORE+2
STA SCORE+3
STA GUARD_PATTERN_OFFSET
STA WIPE_MODE ; WIPE_MODE = SCORE = $97 = 0
STA $53
STA $AB
STA $A8 ; $53 = $AB = $A8 = 0
LDA #$9B ; 155
STA $A9 ; $A9 = 155
LDA #5
STA LIVES ; LIVES = 5
LDA GAME_MODE
LSR
; if GAME_MODE was 0 or 1 (i.e. not displaying high score screen or splash screen),
; play the game.
BEQ .put_status_and_start_game
; We were displaying the high score screen or splash screen
LDA #1
JSR ACCESS_HI_SCORE_DATA_FROM_DISK ; Read hi score data
CMP #$00
BNE .set_rwts_target
JSR BAD_DATA_DISK
JMP RESET_GAME
.set_rwts_target:
LDA $1FFF
BNE .use_dos_target
LDA INDIRECT_TARGET
LDX INDIRECT_TARGET+1
BNE .store_rwts_addr
.use_dos_target:
LDA DISABLE_INTS_CALL_RWTS_PTR
LDX DISABLE_INTS_CALL_RWTS_PTR+1
.store_rwts_addr:
STA RWTS_ADDR
STX RWTS_ADDR+1
.put_status_and_start_game:
JSR PUT_STATUS
STA TXTPAGE1
ORG $609F
.start_game:
LDX #$01
JSR LOAD_LEVEL
LDA #$00
STA KEY_COMMAND
STA KEY_COMMAND_LR
LDA GAME_MODE
LSR
; if GAME_MODE was 0 or 1 (i.e. not displaying high score screen
; or splash screen), play the game.
BEQ .play_game
; When GAME_MODE is 2:
JSR WAIT_KEY
LDA PLAYER_COL
STA GAME_COLNUM
LDA PLAYER_ROW
STA GAME_ROWNUM
LDA #SPRITE_PLAYER
JSR WAIT_FOR_KEY_WITH_CURSOR_PAGE_1
.play_game:
LDX #$00
STX DIG_DIRECTION
STX NOTE_INDEX
LDA GUARD_PATTERN_OFFSET
CLC
ADC GUARD_COUNT ; GUARD_COUNT + $97 can't be greater than 8.
TAY
LDX TIMES_3_TABLE,Y ; X = 3 * Y (goes up to Y=8)
LDA GUARD_PATTERNS_LIST,X
STA GUARD_PATTERNS
LDA GUARD_PATTERNS_LIST+1,X
STA GUARD_PATTERNS+1
LDA GUARD_PATTERNS_LIST+2,X
STA GUARD_PATTERNS+2
LDY GUARD_PATTERN_OFFSET
LDA $621D,Y
STA GUARD_GOLD_TIMER_START_VALUE
.game_loop:
JSR MOVE_PLAYER
LDA ALIVE
BEQ .died
JSR PLAY_SOUND
LDA GOLD_COUNT
BNE .check_player_reached_top
JSR ENABLE_NEXT_LEVEL_LADDERS
.check_player_reached_top:
LDA PLAYER_ROW
BNE .not_at_top
LDA PLAYER_Y_ADJ
CMP #$02
BNE .not_at_top
; Reached top of screen
LDA GOLD_COUNT
BEQ .level_cleared
CMP #$FF
BEQ .level_cleared ; level cleared if GOLD_COUNT == 0 or -1.
.not_at_top:
JSR HANDLE_TIMERS
LDA ALIVE
BEQ .died
JSR PLAY_SOUND
JSR MOVE_GUARDS
LDA ALIVE
BEQ .died
BNE .game_loop
.level_cleared:
INC LEVELNUM
INC DISK_LEVEL_LOC
INC LIVES
BNE .lives_incremented
DEC LIVES ; LIVES doesn't overflow.
.lives_incremented:
; Increment score by 1500, playing an ascending tune while doing so.
LDX #$0F
STX SCRATCH_5C
.loop2:
LDY #$01
LDA #$00
JSR ADD_AND_UPDATE_SCORE ; SCORE += 100
JSR APPEND_LEVEL_CLEARED_NOTE
JSR APPEND_LEVEL_CLEARED_NOTE
JSR APPEND_LEVEL_CLEARED_NOTE
DEC SCRATCH_5C
BNE .loop2
.start_game_:
JMP .start_game
.died:
DEC LIVES
JSR PUT_STATUS_LIVES
JSR LOAD_SOUND_DATA
HEX 02 40 02 40 03 50 03 50 04 60 04 60 05 70 05 70
HEX 06 80 06 80 07 90 07 90 08 A0 08 A0 09 B0 09 B0
HEX 0A C0 0A C0 0B D0 0B D0 0C E0 0C E0 0D F0 0D F0
HEX 00
.play_died_tune:
JSR PLAY_SOUND
BCS .play_died_tune
LDA GAME_MODE
LSR
BEQ .restore_enable_sound ; If GAME_MODE is 0 or 1
LDA LIVES
BNE .start_game_ ; We can still play.
; Game over
JSR RECORD_HI_SCORE_DATA_TO_DISK
JSR SPINNING_GAME_OVER
BCS .key_pressed
ORG $618E
LONG_DELAY:
JSR WAIT_KEY
LDX #$FF
LDY #$FF
LDA #$03
STA GAME_ROWNUM
; fall through to .poll_inputs
; Game loop
ORG $6199
.poll_inputs:
LDA INPUT_MODE
CHECK_FOR_BUTTON_DOWN:
CMP #KEYBOARD_MODE
BEQ .poll_keyboard ; If keyboard mode, skip check button presses.
LDA BUTN1
BMI .set_level_0_and_play_game
LDA BUTN0
BMI .set_level_0_and_play_game
; fall through to .poll_keyboard
ORG $61A9
.poll_keyboard:
LDA KBD
BMI .key_pressed
DEX
BNE .poll_inputs
DEY
BNE .poll_inputs
DEC GAME_ROWNUM
BNE .poll_inputs
; fall through to .no_button_or_key_timeout
ORG $61B8
.no_button_or_key_timeout:
LDA GAME_MODE
BNE .check_game_mode ; If GAME_MODE != 0, .check_game_mode.
; When GAME_MODE = 0:
LDX #$01
STX GAME_MODE ; Set GAME_MODE = 1
STX LEVELNUM
STX $AC
STX $9D ; LEVELNUM = $AC = $9D = 1
LDX ENABLE_SOUND
STX .restore_enable_sound+1 ; Save previous value of DNABLE_SOUND
STA ENABLE_SOUND
JMP INIT_GAME_DATA
.restore_enable_sound:
LDA #$00 ; Fixed up above
STA ENABLE_SOUND
LDA KBD
LDX $AC
BEQ .key_pressed
JMP LONG_DELAY
ORG $61DE
.check_game_mode:
; For game mode 1, reset and play the game.
; For game mode 0, display the high score screen.
CMP #$01
BNE .reset_game
BEQ .display_hi_score_screen ; Unconditional jump
ORG $61E4
.read_and_display_hi_score_screen:
LDA #$01
JSR ACCESS_HI_SCORE_DATA_FROM_DISK ; read hi score table
; fallthrough to .display_hi_score_screen
ORG $61E9
.display_hi_score_screen:
JSR HI_SCORE_SCREEN
LDA #$02
STA GAME_MODE ; GAME_MODE = 2
JMP LONG_DELAY
ORG $61F3
.reset_game:
JMP RESET_GAME
ORG $61F6
.key_pressed:
STA KBDSTRB ; Clear keyboard strobe
CMP #$85 ; if ctrl-E:
BEQ .start_level_editor
CMP #$8D ; if return key:
BEQ .read_and_display_hi_score_screen
; fall through to .button_pressed
ORG $6201
.set_level_0_and_play_game:
LDX #$00
STX DISK_LEVEL_LOC ; DISK_LEVEL_LOC = 0
INX
STX LEVELNUM ; LEVELNUM = 1
STX $9D
LDA #$02
STA GAME_MODE
JMP INIT_GAME_DATA
ORG $6211
.start_level_editor:
JMP LEVEL_EDITOR
ORG $6214
TIMES_3_TABLE:
HEX 00 03 06 09 0C 0F 12 15 18
ORG $621D
GUARD_GOLD_TIMER_START_VALUES:
HEX 26 26 2E 44 47 49 4A 4B 4C 4D 4E 4F 50
ORG $622A
APPEND_LEVEL_CLEARED_NOTE:
SUBROUTINE
LDA SCRATCH_5C
ASL
ASL
ASL
ASL ; pitch = SCRATCH_5C * 16
LDX #$06 ; duration
JSR APPEND_NOTE
JMP PLAY_SOUND
; Joystick routines
ORG $6238
LOAD_LEVEL:
SUBROUTINE
; Enter routine with X set to whether the level should be
; loaded verbatim or not.
STX VERBATIM
LDX #$FF
STX PLAYER_COL
INX
STX LADDER_COUNT
STX GOLD_COUNT
STX GUARD_COUNT
STX GUARD_NUM
STX DIG_ANIM_STATE
STX LEVEL_DATA_INDEX
STX TMP
STX GAME_ROWNUM
TXA
LDX #30
.loop1
STA BRICK_FILL_TIMERS,X
DEX
BPL .loop1
LDX #$05
.loop2
STA GUARD_RESURRECTION_TIMERS,X
DEX
BPL .loop2
LDA #$01
STA ALIVE ; Set player live
; A happens to also be DISK_ACCESS_READ.
JSR ACCESS_COMPRESSED_LEVEL_DATA
LDY GAME_ROWNUM
.row_loop:
LDA CURR_LEVEL_ROW_SPRITES_PTR_OFFSETS,Y
STA PTR1
STA PTR2
LDA CURR_LEVEL_ROW_SPRITES_PTR_PAGES,Y
STA PTR1+1
LDA CURR_LEVEL_ROW_SPRITES_PTR_PAGES2,Y
STA PTR2+1
LDA #$00
STA GAME_COLNUM
.col_loop:
LDA TMP ; odd/even counter
LSR
LDY LEVEL_DATA_INDEX
LDA DISK_BUFFER,Y
BCS .628c ; odd?
AND #$0F
BPL .6292 ; unconditional jump
.628c
LSR
LSR
LSR
LSR
INC LEVEL_DATA_INDEX
.6292
INC TMP
LDY GAME_COLNUM
CMP #10
BCC .629c
LDA #SPRITE_EMPTY ; sprite >= 10 -> sprite 0
.629c:
STA (PTR1),Y
STA (PTR2),Y
INC GAME_COLNUM
LDA GAME_COLNUM
CMP #28
BCC .col_loop ; loop while GAME_COLNUM < 28
INC GAME_ROWNUM
LDY GAME_ROWNUM
CPY #16
BCC .row_loop ; loop while GAME_ROWNUM < 16
JSR DRAW_LEVEL_PAGE2
BCC .end ; No error
LDA DISK_LEVEL_LOC
BEQ .reset_game
LDX #$00
STX DISK_LEVEL_LOC
INC GUARD_PATTERN_OFFSET
DEX
JMP LOAD_LEVEL
.end:
RTS
.reset_game:
JMP RESET_GAME
; Sound routines
ORG $62C7
COMPRESS_AND_SAVE_LEVEL_DATA:
SUBROUTINE
LDA #$00
STA LEVEL_DATA_INDEX
STA TMP
STA GAME_ROWNUM
.loop:
LDY GAME_ROWNUM
LDA CURR_LEVEL_ROW_SPRITES_PTR_OFFSETS,Y
STA PTR1
LDA CURR_LEVEL_ROW_SPRITES_PTR_PAGES,Y
STA PTR1+1
LDY #$00
STY GAME_COLNUM
.loop2:
LDA TMP
LSR
LDA (PTR1),Y
BCS .shift_left
STA SPRITE_NUM
BPL .next
.shift_left:
ASL
ASL
ASL
ASL
ORA SPRITE_NUM
LDY LEVEL_DATA_INDEX
STA DISK_BUFFER,Y
INC LEVEL_DATA_INDEX
.next:
INC TMP
INC GAME_COLNUM
LDY GAME_COLNUM
CPY #MAX_GAME_COL+1
BCC .loop2
INC GAME_ROWNUM
LDA GAME_ROWNUM
CMP #MAX_GAME_ROW+1
BCC .loop
LDA #DISK_ACCESS_WRITE
JMP ACCESS_COMPRESSED_LEVEL_DATA ; tailcall
ORG $630E
ACCESS_COMPRESSED_LEVEL_DATA:
SUBROUTINE
; Enter routine with A set to command: 1 = read, 2 = write, 4 = format
STA IOB_COMMAND_CODE
LDA GAME_MODE
LSR
; If GAME_MODE is 0 or 1, copy level data from image
BEQ .copy_level_data_from_image
; Otherwise, read/write/format level on disk
LDA DISK_LEVEL_LOC
LSR
LSR
LSR
LSR
CLC
ADC #$03
STA IOB_TRACK_NUMBER ; track 3 + (DISK_LEVEL_LOC >> 4)
LDA DISK_LEVEL_LOC
AND #$0F
STA IOB_SECTOR_NUMBER ; sector DISK_LEVEL_LOC & 0x0F
LDA #<DISK_BUFFER
STA IOB_READ_WRITE_BUFFER_PTR
LDA #>DISK_BUFFER
STA IOB_READ_WRITE_BUFFER_PTR+1 ; IOB_READ_WRITE_BUFFER_PTR = 0D00
LDA #$00
STA IOB_VOLUME_NUMBER_EXPECTED ; any volume
ACCESS_DISK_OR_RESET_GAME:
LDY #<DOS_IOB
LDA #>DOS_IOB
JSR JMP_RWTS
BCC .end
JMP RESET_GAME ; On error
.end:
RTS
.copy_level_data_from_image:
LDA LEVELNUM ; 1-based
CLC
ADC #$9E
STA ROW_ADDR+1
LDY #$00
STY ROW_ADDR ; ROW_ADDR <- 9E00 + LEVELNUM * 0x100
.copyloop:
LDA (ROW_ADDR),Y
STA DISK_BUFFER,Y
INY
BNE .copyloop
RTS
ORG $6359
ACCESS_HI_SCORE_DATA_FROM_DISK:
SUBROUTINE
STA IOB_COMMAND_CODE
LDA #$0C
STA IOB_TRACK_NUMBER
LDA #$0F
STA IOB_SECTOR_NUMBER
LDA #<HI_SCORE_DATA
STA IOB_READ_WRITE_BUFFER_PTR
LDA #>HI_SCORE_DATA
STA IOB_READ_WRITE_BUFFER_PTR+1
LDA #$00
STA IOB_VOLUME_NUMBER_EXPECTED
LDY #<DOS_IOB
LDA #>DOS_IOB
JSR INDIRECT_RWTS
BCC .no_error
JMP RESET_GAME
.no_error:
LDY #$0A
LDA #$00
STA MASK0 ; temp storage
.loop:
LDA HI_SCORE_DATA+244,Y
EOR HI_SCORE_DATA_MARKER,Y
ORA MASK0
STA MASK0
DEY
BPL .loop
LDA MASK0
BEQ .all_zero_data
LDA #$00
RTS
.all_zero_data:
LDA #$01
LDX $1FFF