-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathannotations.txt
3126 lines (2924 loc) · 190 KB
/
annotations.txt
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
Reset:
; Execution begins here on power-up and reset.
0000: 00 NOP ; This provides a slot ...
0001: 00 NOP ; ... to put in a JP for ...
0002: 00 NOP ; ... development
0003: C3 D4 18 JP $18D4 ; Continue startup at 18D4
0006: 00 00 ; Padding before fixed ISR address
ScanLine96:
;Interrupt brings us here when the beam is *near* the middle of the screen. The real middle
;would be 224/2 = 112. The code pretends this interrupt happens at line 128.
0008: F5 PUSH AF ; Save ...
0009: C5 PUSH BC ; ...
000A: D5 PUSH DE ; ...
000B: E5 PUSH HL ; ... everything
000C: C3 8C 00 JP $008C ; Continue ISR at 8C
000F: 00 ; Padding before fixed ISR address
ScanLine224:
; Interrupt brings us here when the beam is at the end of the screen (line 224) when the VBLANK begins.
0010: F5 PUSH AF ; Save ...
0011: C5 PUSH BC ; ...
0012: D5 PUSH DE ; ...
0013: E5 PUSH HL ; ... everything
0014: 3E 80 LD A,$80 ; Flag that tells objects ...
0016: 32 72 20 LD (vblankStatus),A ; ... on the lower half of the screen to draw/move
0019: 21 C0 20 LD HL,$20C0 ; Decrement ...
001C: 35 DEC (HL) ; ... the general countdown (used for pauses)
001D: CD CD 17 CALL CheckHandleTilt ; Check and handle TILT
0020: DB 01 IN A,($01) ; {-2_INP1} Read coin switch
0022: 0F RRCA ; Has a coin been deposited (bit 0)?
0023: DA 67 00 JP C,$0067 ; Yes ... note that switch is closed and continue at 3F with A=1
0026: 3A EA 20 LD A,(coinSwitch) ; Switch is now open. Was it ...
0029: A7 AND A ; ... closed last time?
002A: CA 42 00 JP Z,$0042 ; No ... skip registering the credit
;
; Handle bumping credit count
002D: 3A EB 20 LD A,(numCoins) ; Number of credits in BCD
0030: FE 99 CP $99 ; 99 credits already?
0032: CA 3E 00 JP Z,$003E ; Yes ... ignore this (better than rolling over to 00)
0035: C6 01 ADD A,$01 ; Bump number of credits
0037: 27 DAA ; Make it binary coded decimal
0038: 32 EB 20 LD (numCoins),A ; New number of credits
003B: CD 47 19 CALL DrawNumCredits ; Draw credits on screen
003E: AF XOR A ; Credit switch ...
003F: 32 EA 20 LD (coinSwitch),A ; ... has opened
;
0042: 3A E9 20 LD A,(suspendPlay) ; Are we moving ...
0045: A7 AND A ; ... game objects?
0046: CA 82 00 JP Z,$0082 ; No ... restore registers and out
0049: 3A EF 20 LD A,(gameMode) ; Are we in ...
004C: A7 AND A ; ... game mode?
004D: C2 6F 00 JP NZ,$006F ; Yes ... go process game-play things and out
0050: 3A EB 20 LD A,(numCoins) ; Number of credits
0053: A7 AND A ; Are there any credits (player standing there)?
0054: C2 5D 00 JP NZ,$005D ; Yes ... skip any ISR animations for the splash screens
0057: CD BF 0A CALL ISRSplTasks ; Process ISR tasks for splash screens
005A: C3 82 00 JP $0082 ; Restore registers and out
;
; At this point no game is going and there are credits
005D: 3A 93 20 LD A,(waitStartLoop) ; Are we in the ...
0060: A7 AND A ; ... "press start" loop?
0061: C2 82 00 JP NZ,$0082 ; Yes ... restore registers and out
0064: C3 65 07 JP WaitForStart ; Start the "press start" loop
;
; Mark credit as needing registering
0067: 3E 01 LD A,$01 ; Remember switch ...
0069: 32 EA 20 LD (coinSwitch),A ; ... state for debounce
006C: C3 3F 00 JP $003F ; Continue
;
; Main game-play timing loop
006F: CD 40 17 CALL TimeFleetSound ; Time down fleet sound and sets flag if needs new delay value
0072: 3A 32 20 LD A,(obj2TimerExtra) ; Use rolling shot's timer to sync ...
0075: 32 80 20 LD (shotSync),A ; ... other two shots
0078: CD 00 01 CALL DrawAlien ; Draw the current alien (or exploding alien)
007B: CD 48 02 CALL RunGameObjs ; Process game objects (including player object)
007E: CD 13 09 CALL TimeToSaucer ; Count down time to saucer
0081: 00 NOP ; ** Why are we waiting?
;
0082: E1 POP HL ; Restore ...
0083: D1 POP DE ; ...
0084: C1 POP BC ; ...
0085: F1 POP AF ; ... everything
0086: FB EI ; Enable interrupts
0087: C9 RET ; Return from interrupt
0088: 00 00 00 00 ; ** Why waste the space?
; Continues here at scanline 96
;
008C: AF XOR A ; Flag that tells ...
008D: 32 72 20 LD (vblankStatus),A ; ... objects on the upper half of screen to draw/move
0090: 3A E9 20 LD A,(suspendPlay) ; Are we moving ...
0093: A7 AND A ; ... game objects?
0094: CA 82 00 JP Z,$0082 ; No ... restore and return
0097: 3A EF 20 LD A,(gameMode) ; Are we in ...
009A: A7 AND A ; ... game mode?
009B: C2 A5 00 JP NZ,$00A5 ; Yes .... process game objects and out
009E: 3A C1 20 LD A,(isrSplashTask) ; Splash-animation tasks
00A1: 0F RRCA ; If we are in demo-mode then we'll process the tasks anyway
00A2: D2 82 00 JP NC,$0082 ; Not in demo mode ... done
;
00A5: 21 20 20 LD HL,$2020 ; Game object table (skip player-object at 2010)
00A8: CD 4B 02 CALL $024B ; Process all game objects (except player object)
00AB: CD 41 01 CALL CursorNextAlien ; Advance cursor to next alien (move the alien if it is last one)
00AE: C3 82 00 JP $0082 ; Restore and return
InitRack:
; Initialize the player's rack of aliens. Copy the reference-location and deltas from the
; player's data bank.
;
00B1: CD 86 08 CALL GetAlRefPtr ; 2xFC Get current player's ref-alien position pointer
00B4: E5 PUSH HL ; Hold pointer
00B5: 7E LD A,(HL) ; Get player's ...
00B6: 23 INC HL ; ... ref-alien ...
00B7: 66 LD H,(HL) ; ...
00B8: 6F LD L,A ; ... coordinates
00B9: 22 09 20 LD (refAlienYr),HL ; Set game's reference alien's X,Y
00BC: 22 0B 20 LD (alienPosLSB),HL ; Set game's alien cursor bit position
00BF: E1 POP HL ; Restore pointer
00C0: 2B DEC HL ; 21FB or 22FB ref alien's delta (left or right)
00C1: 7E LD A,(HL) ; Get ref alien's delta X
00C2: FE 03 CP $03 ; If there is one alien it will move right at 3
00C4: C2 C8 00 JP NZ,$00C8 ; Not 3 ... keep it
00C7: 3D DEC A ; If it is 3, back it down to 2 until it switches again
00C8: 32 08 20 LD (refAlienDXr),A ; Store alien deltaY
00CB: FE FE CP $FE ; Moving left?
00CD: 3E 00 LD A,$00 ; Value of 0 for rack-moving-right (not XOR so flags are unaffected)
00CF: C2 D3 00 JP NZ,$00D3 ; Not FE ... keep the value 0 for right
00D2: 3C INC A ; It IS FE ... use 1 for left
00D3: 32 0D 20 LD (rackDirection),A ; Store rack direction
00D6: C9 RET ; Done
00D7: 3E 02 LD A,$02 ; Set ...
00D9: 32 FB 21 LD (p1RefAlienDX),A ; ... player 1 and 2 ...
00DC: 32 FB 22 LD (p2RefAlienDX),A ; ... alien delta to 2 (right 2 pixels)
00DF: C3 E4 08 JP $08E4 ;
00E2: 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;
; This is heavily patched from a previous version of the code. There was a test here to jump to a
; self-test routine on startup (based on a dip switch). Even the original code padded with zeros
; to make the next function begin at 0100. Room for expansion?
DrawAlien:
; 2006 holds the index into the alien flag data grid. 2067 holds the MSB of the pointer (21xx or 22xx).
; If there is an alien exploding time it down. Otherwise draw the alien if it alive (or skip if
; it isn't). If an alien is drawn (or blank) then the 2000 alien-drawing flag is cleared.
;
0100: 21 02 20 LD HL,$2002 ; Is there an ...
0103: 7E LD A,(HL) ; ... alien ...
0104: A7 AND A ; ... exploding?
0105: C2 38 15 JP NZ,AExplodeTime ; Yes ... go time it down and out
;
0108: E5 PUSH HL ; 2002 on the stack
0109: 3A 06 20 LD A,(alienCurIndex) ; Get alien index ...
010C: 6F LD L,A ; ... for the 21xx or 22xx pointer
010D: 3A 67 20 LD A,(playerDataMSB) ; Get MSB ...
0110: 67 LD H,A ; ... of data area (21xx or 22xx)
0111: 7E LD A,(HL) ; Get alien status flag
0112: A7 AND A ; Is the alien alive?
0113: E1 POP HL ; HL=2002
0114: CA 36 01 JP Z,$0136 ; No alien ... skip drawing alien sprite (but flag done)
0117: 23 INC HL ; HL=2003 Bump descriptor
0118: 23 INC HL ; HL=2004 Point to alien's row
0119: 7E LD A,(HL) ; Get alien type
011A: 23 INC HL ; HL=2005 Bump descriptor
011B: 46 LD B,(HL) ; Get animation number
011C: E6 FE AND $FE ; Translate row to type offset as follows: ...
011E: 07 RLCA ; ... 0,1 -> 32 (type 1) ...
011F: 07 RLCA ; ... 2,3 -> 16 (type 2) ...
0120: 07 RLCA ; ... 4 -> 32 (type 3) on top row
0121: 5F LD E,A ; Sprite offset LSB
0122: 16 00 LD D,$00 ; MSB is 0
0124: 21 00 1C LD HL,$1C00 ; Position 0 alien sprites
0127: 19 ADD HL,DE ; Offset to sprite type
0128: EB EX DE,HL ; Sprite offset to DE
0129: 78 LD A,B ; Animation frame number
012A: A7 AND A ; Is it position 0?
012B: C4 3B 01 CALL NZ,$013B ; No ... add 30 and use position 1 alien sprites
012E: 2A 0B 20 LD HL,(alienPosLSB) ; Pixel position
0131: 06 10 LD B,$10 ; 16 rows in alien sprites
0133: CD D3 15 CALL DrawSprite ; Draw shifted sprite
;
0136: AF XOR A ; Let the ISR routine ...
0137: 32 00 20 LD (waitOnDraw),A ; ... advance the cursor to the next alien
013A: C9 RET ; Out
;
013B: 21 30 00 LD HL,$0030 ; Offset sprite pointer ...
013E: 19 ADD HL,DE ; ... to animation frame 1 sprites
013F: EB EX DE,HL ; Back to DE
0140: C9 RET ; Out
CursorNextAlien:
; This is called from the mid-screen ISR to set the cursor for the next alien to draw.
; When the cursor moves over all aliens then it is reset to the beginning and the reference
; alien is moved to its next position.
;
; The flag at 2000 keeps this in sync with the alien-draw routine called from the end-screen ISR.
; When the cursor is moved here then the flag at 2000 is set to 1. This routine will not change
; the cursor until the alien-draw routine at 100 clears the flag. Thus no alien is skipped.
;
0141: 3A 68 20 LD A,(playerOK) ; Is the player ...
0144: A7 AND A ; ... blowing up?
0145: C8 RET Z ; Yes ... ignore the aliens
0146: 3A 00 20 LD A,(waitOnDraw) ; Still waiting on ...
0149: A7 AND A ; ... this alien to be drawn?
014A: C0 RET NZ ; Yes ... leave cursor in place
014B: 3A 67 20 LD A,(playerDataMSB) ; Load alien-data ...
014E: 67 LD H,A ; ... MSB (either 21xx or 22xx)
014F: 3A 06 20 LD A,(alienCurIndex) ; Load the xx part of the alien flag pointer
0152: 16 02 LD D,$02 ; When all are gone this triggers 1A1 to return from this stack frame
0154: 3C INC A ; Have we drawn all aliens ...
0155: FE 37 CP $37 ; ... at last position?
0157: CC A1 01 CALL Z,MoveRefAlien ; Yes ... move the bottom/right alien and reset index to 0
015A: 6F LD L,A ; HL now points to alien flag
015B: 46 LD B,(HL) ; Is alien ...
015C: 05 DEC B ; ... alive?
015D: C2 54 01 JP NZ,$0154 ; No ... skip to next alien
0160: 32 06 20 LD (alienCurIndex),A ; New alien index
0163: CD 7A 01 CALL GetAlienCoords ; Calculate bit position and type for index
0166: 61 LD H,C ; The calculation returns the MSB in C
0167: 22 0B 20 LD (alienPosLSB),HL ; Store new bit position
016A: 7D LD A,L ; Has this alien ...
016B: FE 28 CP $28 ; ... reached the end of screen?
016D: DA 71 19 JP C,$1971 ; Yes ... kill the player
0170: 7A LD A,D ; This alien's ...
0171: 32 04 20 LD (alienRow),A ; ... row index
0174: 3E 01 LD A,$01 ; Set the wait-flag for the ...
0176: 32 00 20 LD (waitOnDraw),A ; ... draw-alien routine to clear
0179: C9 RET ; Done
GetAlienCoords:
; Convert alien index in L to screen bit position in C,L.
; Return alien row index (converts to type) in D.
;
017A: 16 00 LD D,$00 ; Row 0
017C: 7D LD A,L ; Hold onto alien index
017D: 21 09 20 LD HL,$2009 ; Get alien X ...
0180: 46 LD B,(HL) ; ... to B
0181: 23 INC HL ; Get alien y ...
0182: 4E LD C,(HL) ; ... to C
0183: FE 0B CP $0B ; Can we take a full row off of index?
0185: FA 94 01 JP M,$0194 ; No ... we have the row
0188: DE 0B SBC A,$0B ; Subtract off 11 (one whole row)
018A: 5F LD E,A ; Hold the new index
018B: 78 LD A,B ; Add ...
018C: C6 10 ADD A,$10 ; ... 16 to bit ...
018E: 47 LD B,A ; ... position Y (1 row in rack)
018F: 7B LD A,E ; Restore tallied index
0190: 14 INC D ; Next row
0191: C3 83 01 JP $0183 ; Keep skipping whole rows
;
0194: 68 LD L,B ; We have the LSB (the row)
0195: A7 AND A ; Are we in the right column?
0196: C8 RET Z ; Yes ... X and Y are right
0197: 5F LD E,A ; Hold index
0198: 79 LD A,C ; Add ...
0199: C6 10 ADD A,$10 ; ... 16 to bit ...
019B: 4F LD C,A ; ... position X (1 column in rack)
019C: 7B LD A,E ; Restore index
019D: 3D DEC A ; We adjusted for 1 column
019E: C3 95 01 JP $0195 ; Keep moving over column
MoveRefAlien:
; The "reference alien" is the bottom left. All other aliens are drawn relative to this
; reference. This routine moves the reference alien (the delta is set elsewhere) and toggles
; the animation frame number between 0 and 1.
;
01A1: 15 DEC D ; This decrements with each call to move
01A2: CA CD 01 JP Z,ReturnTwo ; Return out of TWO call frames (only used if no aliens left)
01A5: 21 06 20 LD HL,$2006 ; Set current alien ...
01A8: 36 00 LD (HL),$00 ; ... index to 0
01AA: 23 INC HL ; Point to DeltaX
01AB: 4E LD C,(HL) ; Load DX into C
01AC: 36 00 LD (HL),$00 ; Set DX to 0
01AE: CD D9 01 CALL AddDelta ; Move alien
01B1: 21 05 20 LD HL,$2005 ; Alien animation frame number
01B4: 7E LD A,(HL) ; Toggle ...
01B5: 3C INC A ; ... animation ...
01B6: E6 01 AND $01 ; ... number between ...
01B8: 77 LD (HL),A ; ... 0 and 1
01B9: AF XOR A ; Alien index in A is now 0
01BA: 21 67 20 LD HL,$2067 ; Restore H ...
01BD: 66 LD H,(HL) ; ... to player data MSB (21 or 22)
01BE: C9 RET ; Done
01BF: 00 ; ** Why?
InitAliens:
; Initialize the 55 aliens from last to 1st. 1 means alive.
;
01C0: 21 00 21 LD HL,$2100 ; Start of alien structures (this is the last alien)
01C3: 06 37 LD B,$37 ; Count to 55 (that's five rows of 11 aliens)
01C5: 36 01 LD (HL),$01 ; Bring alien to live
01C7: 23 INC HL ; Next alien
01C8: 05 DEC B ; All done?
01C9: C2 C5 01 JP NZ,$01C5 ; No ... keep looping
01CC: C9 RET ; Done
ReturnTwo:
; If there are no aliens left on the screen then MoveDrawAlien comes here which returns from the
; caller's stack frame.
;
01CD: E1 POP HL ; Drop return to caller
01CE: C9 RET ; Return to caller's caller
DrawBottomLine:
; Draw a 1px line across the player's stash at the bottom of the screen.
;
01CF: 3E 01 LD A,$01 ; Bit 1 set ... going to draw a 1-pixel stripe down left side
01D1: 06 E0 LD B,$E0 ; All the way down the screen
01D3: 21 02 24 LD HL,$2402 ; Screen coordinates (3rd byte from upper left)
01D6: C3 CC 14 JP $14CC ; Draw line down left side
AddDelta:
; HL points to descriptor: DX DY XX YY except DX is already loaded in C
; ** Why the "already loaded" part? Why not just load it here?
;
01D9: 23 INC HL ; We loaded delta-x already ... skip over it
01DA: 46 LD B,(HL) ; Get delta-y
01DB: 23 INC HL ; Skip over it
01DC: 79 LD A,C ; Add delta-x ...
01DD: 86 ADD A,(HL) ; ... to x
01DE: 77 LD (HL),A ; Store new x
01DF: 23 INC HL ; Skip to y
01E0: 78 LD A,B ; Add delta-y ...
01E1: 86 ADD A,(HL) ; ... to y
01E2: 77 LD (HL),A ; Store new y
01E3: C9 RET ; Done
CopyRAMMirror:
; Block copy ROM mirror 1B00-1BBF to initialize RAM at 2000-20BF.
;
01E4: 06 C0 LD B,$C0 ; Number of bytes
01E6: 11 00 1B LD DE,$1B00 ; RAM mirror in ROM
01E9: 21 00 20 LD HL,$2000 ; Start of RAM
01EC: C3 32 1A JP BlockCopy ; Copy [DE]->[HL] and return
DrawShieldPl1:
; Draw the shields for player 1 (draws it in the buffer in the player's data area).
;
01EF: 21 42 21 LD HL,$2142 ; Player 1 shield buffer (remember between games in multi-player)
01F2: C3 F8 01 JP $01F8 ; Common draw point
;
DrawShieldPl2:
; Draw the shields for player 1 (draws it in the buffer in the player's data area).
;
01F5: 21 42 22 LD HL,$2242 ; Player 2 shield buffer (remember between games in multi-player)
;
01F8: 0E 04 LD C,$04 ; Going to draw 4 shields
01FA: 11 20 1D LD DE,$1D20 ; Shield pixel pattern
01FD: D5 PUSH DE ; Hold the start for the next shield
01FE: 06 2C LD B,$2C ; 44 bytes to copy
0200: CD 32 1A CALL BlockCopy ; Block copy DE to HL (B bytes)
0203: D1 POP DE ; Restore start of shield pattern
0204: 0D DEC C ; Drawn all shields?
0205: C2 FD 01 JP NZ,$01FD ; No ... go draw them all
0208: C9 RET ; Done
RememberShields1:
; Copy shields on the screen to player 1's data area.
;
0209: 3E 01 LD A,$01 ; Not zero means remember
020B: C3 1B 02 JP $021B ; Shuffle-shields player 1
RememberShields2:
; Copy shields on the screen to player 2's data area.
;
020E: 3E 01 LD A,$01 ; Not zero means remember
0210: C3 14 02 JP $0214 ; Shuffle-shields player 2
RestoreShields2:
; Copy shields from player 2's data area to screen.
;
0213: AF XOR A ; Zero means restore
0214: 11 42 22 LD DE,$2242 ; Player 2 shield buffer (remember between games in multi-player)
0217: C3 1E 02 JP CopyShields ; Shuffle-shields player 2
RestoreShields1:
; Copy shields from player 1's data area to screen.
;
021A: AF XOR A ; Zero means restore
021B: 11 42 21 LD DE,$2142 ; Player 1 shield buffer (remember between games in multi-player)
CopyShields:
; A is 1 for screen-to-buffer, 0 for to buffer-to-screen
; HL is screen coordinates of first shield. There are 23 rows between shields.
; DE is sprite buffer in memory.
;
021E: 32 81 20 LD (tmp2081),A ; Remember copy/restore flag
0221: 01 02 16 LD BC,$1602 ; 22 rows, 2 bytes/row (for 1 shield pattern)
0224: 21 06 28 LD HL,$2806 ; Screen coordinates
0227: 3E 04 LD A,$04 ; Four shields to move
0229: F5 PUSH AF ; Hold shield count
022A: C5 PUSH BC ; Hold sprite-size
022B: 3A 81 20 LD A,(tmp2081) ; Get back copy/restore flag
022E: A7 AND A ; Not zero ...
022F: C2 42 02 JP NZ,$0242 ; ... means remember shidles
0232: CD 69 1A CALL RestoreShields ; Restore player's shields
0235: C1 POP BC ; Get back sprite-size
0236: F1 POP AF ; Get back shield count
0237: 3D DEC A ; Have we moved all shields?
0238: C8 RET Z ; Yes ... out
0239: D5 PUSH DE ; Hold sprite buffer
023A: 11 E0 02 LD DE,$02E0 ; Add 2E0 (23 rows) to get to ...
023D: 19 ADD HL,DE ; ... next shield on screen
023E: D1 POP DE ; restore sprite buffer
023F: C3 29 02 JP $0229 ; Go back and do all
;
0242: CD 7C 14 CALL RememberShields ; Remember player's shields
0245: C3 35 02 JP $0235 ; Continue with next shield
RunGameObjs:
; Process game objects. Each game object has a 16 byte structure. The handler routine for the object
; is at xx03 and xx04 of the structure. The pointer to xx04 is pushed onto the stack before calling
; the handler.
;
; All game objects (except task 0 ... the player) are called at the mid-screen and end-screen renderings.
; Each object decides when to run based on its Y (not rotated) coordinate. If an object is on the lower
; half of the screen then it does its work when the beam is at the top of the screen. If an object is
; on the top of the screen then it does its work when the beam is at the bottom. This keeps the
; object from updating while it is being drawn which would result in an ugly flicker.
;
;
; The player is only processed at the mid-screen interrupt. I am not sure why.
;
; The first three bytes of the structure are used for status and timers.
;
; If the first byte is FF then the end of the game-task list has been reached.
; If the first byte is FE then the object is skipped.
;
; If the first-two bytes are non-zero then they are treated like a two-byte counter
; and decremented as such. The 2nd byte is the LSB (moves the fastest).
;
; If the first-two bytes are zero then the third byte is treated as an additional counter. It
; is decremented as such.
;
; When all three bytes reach zero the task is executed.
;
; The third-byte-counter was used as a speed-governor for the player's object, but evidently even the slowest
; setting was too slow. It got changed to 0 (fastest possible).
;
0248: 21 10 20 LD HL,$2010 ; First game object (active player)
024B: 7E LD A,(HL) ; Have we reached the ...
024C: FE FF CP $FF ; ... end of the object list?
024E: C8 RET Z ; Yes ... done
024F: FE FE CP $FE ; Is object active?
0251: CA 81 02 JP Z,$0281 ; No ... skip it
0254: 23 INC HL ; xx01
0255: 46 LD B,(HL) ; First byte to B
0256: 4F LD C,A ; Hold 1st byte
0257: B0 OR B ; OR 1st and 2nd byte
0258: 79 LD A,C ; Restore 1st byte
0259: C2 77 02 JP NZ,$0277 ; If word at xx00,xx02 is non zero then decrement it
;
025C: 23 INC HL ; xx02
025D: 7E LD A,(HL) ; Get byte counter
025E: A7 AND A ; Is it 0?
025F: C2 88 02 JP NZ,$0288 ; No ... decrement byte counter at xx02
0262: 23 INC HL ; xx03
0263: 5E LD E,(HL) ; Get handler address LSB
0264: 23 INC HL ; xx04
0265: 56 LD D,(HL) ; Get handler address MSB
0266: E5 PUSH HL ; Remember pointer to MSB
0267: EB EX DE,HL ; Handler address to HL
0268: E5 PUSH HL ; Now to stack (making room for indirect call)
0269: 21 6F 02 LD HL,$026F ; Return address to 026F
026C: E3 EX (SP),HL ; Return address (026F) now on stack. Handler in HL.
026D: D5 PUSH DE ; Push pointer to data struct (xx04) for handler to use
026E: E9 JP (HL) ; Run object's code (will return to next line)
026F: E1 POP HL ; Restore pointer to xx04
0270: 11 0C 00 LD DE,$000C ; Offset to next ...
0273: 19 ADD HL,DE ; ... game task (C+4=10)
0274: C3 4B 02 JP $024B ; Do next game task
;
; Word at xx00 and xx01 is non-zero. Decrement it and move to next task.
0277: 05 DEC B ; Decrement ...
0278: 04 INC B ; ... two ...
0279: C2 7D 02 JP NZ,$027D ; ... byte ...
027C: 3D DEC A ; ... value ...
027D: 05 DEC B ; ... at ...
027E: 70 LD (HL),B ; ... xx00 ...
027F: 2B DEC HL ; ... and ...
0280: 77 LD (HL),A ; ... xx01
;
0281: 11 10 00 LD DE,$0010 ; Next ...
0284: 19 ADD HL,DE ; ... object descriptor
0285: C3 4B 02 JP $024B ; Keep processing game objects
;
; Word at xx00 and xx01 is zero and byte at xx02 is non-zero. Decrement xx02 and
; move to next task.
0288: 35 DEC (HL) ; Decrement the xx02 counter
0289: 2B DEC HL ; Back up to ...
028A: 2B DEC HL ; ... start of game task
028B: C3 81 02 JP $0281 ; Next game task
GameObj0:
; Game object 0: Move/draw the player
;
; This task is only called at the mid-screen ISR. It ALWAYS does its work here, even though
; the player can be on the top or bottom of the screen (not rotated).
;
028E: E1 POP HL ; Get player object structure 2014
028F: 23 INC HL ; Point to blow-up status
0290: 7E LD A,(HL) ; Get player blow-up status
0291: FE FF CP $FF ; Player is blowing up?
0293: CA 3B 03 JP Z,$033B ; No ... go do normal movement
;
; Handle blowing up player
0296: 23 INC HL ; Point to blow-up delay count
0297: 35 DEC (HL) ; Decrement the blow-up delay
0298: C0 RET NZ ; Not time for a new blow-up sprite ... out
0299: 47 LD B,A ; Hold sprite image number
029A: AF XOR A ; 0
029B: 32 68 20 LD (playerOK),A ; Player is NOT OK ... player is blowing up
029E: 32 69 20 LD (enableAlienFire),A ; Alien fire is disabled
02A1: 3E 30 LD A,$30 ; Reset count ...
02A3: 32 6A 20 LD (alienFireDelay),A ; ... till alien shots are enabled
02A6: 78 LD A,B ; Restore sprite image number (used if we go to 39B)
02A7: 36 05 LD (HL),$05 ; Reload time between blow-up changes
02A9: 23 INC HL ; Point to number of blow-up changes
02AA: 35 DEC (HL) ; Count down blow-up changes
02AB: C2 9B 03 JP NZ,DrawPlayerDie ; Still blowing up ... go draw next sprite
;
; Blow up finished
02AE: 2A 1A 20 LD HL,(playerYr) ; Player's coordinates
02B1: 06 10 LD B,$10 ; 16 Bytes
02B3: CD 24 14 CALL EraseSimpleSprite ; Erase simple sprite (the player)
02B6: 21 10 20 LD HL,$2010 ; Restore player ...
02B9: 11 10 1B LD DE,$1B10 ; ... structure ...
02BC: 06 10 LD B,$10 ; ... from ...
02BE: CD 32 1A CALL BlockCopy ; ... ROM mirror
02C1: 06 00 LD B,$00 ; Turn off ...
02C3: CD DC 19 CALL SoundBits3Off ; ... all sounds
02C6: 3A 6D 20 LD A,(invaded) ; Has rack reached ...
02C9: A7 AND A ; ... the bottom of the screen?
02CA: C0 RET NZ ; Yes ... done here
02CB: 3A EF 20 LD A,(gameMode) ; Are we in ...
02CE: A7 AND A ; ... game mode?
02CF: C8 RET Z ; No ... return to splash screens
02D0: 31 00 24 LD SP,$2400 ; We aren't going to return
02D3: FB EI ; Enable interrupts (we just dropped the ISR context)
02D4: CD D7 19 CALL DsableGameTasks ; Disable game tasks
02D7: CD 2E 09 CALL $092E ; Get number of ships for active player
02DA: A7 AND A ; Any left?
02DB: CA 6D 16 JP Z,$166D ; No ... handle game over for player
02DE: CD E7 18 CALL $18E7 ; Get player-alive status pointer
02E1: 7E LD A,(HL) ; Is player ...
02E2: A7 AND A ; ... alive?
02E3: CA 2C 03 JP Z,$032C ; Yes ... remove a ship from player's stash and reenter game loop
02E6: 3A CE 20 LD A,(twoPlayers) ; Multi-player game
02E9: A7 AND A ; Only one player?
02EA: CA 2C 03 JP Z,$032C ; Yes ... remove a ship from player's stash and reenter game loop
02ED: 3A 67 20 LD A,(playerDataMSB) ; Player data MSB
02F0: F5 PUSH AF ; Hold the MSB
02F1: 0F RRCA ; Player 1 is active player?
02F2: DA 32 03 JP C,$0332 ; Yes ... go store player 1 shields and come back to 02F8
02F5: CD 0E 02 CALL RememberShields2 ; No ... go store player 2 shields
02F8: CD 78 08 CALL $0878 ; Get ref-alien info and pointer to storage
02FB: 73 LD (HL),E ; Hold the ...
02FC: 23 INC HL ; ... ref-alien ...
02FD: 72 LD (HL),D ; ... screen coordinates
02FE: 2B DEC HL ; Back up ...
02FF: 2B DEC HL ; .. to delta storage
0300: 70 LD (HL),B ; Store ref-alien's delta (direction)
0301: 00 NOP ; ** Why?
0302: CD E4 01 CALL CopyRAMMirror ; Copy RAM mirror (getting ready to switch players)
0305: F1 POP AF ; Restore active player MSB
0306: 0F RRCA ; Player 1?
0307: 3E 21 LD A,$21 ; Player 1 data pointer
0309: 06 00 LD B,$00 ; Cocktail bit=0 (player 1)
030B: D2 12 03 JP NC,$0312 ; It was player one ... keep data for player 2
030E: 06 20 LD B,$20 ; Cocktail bit=1 (player 2)
0310: 3E 22 LD A,$22 ; Player 2 data pointer
0312: 32 67 20 LD (playerDataMSB),A ; Change players
0315: CD B6 0A CALL TwoSecDelay ; Two second delay
0318: AF XOR A ; Clear the player-object ...
0319: 32 11 20 LD (obj0TimerLSB),A ; ... timer (player can move instantly after switching players)
031C: 78 LD A,B ; Cocktail bit to A
031D: D3 05 OUT ($05),A ; {-2_SOUND2} Set the cocktail mode
031F: 3C INC A ; Fleet sound 1 (first tone)
0320: 32 98 20 LD (soundPort5),A ; Set the port 5 hold
0323: CD D6 09 CALL ClearPlayField ; Clear center window
0326: CD 7F 1A CALL RemoveShip ; Remove a ship and update indicators
0329: C3 F9 07 JP $07F9 ; Tell the players that the switch has been made
;
032C: CD 7F 1A CALL RemoveShip ; Remove a ship and update indicators
032F: C3 17 08 JP $0817 ; Continue into game loop
;
0332: CD 09 02 CALL RememberShields1 ; Remember the shields for player 1
0335: C3 F8 02 JP $02F8 ; Back to switching-players above
0338: 00 00 00 ; ** Why
; Player not blowing up ... handle inputs
033B: 21 68 20 LD HL,$2068 ; Player OK flag
033E: 36 01 LD (HL),$01 ; Flag 1 ... player is OK
0340: 23 INC HL ; 2069
0341: 7E LD A,(HL) ; Alien shots enabled?
0342: A7 AND A ; Set flags
0343: C3 B0 03 JP $03B0 ; Continue
0346: 00 NOP ; ** Why?
0347: 2B DEC HL ; 2069
0348: 36 01 LD (HL),$01 ; Enable alien fire
034A: 3A 1B 20 LD A,(playerXr) ; Current player coordinates
034D: 47 LD B,A ; Hold it
034E: 3A EF 20 LD A,(gameMode) ; Are we in ...
0351: A7 AND A ; ... game mode?
0352: C2 63 03 JP NZ,$0363 ; Yes ... use switches as player controls
;
0355: 3A 1D 20 LD A,(nextDemoCmd) ; Get demo command
0358: 0F RRCA ; Is it right?
0359: DA 81 03 JP C,MovePlayerRight ; Yes ... do right
035C: 0F RRCA ; Is it left?
035D: DA 8E 03 JP C,MovePlayerLeft ; Yes ... do left
0360: C3 6F 03 JP $036F ; Skip over movement (draw player and out)
; Player is in control
0363: CD C0 17 CALL ReadInputs ; Read active player controls
0366: 07 RLCA ; Test for ...
0367: 07 RLCA ; ... right button
0368: DA 81 03 JP C,MovePlayerRight ; Yes ... handle move right
036B: 07 RLCA ; Test for left button
036C: DA 8E 03 JP C,MovePlayerLeft ; Yes ... handle move left
; Draw player sprite
036F: 21 18 20 LD HL,$2018 ; Active player descriptor
0372: CD 3B 1A CALL ReadDesc ; Load 5 byte sprite descriptor in order: EDLHB
0375: CD 47 1A CALL ConvToScr ; Convert HL to screen coordinates
0378: CD 39 14 CALL DrawSimpSprite ; Draw player
037B: 3E 00 LD A,$00 ; Clear the task timer. Nobody changes this but it could have ...
037D: 32 12 20 LD (obj0TimerExtra),A ; ... been speed set for the player with a value other than 0 (not XORA)
0380: C9 RET ; Out
MovePlayerRight:
; Handle player moving right
0381: 78 LD A,B ; Player coordinate
0382: FE D9 CP $D9 ; At right edge?
0384: CA 6F 03 JP Z,$036F ; Yes ... ignore this
0387: 3C INC A ; Bump X coordinate
0388: 32 1B 20 LD (playerXr),A ; New X coordinate
038B: C3 6F 03 JP $036F ; Draw player and out
MovePlayerLeft:
; Handle player moving left
038E: 78 LD A,B ; Player coordinate
038F: FE 30 CP $30 ; At left edge
0391: CA 6F 03 JP Z,$036F ; Yes ... ignore this
0394: 3D DEC A ; Bump X coordinate
0395: 32 1B 20 LD (playerXr),A ; New X coordinate
0398: C3 6F 03 JP $036F ; Draw player and out
DrawPlayerDie:
; Toggle the player's blowing-up sprite between two pictures and draw it
039B: 3C INC A ; Toggle blowing-up ...
039C: E6 01 AND $01 ; ... player sprite (0,1,0,1)
039E: 32 15 20 LD (playerAlive),A ; Hold current state
03A1: 07 RLCA ; *2
03A2: 07 RLCA ; *4
03A3: 07 RLCA ; *8
03A4: 07 RLCA ; *16
03A5: 21 70 1C LD HL,$1C70 ; Base blow-up sprite location
03A8: 85 ADD A,L ; Offset sprite ...
03A9: 6F LD L,A ; ... pointer
03AA: 22 18 20 LD (plyrSprPicL),HL ; New blow-up sprite picture
03AD: C3 6F 03 JP $036F ; Draw new blow-up sprite and out
03B0: C2 4A 03 JP NZ,$034A ; Alien shots enabled ... move player's ship, draw it, and out
03B3: 23 INC HL ; To 206A
03B4: 35 DEC (HL) ; Time until aliens can fire
03B5: C2 4A 03 JP NZ,$034A ; Not time to enable ... move player's ship, draw it, and out
03B8: C3 46 03 JP $0346 ; Enable alien fire ... move player's ship, draw it, and out
GameObj1:
; Game object 1: Move/draw the player shot
;
; This task executes at either mid-screen ISR (if it is on the top half of the non-rotated screen) or
; at the end-screen ISR (if it is on the bottom half of the screen).
;
03BB: 11 2A 20 LD DE,$202A ; Object's Yn coordiante
03BE: CD 06 1A CALL CompYToBeam ; Compare to screen-update location
03C1: E1 POP HL ; Pointer to task data
03C2: D0 RET NC ; Make sure we are in the right ISR
03C3: 23 INC HL ; Point to 2025 ... the shot status
03C4: 7E LD A,(HL) ; Get shot status
03C5: A7 AND A ; Return if ...
03C6: C8 RET Z ; ... no shot is active
;
03C7: FE 01 CP $01 ; Shot just starting (requested elsewhere)?
03C9: CA FA 03 JP Z,InitPlyShot ; Yes ... go initiate shot
;
03CC: FE 02 CP $02 ; Progressing normally?
03CE: CA 0A 04 JP Z,MovePlyShot ; Yes ... go move it
;
03D1: 23 INC HL ; 2026
03D2: FE 03 CP $03 ; Shot blowing up (not because of alien)?
03D4: C2 2A 04 JP NZ,$042A ; No ... try other options
;
; Shot blowing up because it left the playfield, hit a shield, or hit another bullet
03D7: 35 DEC (HL) ; Decrement the timer
03D8: CA 36 04 JP Z,EndOfBlowup ; If done then
03DB: 7E LD A,(HL) ; Get timer value
03DC: FE 0F CP $0F ; Starts at 10 ... first decrement brings us here
03DE: C0 RET NZ ; Not the first time ... explosion has been drawn
; Draw explosion first pass through timer loop
03DF: E5 PUSH HL ; Hold pointer to data
03E0: CD 30 04 CALL ReadPlyShot ; Read shot descriptor
03E3: CD 52 14 CALL EraseShifted ; Erase the sprite
03E6: E1 POP HL ; 2026 (timer flag)
03E7: 23 INC HL ; 2027 point to sprite LSB
03E8: 34 INC (HL) ; Change 1C90 to 1C91
03E9: 23 INC HL ; 2028
03EA: 23 INC HL ; 2029
03EB: 35 DEC (HL) ; Drop X coordinate ...
03EC: 35 DEC (HL) ; ... by 2
03ED: 23 INC HL ; 202A
03EE: 35 DEC (HL) ; Drop Y ...
03EF: 35 DEC (HL) ; ... coordinate ...
03F0: 35 DEC (HL) ; ... by ...
03F1: 23 INC HL ; ... 3
03F2: 36 08 LD (HL),$08 ; 202B 8 bytes in size of sprite
03F4: CD 30 04 CALL ReadPlyShot ; Read player shot structure
03F7: C3 00 14 JP DrawShiftedSprite ; Draw sprite and out
;
InitPlyShot:
03FA: 3C INC A ; Type is now ...
03FB: 77 LD (HL),A ; ... 2 (in progress)
03FC: 3A 1B 20 LD A,(playerXr) ; Players Y coordinate
03FF: C6 08 ADD A,$08 ; To center of player
0401: 32 2A 20 LD (obj1CoorXr),A ; Shot's Y coordinate
0404: CD 30 04 CALL ReadPlyShot ; Read 5 byte structure
0407: C3 00 14 JP DrawShiftedSprite ; Draw sprite and out
;
MovePlyShot:
040A: CD 30 04 CALL ReadPlyShot ; Read the shot structure
040D: D5 PUSH DE ; Hold pointer to sprite image
040E: E5 PUSH HL ; Hold sprite coordinates
040F: C5 PUSH BC ; Hold sprite size (in B)
0410: CD 52 14 CALL EraseShifted ; Erase the sprite from the screen
0413: C1 POP BC ; Restore size
0414: E1 POP HL ; Restore coords
0415: D1 POP DE ; Restore pointer to sprite image
0416: 3A 2C 20 LD A,(shotDeltaX) ; DeltaX for shot
0419: 85 ADD A,L ; Move the shot ...
041A: 6F LD L,A ; ... up the screen
041B: 32 29 20 LD (obj1CoorYr),A ; Store shot's new X coordinate
041E: CD 91 14 CALL DrawSprCollision ; Draw sprite with collision detection
0421: 3A 61 20 LD A,(collision) ; Test for ...
0424: A7 AND A ; ... collision
0425: C8 RET Z ; No collision ... out
;
; Collision with alien detected
0426: 32 02 20 LD (alienIsExploding),A; Set to not-0 indicating ...
0429: C9 RET ; ... an alien is blowing up
;
; Other shot-status options
042A: FE 05 CP $05 ; Alien explosion in progress?
042C: C8 RET Z ; Yes ... nothing to do
042D: C3 36 04 JP EndOfBlowup ; Anything else erases the shot and removes it from duty
ReadPlyShot:
0430: 21 27 20 LD HL,$2027 ; Read 5 byte sprite structure for ...
0433: C3 3B 1A JP ReadDesc ; ... player shot
EndOfBlowup:
0436: CD 30 04 CALL ReadPlyShot ; Read the shot structure
0439: CD 52 14 CALL EraseShifted ; Erase the player's shot
043C: 21 25 20 LD HL,$2025 ; Reinit ...
043F: 11 25 1B LD DE,$1B25 ; ... shot structure ...
0442: 06 07 LD B,$07 ; ... from ...
0444: CD 32 1A CALL BlockCopy ; ... ROM mirror
0447: 2A 8D 20 LD HL,(sauScoreLSB) ; Get pointer to saucer-score table
044A: 2C INC L ; Every shot explosion advances it one
044B: 7D LD A,L ; Have we passed ...
044C: FE 63 CP $63 ; ... the end at 1D63 (bug! this should be $64 to cover all 16 values)
044E: DA 53 04 JP C,$0453 ; No .... keep it
0451: 2E 54 LD L,$54 ; Wrap back around to 1D54
0453: 22 8D 20 LD (sauScoreLSB),HL ; New score pointer
0456: 2A 8F 20 LD HL,(shotCountLSB) ; Increments with every shot ...
0459: 2C INC L ; ... but only LSB ** ...
045A: 22 8F 20 LD (shotCountLSB),HL ; ... used for saucer direction
;
045D: 3A 84 20 LD A,(saucerActive) ; Is saucer ...
0460: A7 AND A ; ... on screen?
0461: C0 RET NZ ; Yes ... don't reset it
;
; Setup saucer direction for next trip
0462: 7E LD A,(HL) ; Shot counter
0463: E6 01 AND $01 ; Lowest bit set?
0465: 01 29 02 LD BC,$0229 ; Xr delta of 2 starting at Xr=29
0468: C2 6E 04 JP NZ,$046E ; Yes ... use 2/29
046B: 01 E0 FE LD BC,$FEE0 ; No ... Xr delta of -2 starting at Xr=E0
046E: 21 8A 20 LD HL,$208A ; Saucer descriptor
0471: 71 LD (HL),C ; Store Xr coordinate
0472: 23 INC HL ; Point to ...
0473: 23 INC HL ; ... delta Xr
0474: 70 LD (HL),B ; Store delta Xr
0475: C9 RET ; Done
GameObj2:
; Game object 2: Alien rolling-shot (targets player specifically)
;
; The 2-byte value at 2038 is where the firing-column-table-pointer would be (see other
; shots ... next game objects). This shot doesn't use that table. It targets the player
; specifically. Instead the value is used as a flag to have the shot skip its first
; attempt at firing every time it is reinitialized (when it blows up).
;
; The task-timer at 2032 is copied to 2080 in the game loop. The flag is used as a
; synchronization flag to keep all the shots processed on separate interrupt ticks. This
; has the main effect of slowing the shots down.
;
; When the timer is 2 the squiggly-shot/saucer (object 4 ) runs.
; When the timer is 1 the plunger-shot (object 3) runs.
; When the timer is 0 this object, the rolling-shot, runs.
;
0476: E1 POP HL ; Game object data
0477: 3A 32 1B LD A,($1B32) ; Restore delay from ...
047A: 32 32 20 LD (obj2TimerExtra),A ; ... ROM mirror (value 2)
047D: 2A 38 20 LD HL,(rolShotCFirLSB) ; Get pointer to ...
0480: 7D LD A,L ; ... column-firing table.
0481: B4 OR H ; All zeros?
0482: C2 8A 04 JP NZ,$048A ; No ... must be a valid column. Go fire.
0485: 2B DEC HL ; Decrement the counter
0486: 22 38 20 LD (rolShotCFirLSB),HL ; Store new counter value (run the shot next time)
0489: C9 RET ; And out
048A: 11 35 20 LD DE,$2035 ; Rolling-shot data structure
048D: 3E F9 LD A,$F9 ; Last picture of "rolling" alien shot
048F: CD 50 05 CALL ToShotStruct ; Set code to handle rolling-shot
0492: 3A 46 20 LD A,(pluShotStepCnt) ; Get the plunger-shot step count
0495: 32 70 20 LD (otherShot1),A ; Hold it
0498: 3A 56 20 LD A,(squShotStepCnt) ; Get the squiggly-shot step count
049B: 32 71 20 LD (otherShot2),A ; Hold it
049E: CD 63 05 CALL HandleAlienShot ; Handle active shot structure
04A1: 3A 78 20 LD A,(aShotBlowCnt) ; Blow up counter
04A4: A7 AND A ; Test if shot has cycled through blowing up
04A5: 21 35 20 LD HL,$2035 ; Rolling-shot data structure
04A8: C2 5B 05 JP NZ,FromShotStruct ; If shot is still running, copy the updated data and out
ResetShot:
; The rolling-shot has blown up. Reset the data structure.
04AB: 11 30 1B LD DE,$1B30 ; Reload ...
04AE: 21 30 20 LD HL,$2030 ; ... object ...
04B1: 06 10 LD B,$10 ; ... structure ...
04B3: C3 32 1A JP BlockCopy ; ... from ROM mirror and out
GameObj3:
; Game object 3: Alien plunger-shot
; This is skipped if there is only one alien left on the screen.
;
04B6: E1 POP HL ; Game object data
04B7: 3A 6E 20 LD A,(skipPlunger) ; One alien left? Skip plunger shot?
04BA: A7 AND A ; Check
04BB: C0 RET NZ ; Yes. Only one alien. Skip this shot.
04BC: 3A 80 20 LD A,(shotSync) ; Sync flag (copied from GO-2's timer value)
04BF: FE 01 CP $01 ; GO-2 and GO-4 are idle?
04C1: C0 RET NZ ; No ... only one shot at a time
04C2: 11 45 20 LD DE,$2045 ; Plunger alien shot data structure
04C5: 3E ED LD A,$ED ; Last picture of "plunger" alien shot
04C7: CD 50 05 CALL ToShotStruct ; Copy the plunger alien to the active structure
04CA: 3A 36 20 LD A,(rolShotStepCnt) ; Step count from rolling-shot
04CD: 32 70 20 LD (otherShot1),A ; Hold it
04D0: 3A 56 20 LD A,(squShotStepCnt) ; Step count from squiggly shot
04D3: 32 71 20 LD (otherShot2),A ; Hold it
04D6: CD 63 05 CALL HandleAlienShot ; Handle active shot structure
04D9: 3A 76 20 LD A,(aShotCFirLSB) ; LSB of column-firing table
04DC: FE 10 CP $10 ; Been through all entries in the table?
04DE: DA E7 04 JP C,$04E7 ; Not yet ... table is OK
04E1: 3A 48 1B LD A,($1B48) ; Been through all ..
04E4: 32 76 20 LD (aShotCFirLSB),A ; ... so reset pointer into firing-column table
04E7: 3A 78 20 LD A,(aShotBlowCnt) ; Get the blow up timer
04EA: A7 AND A ; Zero means shot is done
04EB: 21 45 20 LD HL,$2045 ; Plunger shot data
04EE: C2 5B 05 JP NZ,FromShotStruct ; If shot is still running, go copy the updated data and out
;
04F1: 11 40 1B LD DE,$1B40 ; Reload ...
04F4: 21 40 20 LD HL,$2040 ; ... object ...
04F7: 06 10 LD B,$10 ; ... structure ...
04F9: CD 32 1A CALL BlockCopy ; ... from mirror
;
04FC: 3A 82 20 LD A,(numAliens) ; Number of aliens on screen
04FF: 3D DEC A ; Is there only one left?
0500: C2 08 05 JP NZ,$0508 ; No ... move on
0503: 3E 01 LD A,$01 ; Disable plunger shot ...
0505: 32 6E 20 LD (skipPlunger),A ; ... when only one alien remains
0508: 2A 76 20 LD HL,(aShotCFirLSB) ; Set the plunger shot's ...
050B: C3 7E 06 JP $067E ; ... column-firing pointer data
; Game task 4 when splash screen alien is shooting extra "C" with a squiggly shot
050E: E1 POP HL ; Ignore the task data pointer passed on stack
;
; GameObject 4 comes here if processing a squiggly shot
050F: 11 55 20 LD DE,$2055 ; Squiggly shot data structure
0512: 3E DB LD A,$DB ; LSB of last byte of picture
0514: CD 50 05 CALL ToShotStruct ; Copy squiggly shot to
0517: 3A 46 20 LD A,(pluShotStepCnt) ; Get plunger ...
051A: 32 70 20 LD (otherShot1),A ; ... step count
051D: 3A 36 20 LD A,(rolShotStepCnt) ; Get rolling ...
0520: 32 71 20 LD (otherShot2),A ; ... step count
0523: CD 63 05 CALL HandleAlienShot ; Handle active shot structure
0526: 3A 76 20 LD A,(aShotCFirLSB) ; LSB of column-firing table pointer
0529: FE 15 CP $15 ; Have we processed all entries?
052B: DA 34 05 JP C,$0534 ; No ... don't reset it
052E: 3A 58 1B LD A,($1B58) ; Reset the pointer ...
0531: 32 76 20 LD (aShotCFirLSB),A ; ... back to the start of the table
0534: 3A 78 20 LD A,(aShotBlowCnt) ; Check to see if squiggly shot is done
0537: A7 AND A ; 0 means blow-up timer expired
0538: 21 55 20 LD HL,$2055 ; Squiggly shot data structure
053B: C2 5B 05 JP NZ,FromShotStruct ; If shot is still running, go copy the updated data and out
; Shot explosion is over. Remove the shot.
053E: 11 50 1B LD DE,$1B50 ; Reload
0541: 21 50 20 LD HL,$2050 ; ... object ...
0544: 06 10 LD B,$10 ; ... structure ...
0546: CD 32 1A CALL BlockCopy ; ... from mirror
0549: 2A 76 20 LD HL,(aShotCFirLSB) ; Copy pointer to column-firing table ...
054C: 22 58 20 LD (squShotCFirLSB),HL ; ... back to data structure (for next shot)
054F: C9 RET ; Done
ToShotStruct:
0550: 32 7F 20 LD (shotPicEnd),A ; LSB of last byte of last picture in sprite
0553: 21 73 20 LD HL,$2073 ; Destination is the shot-structure
0556: 06 0B LD B,$0B ; 11 bytes
0558: C3 32 1A JP BlockCopy ; Block copy and out
FromShotStruct:
055B: 11 73 20 LD DE,$2073 ; Source is the shot-structure
055E: 06 0B LD B,$0B ; 11 bytes
0560: C3 32 1A JP BlockCopy ; Block copy and out
HandleAlienShot:
; Each of the 3 shots copy their data to the 2073 structure (0B bytes) and call this.
; Then they copy back if the shot is still active. Otherwise they copy from the mirror.
;
; The alien "fire rate" is based on the number of steps the other two shots on the screen
; have made. The smallest number-of-steps is compared to the reload-rate. If it is too
; soon then no shot is made. The reload-rate is based on the player's score. The MSB
; is looked up in a table to get the reload-rate. The smaller the rate the faster the
; aliens fire. Setting rate this way keeps shots from walking on each other.
;
0563: 21 73 20 LD HL,$2073 ; Start of active shot structure
0566: 7E LD A,(HL) ; Get the shot status
0567: E6 80 AND $80 ; Is the shot active?
0569: C2 C1 05 JP NZ,$05C1 ; Yes ... go move it
056C: 3A C1 20 LD A,(isrSplashTask) ; ISR splash task
056F: FE 04 CP $04 ; Shooting the "C" ?
0571: 3A 69 20 LD A,(enableAlienFire) ; Alien fire enabled flag
0574: CA B7 05 JP Z,$05B7 ; We are shooting the extra "C" ... just flag it active and out
0577: A7 AND A ; Is alien fire enabled?
0578: C8 RET Z ; No ... don't start a new shot
0579: 23 INC HL ; 2074 step count of current shot
057A: 36 00 LD (HL),$00 ; clear the step count
; Make sure it isn't too soon to fire another shot
057C: 3A 70 20 LD A,(otherShot1) ; Get the step count of the 1st "other shot"
057F: A7 AND A ; Any steps made?
0580: CA 89 05 JP Z,$0589 ; No ... ignore this count
0583: 47 LD B,A ; Shuffle off step count
0584: 3A CF 20 LD A,(aShotReloadRate) ; Get the reload rate (based on MSB of score)
0587: B8 CP B ; Too soon to fire again?
0588: D0 RET NC ; Yes ... don't fire
0589: 3A 71 20 LD A,(otherShot2) ; Get the step count of the 2nd "other shot"
058C: A7 AND A ; Any steps made?
058D: CA 96 05 JP Z,$0596 ; No steps on any shot ... we are clear to fire
0590: 47 LD B,A ; Shuffle off step count
0591: 3A CF 20 LD A,(aShotReloadRate) ; Get the reload rate (based on MSB of score)
0594: B8 CP B ; Too soon to fire again?
0595: D0 RET NC ; Yes ... don't fire
0596: 23 INC HL ; 2075
0597: 7E LD A,(HL) ; Get tracking flag
0598: A7 AND A ; Does this shot track the player?
0599: CA 1B 06 JP Z,$061B ; Yes ... go make a tracking shot;
059C: 2A 76 20 LD HL,(aShotCFirLSB) ; Column-firing table
059F: 4E LD C,(HL) ; Get next column to fire from
05A0: 23 INC HL ; Bump the ...
05A1: 00 NOP ; % WHY?
05A2: 22 76 20 LD (aShotCFirLSB),HL ; ... pointer into column table
05A5: CD 2F 06 CALL FindInColumn ; Find alien in target column
05A8: D0 RET NC ; No alien is alive in target column ... out
;
05A9: CD 7A 01 CALL GetAlienCoords ; Get coordinates of alien (lowest alien in firing column)
05AC: 79 LD A,C ; Offset ...
05AD: C6 07 ADD A,$07 ; ... Y by 7
05AF: 67 LD H,A ; To H
05B0: 7D LD A,L ; Offset ...
05B1: D6 0A SUB $0A ; ... X down 10
05B3: 6F LD L,A ; To L
05B4: 22 7B 20 LD (alienShotYr),HL ; Set shot coordinates below alien
;