• Contact
  • Journal
  • Home
  • Arcade
  • Space Invaders
  • Code
  • Site
  • Page
  • Amiga
    • Rainbow Islands
      • 1loader-dec
      • 1loader
      • boot
      • orig-boot
      • Journal
  • Arcade
    • Asteroids 80%
      • Hardware
      • RAMUse
      • Code

      • DVG
      • VectorROM

      • Journal
    • Crazy Climber 1%
      • BigSpriteGraphics.pdf
      • Buildings.pdf
      • cclimber.asm
      • CharEnc.inc
      • CrazyClimberMemoryMapInfo.pdf
      • GraphicsAndCharacterAssetInfo.pdf
      • MemoryMap.inc
    • Defender 75%
      • RAMUse
      • Hardware
      • Bank1
      • Bank2
      • Bank3
      • Bank7
      • BankFixed
      • Mapping.txt
      • SoundHardware
      • SoundRAMUse
      • SoundCode
      • Defender-Theory-Early.pdf
      • Defender-Theory-Later.pdf
      • Defender.CPU.jpg
      • Defender.ROM.B&W.jpg
      • Defender.Vid.B&W.jpg
      • SoundROM.txt
    • Frogger (Sound)
      • SoundHardware
      • SoundRAMUse
      • SoundCode

      • Hardware
      • RAMUse
      • Code

      • GFX

      • Journal
    • Galaga 5%
      • CPU1 (Main)
      • CPU2 (Secondary)
      • CPU3 (Sound)
      • GFX1 (Characters)
      • GFX2 (Sprites)
      • PROMcolors
      • PROMpaletteChar
      • PROMpaletteSprite

      • CPU1Fix

      • Journal
    • Moon Patrol 75%
      • Hardware
      • RAMUse
      • Code

      • GFX1 (Text)
      • GFX2 (Sprites)
      • GFX3 (Mountains)
      • GFX4 (Hills)
      • GFX5 (City)
      • ImageBackgroundColors
      • SpriteColors
      • SpriteColorSets
      • TextColors

      • MoonPatrolSound
      • SoundHardware
      • SoundRAMUse
      • SoundCode

      • Journal
    • Omega Race 10%
      • Hardware
      • RAMUse
      • MainBoard

      • SoundHardware
      • SoundRAMUse
      • SoundBoard

      • DVGPROM
      • VectorROM

      • Journal
    • Phoenix 35%
      • Hardware
      • RAMUse
      • Code

      • Background
      • Foreground

      • Journal

      • Scramble HHi
        • phoenixj-func-main2.pdf
        • phoenixj-func-main2.scap
        • phoenixj.asm-may2025.txt
        • phoenixj.asm-may2025.txt.pdf
    • Space Invaders
      • Hardware
      • RAMUse
      • Code

      • Journal
    • Time Pilot (Sound)
      • SoundHardware
      • SoundRAMUse
      • SoundCode

      • Hardware
      • RAMUse
      • Code

      • Journal
    • Sea Wolf 1%
      • Hardware
      • RAMUse
      • Code

      • Journal
    • Scramble 1%
      • SoundHardware
      • SoundRAMUse
      • SoundCode

      • Journal
  • Atari2600
    • Stella (Hardware Info)
    • Asteroids 5%
      • RAMUse
      • Code

      • Journal
    • Battle Zone 1%
      • RAMUse
      • Code

      • Journal
    • Chess 1%
      • RAMUse
      • Code

      • Journal
    • Combat 10%
      • RAMUse
      • Code
      • CodePAL

      • Journal
    • Double Gap
      • Code
      • DoubleGap.asm

      • Journal
    • Entombed 1%
      • RAMUse
      • Code

      • Journal
    • ET 1%
      • RAMUse
      • Code

      • Journal
    • Burger Time 1%
      • RAMUse
      • CodeBank0
      • CodeBank1
      • CodeBank2
      • CodeBank3
      • CodeBank4
      • CodeBank5
      • CodeBank6
      • CodeBank7

      • Journal
    • Missile Command 1%
      • RAMUse
      • Code

      • Journal
    • Space Invaders 1%
      • RAMUse
      • Code

      • Journal
  • CoCo
    • Hardware
    • Early Work
    • Pyramid
      • RAMUse
      • Code

      • Journal
    • Raaka Tu
      • RAMUse
      • Code

      • Journal
    • Bedlam
      • RAMUse
      • Code

      • Journal
    • Madness & Minotaur
      • Walk Through
        • after_start.txt
        • after_start.cas
        • after_1.txt
        • after_1.cas
        • after_2.txt
        • after_2.cas
        • after_3.txt
        • after_3.cas
        • after_4.txt
        • after_4.cas
        • after_5.txt
        • after_5.cas
        • after_6.txt
        • after_6.cas
        • after_7.txt
        • after_7.cas
        • after_8.txt
        • after_8.cas
        • after_9.txt
        • after_9.cas
        • after_10.txt
        • after_10.cas
        • after_11.txt
        • after_11.cas
        • after_12.txt
        • after_12.cas
        • after_13.txt
        • after_13.cas
        • after_14.txt
        • after_14.cas
        • after_15.txt
        • after_15.cas
        • after_16.txt
        • after_16.cas
        • after_17.txt
        • after_17.cas
        • after_18.txt
        • after_18.cas
        • after_19.txt
        • after_19.cas
        • after_20.txt
        • after_20.cas
        • after_21.txt
        • after_21.cas
        • after_22.txt
        • after_22.cas
        • after_23.txt
        • after_23.cas
        • after_24.txt
        • after_24.cas
        • after_25.txt
        • after_25.cas
      • RAMUse
      • Code

      • SaveGameViewer

      • Journal
    • Mega-Bug
      • RAMUse
      • Code

      • Journal
    • Daggorath
      • RAMUse
      • Code

      • Level Maps

      • Journal
    • Downland 5%
      • RAMUse
      • Code

      • Journal
    • Audio Analyzer 5%
      • RAMUse
      • Code

      • Journal
    • Doubleback
      • RAMUse
      • Code

      • Journal
  • NES
    • Zelda 5%
      • Hardware
      • RAMUse
      • Bank0
      • Bank1
      • Bank2
      • Bank3
      • Bank4
      • Bank5
      • Bank6
      • Bank7

      • Journal
    • Kid Icarus 1%
      • Hardware
      • RAMUse
      • Bank0
      • Bank1
      • Bank2
      • Bank3
      • Bank4
      • Bank5
      • Bank6
      • Bank7

      • Journal
  • Gameboy
    • Hardware
    • Link's Awakening 1%
      • RAMUse
      • Bank00
      • Bank01
      • Bank02
      • Bank03
      • Bank04
      • Bank05
      • Bank06
      • Bank07
      • Bank08
      • Bank09
      • Bank0A
      • Bank0B
      • Bank0C
      • Bank0D
      • Bank0E
      • Bank0F
      • Bank10
      • Bank11
      • Bank12
      • Bank13
      • Bank14
      • Bank15
      • Bank16
      • Bank17
      • Bank18
      • Bank19
      • Bank1A
      • Bank1B
      • Bank1C
      • Bank1D
      • Bank1E
      • Bank1F

      • Journal
    • Tetris 1%
      • RAMUse
      • Code

      • Journal
  • TRS80
    • Hardware
    • HauntedHouse
      • RAMUse1
      • Code1
      • RAMUse2
      • Code2

      • Journal
    • Pyramid
      • RAMUse
      • Code

      • RAMUse1
      • Code1

      • Journal
    • RaakaTu
      • RAMUse
      • Code

      • Journal
    • Bedlam
      • RAMUse
      • Code

      • Journal
  • Virus
    • Morris Worm 1%
      • Journal
    • Stoned
      • Journal

  • Tools
    • Blend
      • blend.zip

      • Journal
  • Space Invaders
  • Startup and Interrupts
  • The Aliens
  • Misc
  • Copy/Restore Shields
  • Game Objects
  • Start New Game
  • Diagnostics Routine
  • Data From Here Down
    • Alien Pulling Upside Down 'Y'
    • Alien Images
    • Player Sprite
    • Player Shot Sprite
    • Player Shot Exploding
    • Alien Exploding Sprite
    • Squigly Shot Sprite
    • Alien Shot Exploding
    • Plunger Shot Sprite
    • Rolling Shot Sprite
    • Shield Image
    • Flying Saucer Sprite
    • Text Character Sprites
    • Alien Sprite Carrying 'Y'

Space Invaders

Hardware Info

RAM Usage

It is never completely finished:

  • TODO Look at the various versions of the ROMs and see what's different
  • TODO Check all X/Y references and make !Xr/Yr or !Xn/Yn

A word on coordinates. Sometimes the code is easier to understand in the context of the screen in actual (not rotated) position. The comments will refer to Xn (X not-rotated) and Yn. Sometimes the code is easier to understand in the context of the rotated screen. The comments will refer to Xr (X rotated) and Yr.

Startup and Interrupts

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      init                ; 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,isrDelay         ; 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,(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

The Aliens

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

Misc

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

Copy/Restore Shields

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

Game Objects

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     (SOUND2),A          ; 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
;
05B7: 21 73 20        LD      HL,$2073            ; Alien shot status
05BA: 7E              LD      A,(HL)              ; Get the status
05BB: F6 80           OR      $80                 ; Mark this shot ...
05BD: 77              LD      (HL),A              ; ... as actively running
05BE: 23              INC     HL                  ; 2074 step count
05BF: 34              INC     (HL)                ; Give this shot 1 step (it just started)
05C0: C9              RET                         ; Out
;
; Move the alien shot
05C1: 11 7C 20        LD      DE,$207C            ; Alien-shot Y coordinate
05C4: CD 06 1A        CALL    CompYToBeam         ; Compare to beam position
05C7: D0              RET     NC                  ; Not the right ISR for this shot
;
05C8: 23              INC     HL                  ; 2073 status
05C9: 7E              LD      A,(HL)              ; Get shot status
05CA: E6 01           AND     $01                 ; Bit 0 is 1 if blowing up
05CC: C2 44 06        JP      NZ,ShotBlowingUp    ; Go do shot-is-blowing-up sequence
05CF: 23              INC     HL                  ; 2074 step count
05D0: 34              INC     (HL)                ; Count the steps (used for fire rate)
05D1: CD 75 06        CALL    $0675               ; Erase shot
05D4: 3A 79 20        LD      A,(aShotImageLSB)   ; Get LSB of the image pointer
05D7: C6 03           ADD     A,$03               ; Next set of images
05D9: 21 7F 20        LD      HL,$207F            ; End of image
05DC: BE              CP      (HL)                ; Have we reached the end of the set?
05DD: DA E2 05        JP      C,$05E2             ; No ... keep it
05E0: D6 0C           SUB     $0C                 ; Back up to the 1st image in the set
05E2: 32 79 20        LD      (aShotImageLSB),A   ; New LSB image pointer
05E5: 3A 7B 20        LD      A,(alienShotYr)     ; Get shot's Y coordinate
05E8: 47              LD      B,A                 ; Hold it
05E9: 3A 7E 20        LD      A,(alienShotDelta)  ; Get alien shot delta
05EC: 80              ADD     A,B                 ; Add to shots coordinate
05ED: 32 7B 20        LD      (alienShotYr),A     ; New shot Y coordinate
05F0: CD 6C 06        CALL    $066C               ; Draw the alien shot
05F3: 3A 7B 20        LD      A,(alienShotYr)     ; Shot's Y coordinate
05F6: FE 15           CP      $15                 ; Still in the active playfield?
05F8: DA 12 06        JP      C,$0612             ; No ... end it
05FB: 3A 61 20        LD      A,(collision)       ; Did shot collide ...
05FE: A7              AND     A                   ; ... with something?
05FF: C8              RET     Z                   ; No ... we are done here
0600: 3A 7B 20        LD      A,(alienShotYr)     ; Shot's Y coordinate
0603: FE 1E           CP      $1E                 ; Is it below player's area?
0605: DA 12 06        JP      C,$0612             ; Yes ... end it
0608: FE 27           CP      $27                 ; Is it above player's area?
060A: 00              NOP                         ; ** WHY?
060B: D2 12 06        JP      NC,$0612            ; Yes ... end it
060E: 97              SUB     A                   ; Flag that player ...
060F: 32 15 20        LD      (playerAlive),A     ; ... has been struck
;
0612: 3A 73 20        LD      A,(aShotStatus)     ; Flag to ...
0615: F6 01           OR      $01                 ; ... start shot ...
0617: 32 73 20        LD      (aShotStatus),A     ; ... blowing up
061A: C9              RET                         ; Out
;
; Start a shot right over the player
061B: 3A 1B 20        LD      A,(playerXr)        ; Player's X coordinate
061E: C6 08           ADD     A,$08               ; Center of player
0620: 67              LD      H,A                 ; To H for routine
0621: CD 6F 15        CALL    FindColumn          ; Find the column
0624: 79              LD      A,C                 ; Get the column right over player
0625: FE 0C           CP      $0C                 ; Is it a valid column?
0627: DA A5 05        JP      C,$05A5             ; Yes ... use what we found
062A: 0E 0B           LD      C,$0B               ; Else use ...
062C: C3 A5 05        JP      $05A5               ; ... as far over as we can

FindInColumn:
; C contains the target column. Look for a live alien in the column starting with
; the lowest position. Return C=1 if found ... HL points to found slot.
062F: 0D              DEC     C                   ; Column that is firing
0630: 3A 67 20        LD      A,(playerDataMSB)   ; Player's MSB (21xx or 22xx)
0633: 67              LD      H,A                 ; To MSB of HL
0634: 69              LD      L,C                 ; Column to L
0635: 16 05           LD      D,$05               ; 5 rows of aliens
0637: 7E              LD      A,(HL)              ; Get alien's status
0638: A7              AND     A                   ; 0 means dead
0639: 37              SCF                         ; In case not 0
063A: C0              RET     NZ                  ; Alien is alive? Yes ... return
063B: 7D              LD      A,L                 ; Get the flag pointer LSB
063C: C6 0B           ADD     A,$0B               ; Jump to same column on next row of rack (+11 aliens per row)
063E: 6F              LD      L,A                 ; New alien index
063F: 15              DEC     D                   ; Tested all rows?
0640: C2 37 06        JP      NZ,$0637            ; No ... keep looking for a live alien up the rack
0643: C9              RET                         ; Didn't find a live alien. Return with C=0.

ShotBlowingUp:
; Alien shot is blowing up
0644: 21 78 20        LD      HL,$2078            ; Blow up timer
0647: 35              DEC     (HL)                ; Decrement the value
0648: 7E              LD      A,(HL)              ; Get the value
0649: FE 03           CP      $03                 ; First tick, 4, we draw the explosion
064B: C2 67 06        JP      NZ,$0667            ; After that just wait
064E: CD 75 06        CALL    $0675               ; Erase the shot
0651: 21 DC 1C        LD      HL,$1CDC            ; Alien shot ...
0654: 22 79 20        LD      (aShotImageLSB),HL  ; ... explosion sprite
0657: 21 7C 20        LD      HL,$207C            ; Alien shot Y
065A: 35              DEC     (HL)                ; Left two for ...
065B: 35              DEC     (HL)                ; ... explosion
065C: 2B              DEC     HL                  ; Point slien shot X
065D: 35              DEC     (HL)                ; Up two for ...
065E: 35              DEC     (HL)                ; ... explosion
065F: 3E 06           LD      A,$06               ; Alien shot descriptor ...
0661: 32 7D 20        LD      (alienShotSize),A   ; ... size 6
0664: C3 6C 06        JP      $066C               ; Draw alien shot explosion

0667: A7              AND     A                   ; Have we reached 0?
0668: C0              RET     NZ                  ; No ... keep waiting
0669: C3 75 06        JP      $0675               ; Erase the explosion and out
;
066C: 21 79 20        LD      HL,$2079            ; Alien shot descriptor
066F: CD 3B 1A        CALL    ReadDesc            ; Read 5 byte structure
0672: C3 91 14        JP      DrawSprCollision    ; Draw shot and out
;
0675: 21 79 20        LD      HL,$2079            ; Alien shot descriptor
0678: CD 3B 1A        CALL    ReadDesc            ; Read 5 byte structure
067B: C3 52 14        JP      EraseShifted        ; Erase the shot and out

067E: 22 48 20        LD      (pluShotCFirLSB),HL ; From 50B, update ...
0681: C9              RET                         ; ... column-firing table pointer and out

       

GameObj4:
; Game object 4: Flying Saucer OR squiggly shot
;
; This task is shared by the squiggly-shot and the flying saucer. The saucer waits until the
; squiggly-shot is over before it begins.
;
0682: E1              POP     HL                  ; Pull data pointer from the stack (not going to use it)
0683: 3A 80 20        LD      A,(shotSync)        ; Sync flag (copied from GO-2's timer value)
0686: FE 02           CP      $02                 ; Are GO-2 and GO-3 idle?
0688: C0              RET     NZ                  ; No ... only one at a time
0689: 21 83 20        LD      HL,$2083            ; Time-till-saucer flag
068C: 7E              LD      A,(HL)              ; Is it time ...
068D: A7              AND     A                   ; ... for a saucer?
068E: CA 0F 05        JP      Z,$050F             ; No ... go process squiggly shot
0691: 3A 56 20        LD      A,(squShotStepCnt)  ; Is there a ...
0694: A7              AND     A                   ; ... squiggly shot going?
0695: C2 0F 05        JP      NZ,$050F            ; Yes ... go handle squiggly shot

0698: 23              INC     HL                  ; Saucer on screen flag
0699: 7E              LD      A,(HL)              ; (2084) Is the saucer ...
069A: A7              AND     A                   ; ... already on the screen?
069B: C2 AB 06        JP      NZ,$06AB            ; Yes ... go handle it
069E: 3A 82 20        LD      A,(numAliens)       ; Number of aliens remaining
06A1: FE 08           CP      $08                 ; Less than ...
06A3: DA 0F 05        JP      C,$050F             ; ... 8 ... no saucer
06A6: 36 01           LD      (HL),$01            ; (2084) The saucer is on the screen
06A8: CD 3C 07        CALL    $073C               ; Draw the flying saucer

06AB: 11 8A 20        LD      DE,$208A            ; Saucer's Y coordinate
06AE: CD 06 1A        CALL    CompYToBeam         ; Compare to beam position
06B1: D0              RET     NC                  ; Not the right ISR for moving saucer

06B2: 21 85 20        LD      HL,$2085            ; Saucer hit flag
06B5: 7E              LD      A,(HL)              ; Has saucer ...
06B6: A7              AND     A                   ; ... been hit?
06B7: C2 D6 06        JP      NZ,$06D6            ; Yes ... don't move it

06BA: 21 8A 20        LD      HL,$208A            ; Saucer's structure
06BD: 7E              LD      A,(HL)              ; Get saucer's Y coordinate
06BE: 23              INC     HL                  ; Bump to ...
06BF: 23              INC     HL                  ; ... delta Y
06C0: 86              ADD     A,(HL)              ; Move saucer
06C1: 32 8A 20        LD      (saucerPriPicMSB),A ; New coordinate
06C4: CD 3C 07        CALL    $073C               ; Draw the flying saucer
06C7: 21 8A 20        LD      HL,$208A            ; Saucer's structure
06CA: 7E              LD      A,(HL)              ; Y coordinate
06CB: FE 28           CP      $28                 ; Too low? End of screen?
06CD: DA F9 06        JP      C,$06F9             ; Yes ... remove from play
06D0: FE E1           CP      $E1                 ; Too high? End of screen?
06D2: D2 F9 06        JP      NC,$06F9            ; Yes ... remove from play
06D5: C9              RET                         ; Done

06D6: 06 FE           LD      B,$FE               ; Turn off ...
06D8: CD DC 19        CALL    SoundBits3Off       ; ... flying saucer sound
06DB: 23              INC     HL                  ; (2086) show-hit timer
06DC: 35              DEC     (HL)                ; Count down show-hit timer
06DD: 7E              LD      A,(HL)              ; Get current value
06DE: FE 1F           CP      $1F                 ; Starts at 20 ... is this the first tick of show-hit timer?
06E0: CA 4B 07        JP      Z,$074B             ; Yes ... go show the explosion
06E3: FE 18           CP      $18                 ; A little later ...
06E5: CA 0C 07        JP      Z,$070C             ; ... show the score besides the saucer and add it
06E8: A7              AND     A                   ; Has timer expired?
06E9: C0              RET     NZ                  ; No ... let it run
06EA: 06 EF           LD      B,$EF               ; 1110_1111 (mask off saucer hit sound)
06EC: 21 98 20        LD      HL,$2098            ; Get current ...
06EF: 7E              LD      A,(HL)              ; ... value of port 5 sound
06F0: A0              AND     B                   ; Mask off the saucer-hit sound
06F1: 77              LD      (HL),A              ; Set the new value
06F2: E6 20           AND     $20                 ; All sound off but ...
06F4: D3 05           OUT     (SOUND2),A          ; ... cocktail cabinet bit
06F6: 00              NOP                         ; ** Why
06F7: 00              NOP                         ; **
06F8: 00              NOP                         ; **
;
06F9: CD 42 07        CALL    $0742               ; Covert pixel pos from descriptor to HL screen and shift
06FC: CD CB 14        CALL    ClearSmallSprite    ; Clear a one byte sprite at HL
06FF: 21 83 20        LD      HL,$2083            ; Saucer structure
0702: 06 0A           LD      B,$0A               ; 10 bytes in saucer structure
0704: CD 5F 07        CALL    $075F               ; Re-initialize saucer structure

0707: 06 FE           LD      B,$FE               ; Turn off UFO ...
0709: C3 DC 19        JP      SoundBits3Off       ; ... sound and out

070C: 3E 01           LD      A,$01               ; Flag the score ...
070E: 32 F1 20        LD      (adjustScore),A     ; ... needs updating
0711: 2A 8D 20        LD      HL,(sauScoreLSB)    ; Saucer score table
0714: 46              LD      B,(HL)              ; Get score for this saucer
0715: 0E 04           LD      C,$04               ; There are only 4 possibilities
0717: 21 50 1D        LD      HL,$1D50            ; Possible scores table
071A: 11 4C 1D        LD      DE,$1D4C            ; Print strings for each score
071D: 1A              LD      A,(DE)              ; Find ...
071E: B8              CP      B                   ; ... the ...
071F: CA 28 07        JP      Z,$0728             ; ... print ...
0722: 23              INC     HL                  ; ... string ...
0723: 13              INC     DE                  ; ... for ...
0724: 0D              DEC     C                   ; ... the ...
0725: C2 1D 07        JP      NZ,$071D            ; ... score
0728: 7E              LD      A,(HL)              ; Get LSB of message (MSB is 2088 which is 1D)
0729: 32 87 20        LD      (saucerPriLocLSB),A ; Message's LSB (_50=1D94 100=1D97 150=1D9A 300=1D9D)
072C: 26 00           LD      H,$00               ; MSB = 0 ...
072E: 68              LD      L,B                 ; HL = B
072F: 29              ADD     HL,HL               ; *2
0730: 29              ADD     HL,HL               ; *4
0731: 29              ADD     HL,HL               ; *8
0732: 29              ADD     HL,HL               ; *16
0733: 22 F2 20        LD      (scoreDeltaLSB),HL  ; Add score for hitting saucer (015 becomes 150 in BCD).
0736: CD 42 07        CALL    $0742               ; Get the flying saucer score descriptor
0739: C3 F1 08        JP      $08F1               ; Print the three-byte score and out

073C: CD 42 07        CALL    $0742               ; Draw the ...
073F: C3 39 14        JP      DrawSimpSprite      ; ... flying saucer

0742: 21 87 20        LD      HL,$2087            ; Read flying saucer ...
0745: CD 3B 1A        CALL    ReadDesc            ; ... structure
0748: C3 47 1A        JP      ConvToScr           ; Convert pixel number to screen and shift and out
;
074B: 06 10           LD      B,$10               ; Saucer hit sound bit
074D: 21 98 20        LD      HL,$2098            ; Current state of sounds
0750: 7E              LD      A,(HL)              ; OR ...
0751: B0              OR      B                   ; ... in ...
0752: 77              LD      (HL),A              ; ... saucer-hit sound
0753: CD 70 17        CALL    $1770               ; Turn off fleet sound and start saucer-hit
0756: 21 7C 1D        LD      HL,$1D7C            ; Sprite for saucer blowing up
0759: 22 87 20        LD      (saucerPriLocLSB),HL; Store it in structure
075C: C3 3C 07        JP      $073C               ; Draw the flying saucer
;
075F: 11 83 1B        LD      DE,$1B83            ; Data for saucer (702 sets count to 0A)
0762: C3 32 1A        JP      BlockCopy           ; Reset saucer object data


WaitForStart:
; Wait for player 1 start button press
0765: 3E 01           LD      A,$01               ; Tell ISR that we ...
0767: 32 93 20        LD      (waitStartLoop),A   ; ... have started to wait
076A: 31 00 24        LD      SP,$2400            ; Reset stack
076D: FB              EI                          ; Enable interrupts
076E: CD 79 19        CALL    $1979               ; Suspend game tasks
0771: CD D6 09        CALL    ClearPlayField      ; Clear center window
0774: 21 13 30        LD      HL,$3013            ; Screen coordinates
0777: 11 F3 1F        LD      DE,$1FF3            ; "PRESS"
077A: 0E 04           LD      C,$04               ; Message length
077C: CD F3 08        CALL    PrintMessage        ; Print it
077F: 3A EB 20        LD      A,(numCoins)        ; Number of credits
0782: 3D              DEC     A                   ; Set flags
0783: 21 10 28        LD      HL,$2810            ; Screen coordinates
0786: 0E 14           LD      C,$14               ; Message length
0788: C2 57 08        JP      NZ,$0857            ; Take 1 or 2 player start
078B: 11 CF 1A        LD      DE,$1ACF            ; "ONLY 1PLAYER BUTTON "
078E: CD F3 08        CALL    PrintMessage        ; Print message
0791: DB 01           IN      A,(INP1)            ; Read player controls
0793: E6 04           AND     $04                 ; 1Player start button?
0795: CA 7F 07        JP      Z,$077F             ; No ... wait for button or credit

Start New Game

NewGame:
; 1 Player start
0798: 06 99           LD      B,$99               ; Essentially a -1 for DAA
079A: AF              XOR     A                   ; Clear two player flag
;
; 2 player start sequence enters here with a=1 and B=98 (-2)
079B: 32 CE 20        LD      (twoPlayers),A      ; Set flag for 1 or 2 players
079E: 3A EB 20        LD      A,(numCoins)        ; Number of credits
07A1: 80              ADD     A,B                 ; Take away credits
07A2: 27              DAA                         ; Convert back to DAA
07A3: 32 EB 20        LD      (numCoins),A        ; New credit count
07A6: CD 47 19        CALL    DrawNumCredits      ; Display number of credits
07A9: 21 00 00        LD      HL,$0000            ; Score of 0000
07AC: 22 F8 20        LD      (P1ScorL),HL        ; Clear player-1 score
07AF: 22 FC 20        LD      (P2ScorL),HL        ; Clear player-2 score
07B2: CD 25 19        CALL    $1925               ; Print player-1 score
07B5: CD 2B 19        CALL    $192B               ; Print player-2 score
07B8: CD D7 19        CALL    DsableGameTasks     ; Disable game tasks
07BB: 21 01 01        LD      HL,$0101            ; Two bytes 1, 1
07BE: 7C              LD      A,H                 ; 1 to A
07BF: 32 EF 20        LD      (gameMode),A        ; 20EF=1 ... game mode
07C2: 22 E7 20        LD      (player1Alive),HL   ; 20E7 and 20E8 both one ... players 1 and 2 are alive
07C5: 22 E5 20        LD      (player1Ex),HL      ; Extra-ship is available for player-1 and player-2
07C8: CD 56 19        CALL    DrawStatus          ; Print scores and credits
07CB: CD EF 01        CALL    DrawShieldPl1       ; Draw shields for player-1
07CE: CD F5 01        CALL    DrawShieldPl2       ; Draw shields for player-2
07D1: CD D1 08        CALL    GetShipsPerCred     ; Get number of ships from DIP settings
07D4: 32 FF 21        LD      (p1ShipsRem),A      ; Player-1 ships
07D7: 32 FF 22        LD      (p2ShipsRem),A      ; Player-2 ships
07DA: CD D7 00        CALL    $00D7               ; Set player-1 and player-2 alien racks going right
07DD: AF              XOR     A                   ; Make a 0
07DE: 32 FE 21        LD      (p1RackCnt),A       ; Player 1 is on first rack of aliens
07E1: 32 FE 22        LD      (p2RackCnt),A       ; Player 2 is on first rack of aliens
07E4: CD C0 01        CALL    InitAliens          ; Initialize 55 aliens for player 1
07E7: CD 04 19        CALL    InitAliensP2        ; Initialize 55 aliens for player 2
07EA: 21 78 38        LD      HL,$3878            ; Screen coordinates for lower-left alien
07ED: 22 FC 21        LD      (p1RefAlienY),HL    ; Initialize reference alien for player 1
07F0: 22 FC 22        LD      (p2RefAlienYr),HL   ; Initialize reference alien for player 2
07F3: CD E4 01        CALL    CopyRAMMirror       ; Copy ROM mirror to RAM (2000 - 20C0)
07F6: CD 7F 1A        CALL    RemoveShip          ; Initialize ship hold indicator
;
07F9: CD 8D 08        CALL    PromptPlayer        ; Prompt with "PLAY PLAYER "
07FC: CD D6 09        CALL    ClearPlayField      ; Clear the playfield
07FF: 00              NOP                         ; % Why?
0800: AF              XOR     A                   ; Make a 0
0801: 32 C1 20        LD      (isrSplashTask),A   ; Disable isr splash-task animation
0804: CD CF 01        CALL    DrawBottomLine      ; Draw line across screen under player
0807: 3A 67 20        LD      A,(playerDataMSB)   ; Current player
080A: 0F              RRCA                        ; Right bit tells all
080B: DA 72 08        JP      C,$0872             ; Go do player 1
;
080E: CD 13 02        CALL    RestoreShields2     ; Restore shields for player 2
0811: CD CF 01        CALL    DrawBottomLine      ; Draw line across screen under player
0814: CD B1 00        CALL    InitRack            ; Initialize alien rack for current player
0817: CD D1 19        CALL    EnableGameTasks     ; Enable game tasks in ISR
081A: 06 20           LD      B,$20               ; Enable ...
081C: CD FA 18        CALL    SoundBits3On        ; ... sound amplifier
;
; GAME LOOP
;
081F: CD 18 16        CALL    PlrFireOrDemo       ; Initiate player shot if button pressed
0822: CD 0A 19        CALL    PlyrShotAndBump     ; Collision detect player's shot and rack-bump
0825: CD F3 15        CALL    CountAliens         ; Count aliens (count to 2082)
0828: CD 88 09        CALL    AdjustScore         ; Adjust score (and print) if there is an adjustment
082B: 3A 82 20        LD      A,(numAliens)       ; Number of live aliens
082E: A7              AND     A                   ; All aliens gone?
082F: CA EF 09        JP      Z,$09EF             ; Yes ... end of turn
0832: CD 0E 17        CALL    AShotReloadRate     ; Update alien-shot-rate based on player's score
0835: CD 35 09        CALL    $0935               ; Check (and handle) extra ship award
0838: CD D8 08        CALL    SpeedShots          ; Adjust alien shot speed
083B: CD 2C 17        CALL    ShotSound           ; Shot sound on or off with 2025
083E: CD 59 0A        CALL    $0A59               ; Check if player is hit
0841: CA 49 08        JP      Z,$0849             ; No hit ... jump handler
0844: 06 04           LD      B,$04               ; Player hit sound
0846: CD FA 18        CALL    SoundBits3On        ; Make explosion sound
0849: CD 75 17        CALL    FleetDelayExShip    ; Extra-ship sound timer, set fleet-delay, play fleet movement sound
084C: D3 06           OUT     (WATCHDOG),A        ; Feed the watchdog
084E: CD 04 18        CALL    CtrlSaucerSound     ; Control saucer sound
0851: C3 1F 08        JP      $081F               ; Continue game loop

0854: 00 00 00                                    ; ** Why?

; Test for 1 or 2 player start button press
0857: 11 BA 1A        LD      DE,$1ABA            ; "1 OR 2PLAYERS BUTTON"
085A: CD F3 08        CALL    PrintMessage        ; Print message
085D: 06 98           LD      B,$98               ; -2 (take away 2 credits)
085F: DB 01           IN      A,(INP1)            ; Read player controls
0861: 0F              RRCA                        ; Test ...
0862: 0F              RRCA                        ; ... bit 2
0863: DA 6D 08        JP      C,$086D             ; 2 player button pressed ... do it
0866: 0F              RRCA                        ; Test bit 3
0867: DA 98 07        JP      C,NewGame           ; One player start ... do it
086A: C3 7F 07        JP      $077F               ; Keep waiting on credit or button
; 2 PLAYER START
086D: 3E 01           LD      A,$01               ; Flag 2 player game
086F: C3 9B 07        JP      $079B               ; Continue normal startup

0872: CD 1A 02        CALL    RestoreShields1     ; Restore shields for player 1
0875: C3 14 08        JP      $0814               ; Continue in game loop

0878: 3A 08 20        LD      A,(refAlienDXr)     ; Alien deltaY
087B: 47              LD      B,A                 ; Hold it
087C: 2A 09 20        LD      HL,(refAlienYr)     ; Alien coordinates
087F: EB              EX      DE,HL               ; Coordinates to DE
0880: C3 86 08        JP      GetAlRefPtr         ; HL is 21FC or 22FC and out
            
0883: 00 00 00                                    ; ** Why?

GetAlRefPtr:
; Get pointer to player's alien ref coordiantes
0886: 3A 67 20        LD      A,(playerDataMSB)   ; Player data MSB (21 or 22)
0889: 67              LD      H,A                 ; To H
088A: 2E FC           LD      L,$FC               ; 21FC or 22FC ... alien coordinates
088C: C9              RET                         ; Done

PromptPlayer:
; Print "PLAY PLAYER <n>" and blink score for 2 seconds.
;
088D: 21 11 2B        LD      HL,$2B11            ; Screen coordinates
0890: 11 70 1B        LD      DE,$1B70            ; Message "PLAY PLAYER<1>"
0893: 0E 0E           LD      C,$0E               ; 14 bytes in message
0895: CD F3 08        CALL    PrintMessage        ; Print the message
0898: 3A 67 20        LD      A,(playerDataMSB)   ; Get the player number
089B: 0F              RRCA                        ; C will be set for player 1
089C: 3E 1C           LD      A,$1C               ; The "2" character
089E: 21 11 37        LD      HL,$3711            ; Replace the "<1>" with "<2">
08A1: D4 FF 08        CALL    NC,DrawChar         ; If player 2 ... change the message
08A4: 3E B0           LD      A,$B0               ; Delay of 176 (roughly 2 seconds)
08A6: 32 C0 20        LD      (isrDelay),A        ; Set the ISR delay value
;
08A9: 3A C0 20        LD      A,(isrDelay)        ; Get the ISR delay value
08AC: A7              AND     A                   ; Has the 2 second delay expired?
08AD: C8              RET     Z                   ; Yes ... done
08AE: E6 04           AND     $04                 ; Every 4 ISRs ...
08B0: C2 BC 08        JP      NZ,$08BC            ; ... flash the player's score
08B3: CD CA 09        CALL    $09CA               ; Get the score descriptor for the active player
08B6: CD 31 19        CALL    DrawScore           ; Draw the score
08B9: C3 A9 08        JP      $08A9               ; Back to the top of the wait loop
;
08BC: 06 20           LD      B,$20               ; 32 rows (4 characters * 8 bytes each)
08BE: 21 1C 27        LD      HL,$271C            ; Player-1 score on the screen
08C1: 3A 67 20        LD      A,(playerDataMSB)   ; Get the player number
08C4: 0F              RRCA                        ; C will be set for player 1
08C5: DA CB 08        JP      C,$08CB             ; We have the right score coordinates
08C8: 21 1C 39        LD      HL,$391C            ; Use coordinates for player-2's score
08CB: CD CB 14        CALL    ClearSmallSprite    ; Clear a one byte sprite at HL
08CE: C3 A9 08        JP      $08A9               ; Back to the top of the wait loop


GetShipsPerCred:
; Get number of ships from DIP settings
08D1: DB 02           IN      A,(INP2)            ; DIP settings
08D3: E6 03           AND     $03                 ; Get number of ships
08D5: C6 03           ADD     A,$03               ; From 3-6
08D7: C9              RET                         ; Out

SpeedShots:
; With less than 9 aliens on the screen the alien shots get a tad bit faster. Probably
; because the advancing rack can catch them.
;
08D8: 3A 82 20        LD      A,(numAliens)       ; Number of aliens on screen
08DB: FE 09           CP      $09                 ; More than 8?
08DD: D0              RET     NC                  ; Yes ... leave shot speed alone
08DE: 3E FB           LD      A,$FB               ; Normally FF (-4) ... now FB (-5)
08E0: 32 7E 20        LD      (alienShotDelta),A  ; Speed up alien shots
08E3: C9              RET                         ; Done

08E4: 3A CE 20        LD      A,(twoPlayers)      ; Number of players
08E7: A7              AND     A                   ; Skip if ...
08E8: C0              RET     NZ                  ; ... two player
08E9: 21 1C 39        LD      HL,$391C            ; Player 2's score
08EC: 06 20           LD      B,$20               ; 32 rows is 4 digits * 8 rows each
08EE: C3 CB 14        JP      ClearSmallSprite    ; Clear a one byte sprite (32 rows long) at HL

08F1: 0E 03           LD      C,$03               ; Length of saucer-score message ... fall into print

PrintMessage:
; Print a message on the screen
; HL = coordinates
; DE = message buffer
; C = length
08F3: 1A              LD      A,(DE)              ; Get character
08F4: D5              PUSH    DE                  ; Preserve
08F5: CD FF 08        CALL    DrawChar            ; Print character
08F8: D1              POP     DE                  ; Restore
08F9: 13              INC     DE                  ; Next character
08FA: 0D              DEC     C                   ; All done?
08FB: C2 F3 08        JP      NZ,PrintMessage     ; Print all of message
08FE: C9              RET                         ; Out

;=============================================================
DrawChar:
; Get pointer to 8 byte sprite number in A and
; draw sprite on screen at HL
08FF: 11 00 1E        LD      DE,$1E00            ; Character set
0902: E5              PUSH    HL                  ; Preserve
0903: 26 00           LD      H,$00               ; MSB=0
0905: 6F              LD      L,A                 ; Character number to L
0906: 29              ADD     HL,HL               ; HL = HL *2
0907: 29              ADD     HL,HL               ; *4
0908: 29              ADD     HL,HL               ; *8 (8 bytes each)
0909: 19              ADD     HL,DE               ; Get pointer to sprite
090A: EB              EX      DE,HL               ; Now into DE
090B: E1              POP     HL                  ; Restore HL
090C: 06 08           LD      B,$08               ; 8 bytes each
090E: D3 06           OUT     (WATCHDOG),A        ; Feed watchdog
0910: C3 39 14        JP      DrawSimpSprite      ; To screen

TimeToSaucer:
0913: 3A 09 20        LD      A,(refAlienYr)      ; Reference alien's X coordinate
0916: FE 78           CP      $78                 ; Don't process saucer timer ... ($78 is 1st rack Yr)
0918: D0              RET     NC                  ; ... unless aliens are closer to bottom
0919: 2A 91 20        LD      HL,(tillSaucerLSB)  ; Time to saucer
091C: 7D              LD      A,L                 ; Is it time ...
091D: B4              OR      H                   ; ... for a saucer
091E: C2 29 09        JP      NZ,$0929            ; No ... skip flagging
0921: 21 00 06        LD      HL,$0600            ; Reset timer to 600 game loops
0924: 3E 01           LD      A,$01               ; Flag a ...
0926: 32 83 20        LD      (saucerStart),A     ; ... saucer sequence
0929: 2B              DEC     HL                  ; Decrement the ...
092A: 22 91 20        LD      (tillSaucerLSB),HL  ; ... time-to-saucer
092D: C9              RET                         ; Done

;=============================================================
; Get number of ships for acive player
092E: CD 11 16        CALL    GetPlayerDataPtr    ; HL points to player data
0931: 2E FF           LD      L,$FF               ; Last byte = numbe of ships
0933: 7E              LD      A,(HL)              ; Get number of ships
0934: C9              RET                         ; Done

;=============================================================
; Award extra ship if score has reached ceiling
0935: CD 10 19        CALL    CurPlyAlive         ; Get descriptor of sorts
0938: 2B              DEC     HL                  ; Back up ...
0939: 2B              DEC     HL                  ; ... two bytes
093A: 7E              LD      A,(HL)              ; Has extra ship ...
093B: A7              AND     A                   ; already been awarded?
093C: C8              RET     Z                   ; Yes ... ignore
093D: 06 15           LD      B,$15               ; Default 1500
093F: DB 02           IN      A,(INP2)            ; Read DIP settings
0941: E6 08           AND     $08                 ; Extra ship at 1000 or 1500
0943: CA 48 09        JP      Z,$0948             ; 0=1500
0946: 06 10           LD      B,$10               ; Awarded at 1000
0948: CD CA 09        CALL    $09CA               ; Get score descriptor for active player
094B: 23              INC     HL                  ; MSB of score ...
094C: 7E              LD      A,(HL)              ; ... to accumulator
094D: B8              CP      B                   ; Time for an extra ship?
094E: D8              RET     C                   ; No ... out
094F: CD 2E 09        CALL    $092E               ; Get pointer to number of ships
0952: 34              INC     (HL)                ; Bump number of ships
0953: 7E              LD      A,(HL)              ; Get the new total
0954: F5              PUSH    AF                  ; Hang onto it for a bit
0955: 21 01 25        LD      HL,$2501            ; Screen coords for ship hold
0958: 24              INC     H                   ; Bump to ...
0959: 24              INC     H                   ; ... next
095A: 3D              DEC     A                   ; ... spot
095B: C2 58 09        JP      NZ,$0958            ; Find spot for new ship
095E: 06 10           LD      B,$10               ; 16 byte sprite
0960: 11 60 1C        LD      DE,$1C60            ; Player sprite
0963: CD 39 14        CALL    DrawSimpSprite      ; Draw the sprite
0966: F1              POP     AF                  ; Restore the count
0967: 3C              INC     A                   ; +1
0968: CD 8B 1A        CALL    $1A8B               ; Print the number of ships
096B: CD 10 19        CALL    CurPlyAlive         ; Get descriptor for active player of some sort
096E: 2B              DEC     HL                  ; Back up ...
096F: 2B              DEC     HL                  ; ... two bytes
0970: 36 00           LD      (HL),$00            ; Flag extra ship has been awarded
0972: 3E FF           LD      A,$FF               ; Set timer ...
0974: 32 99 20        LD      (extraHold),A       ; ... for extra-ship sound
0977: 06 10           LD      B,$10               ; Make sound ...
0979: C3 FA 18        JP      SoundBits3On        ; ... for extra man

AlienScoreValue:
097C: 21 A0 1D        LD      HL,$1DA0            ; Table for scores for hitting alien
097F: FE 02           CP      $02                 ; 0 or 1 (lower two rows) ...
0981: D8              RET     C                   ; ... return HL points to value 10
0982: 23              INC     HL                  ; next value
0983: FE 04           CP      $04                 ; 2 or 3 (middle two rows) ...
0985: D8              RET     C                   ; ... return HL points to value 20
0986: 23              INC     HL                  ; Top row ...
0987: C9              RET                         ; ... return HL points to value 30

AdjustScore:
; Adjust the score for the active player. 20F1 is 1 if there is a new value to add.
; The adjustment is in 20F2,20F3. Then print the score.
0988: CD CA 09        CALL    $09CA               ; Get score structure for active player
098B: 3A F1 20        LD      A,(adjustScore)     ; Does the score ...
098E: A7              AND     A                   ; ... need increasing?
098F: C8              RET     Z                   ; No ... done
0990: AF              XOR     A                   ; Mark score ...
0991: 32 F1 20        LD      (adjustScore),A     ; ... as adjusted
0994: E5              PUSH    HL                  ; Hold the pointer to the structure
0995: 2A F2 20        LD      HL,(scoreDeltaLSB)  ; Get requested adjustment
0998: EB              EX      DE,HL               ; Adjustment to DE
0999: E1              POP     HL                  ; Get back pointer to structure
099A: 7E              LD      A,(HL)              ; Add adjustment ...
099B: 83              ADD     A,E                 ; ... first byte
099C: 27              DAA                         ; Adjust it for BCD
099D: 77              LD      (HL),A              ; Store new LSB
099E: 5F              LD      E,A                 ; Add adjustment ...
099F: 23              INC     HL                  ; ... to ...
09A0: 7E              LD      A,(HL)              ; ... second ...
09A1: 8A              ADC     A,D                 ; ... byte
09A2: 27              DAA                         ; Adjust for BCD (cary gets dropped)
09A3: 77              LD      (HL),A              ; Store second byte
09A4: 57              LD      D,A                 ; Second byte to D (first byte still in E)
09A5: 23              INC     HL                  ; Load ...
09A6: 7E              LD      A,(HL)              ; ... the ...
09A7: 23              INC     HL                  ; ... screen ...
09A8: 66              LD      H,(HL)              ; ... coordinates ...
09A9: 6F              LD      L,A                 ; ... to HL
09AA: C3 AD 09        JP      Print4Digits        ; ** Usually a good idea, but wasted here

Print4Digits:
; Print 4 digits in DE
09AD: 7A              LD      A,D                 ; Get first 2 digits of BCD or hex
09AE: CD B2 09        CALL    DrawHexByte         ; Print them
09B1: 7B              LD      A,E                 ; Get second 2 digits of BCD or hex (fall into print)

DrawHexByte:
; Display 2 digits in A to screen at HL
09B2: D5              PUSH    DE                  ; Preserve
09B3: F5              PUSH    AF                  ; Save for later
09B4: 0F              RRCA                        ; Get ...
09B5: 0F              RRCA                        ; ...
09B6: 0F              RRCA                        ; ...
09B7: 0F              RRCA                        ; ... left digit
09B8: E6 0F           AND     $0F                 ; Mask out lower digit's bits
09BA: CD C5 09        CALL    $09C5               ; To screen at HL
09BD: F1              POP     AF                  ; Restore digit
09BE: E6 0F           AND     $0F                 ; Mask out upper digit
09C0: CD C5 09        CALL    $09C5               ; To screen
09C3: D1              POP     DE                  ; Restore
09C4: C9              RET                         ; Done
;
09C5: C6 1A           ADD     A,$1A               ; Bump to number characters
09C7: C3 FF 08        JP      DrawChar            ; Continue ...

; Get score descriptor for active player
09CA: 3A 67 20        LD      A,(playerDataMSB)   ; Get active player
09CD: 0F              RRCA                        ; Test for player
09CE: 21 F8 20        LD      HL,$20F8            ; Player 1 score descriptor
09D1: D8              RET     C                   ; Keep it if player 1 is active
09D2: 21 FC 20        LD      HL,$20FC            ; Else get player 2 descriptor
09D5: C9              RET                         ; Out

ClearPlayField:
; Clear center window of screen
09D6: 21 02 24        LD      HL,$2402            ; Thrid from left, top of screen
09D9: 36 00           LD      (HL),$00            ; Clear screen byte
09DB: 23              INC     HL                  ; Next in row
09DC: 7D              LD      A,L                 ; Get X ...
09DD: E6 1F           AND     $1F                 ; ... coordinate
09DF: FE 1C           CP      $1C                 ; Edge minus a buffer?
09E1: DA E8 09        JP      C,$09E8             ; No ... keep going
09E4: 11 06 00        LD      DE,$0006            ; Else ... bump to
09E7: 19              ADD     HL,DE               ; ... next edge + buffer
09E8: 7C              LD      A,H                 ; Get Y coordinate
09E9: FE 40           CP      $40                 ; Reached bottom?
09EB: DA D9 09        JP      C,$09D9             ; No ... keep going
09EE: C9              RET                         ; Done

09EF: CD 3C 0A        CALL    $0A3C               ; 
09F2: AF              XOR     A                   ; Suspend ...
09F3: 32 E9 20        LD      (suspendPlay),A     ; ... ISR game tasks
09F6: CD D6 09        CALL    ClearPlayField      ; Clear playfield
09F9: 3A 67 20        LD      A,(playerDataMSB)   ; Hold current player number ...
09FC: F5              PUSH    AF                  ; ... on stack
09FD: CD E4 01        CALL    CopyRAMMirror       ; Block copy RAM mirror from ROM
0A00: F1              POP     AF                  ; Restore ...
0A01: 32 67 20        LD      (playerDataMSB),A   ; ... current player number
0A04: 3A 67 20        LD      A,(playerDataMSB)   ; ** Why load this again? Nobody ever jumps to 0A04?
0A07: 67              LD      H,A                 ; To H
0A08: E5              PUSH    HL                  ; Hold player-data pointer
0A09: 2E FE           LD      L,$FE               ; 2xFE ... rack count
0A0B: 7E              LD      A,(HL)              ; Get the number of racks the player has beaten
0A0C: E6 07           AND     $07                 ; 0-7
0A0E: 3C              INC     A                   ; Now 1-8
0A0F: 77              LD      (HL),A              ; Update count since player just beat a rack
0A10: 21 A2 1D        LD      HL,$1DA2            ; Starting coordinate of alien table
0A13: 23              INC     HL                  ; Find the ...
0A14: 3D              DEC     A                   ; ... right entry ...
0A15: C2 13 0A        JP      NZ,$0A13            ; ... in the table
0A18: 7E              LD      A,(HL)              ; Get the starting Y coordiante
0A19: E1              POP     HL                  ; Restore player's pointer
0A1A: 2E FC           LD      L,$FC               ; 2xFC ...
0A1C: 77              LD      (HL),A              ; Set rack's starting Y coordinate
0A1D: 23              INC     HL                  ; Point to X
0A1E: 36 38           LD      (HL),$38            ; Set rack's starting X coordinate to 38
0A20: 7C              LD      A,H                 ; Player ...
0A21: 0F              RRCA                        ; ... number to carry
0A22: DA 33 0A        JP      C,$0A33             ; 2nd player stuff
0A25: 3E 21           LD      A,$21               ; Start fleet with ...
0A27: 32 98 20        LD      (soundPort5),A      ; ... first sound
0A2A: CD F5 01        CALL    DrawShieldPl2       ; Draw shields for player 2
0A2D: CD 04 19        CALL    InitAliensP2        ; Initalize aliens for player 2
0A30: C3 04 08        JP      $0804               ; Continue at top of game loop
;
0A33: CD EF 01        CALL    DrawShieldPl1       ; Draw shields for player 1
0A36: CD C0 01        CALL    InitAliens          ; Initialize aliens for player 1
0A39: C3 04 08        JP      $0804               ; Continue at top of game loop
;
0A3C: CD 59 0A        CALL    $0A59               ; Check player collision
0A3F: C2 52 0A        JP      NZ,$0A52            ; Player is not alive ... skip delay
0A42: 3E 30           LD      A,$30               ; Half second delay
0A44: 32 C0 20        LD      (isrDelay),A        ; Set ISR timer
0A47: 3A C0 20        LD      A,(isrDelay)        ; Has timer expired?
0A4A: A7              AND     A                   ; Check exipre
0A4B: C8              RET     Z                   ; Out if done
0A4C: CD 59 0A        CALL    $0A59               ; Check player collision
0A4F: CA 47 0A        JP      Z,$0A47             ; No collision ... wait on timer
0A52: CD 59 0A        CALL    $0A59               ; Wait for ...
0A55: C2 52 0A        JP      NZ,$0A52            ; ... collision to end
0A58: C9              RET                         ; Done

; Check to see if player is hit
0A59: 3A 15 20        LD      A,(playerAlive)     ; Active player hit flag
0A5C: FE FF           CP      $FF                 ; All FFs means player is OK
0A5E: C9              RET                         ; Out

ScoreForAlien:
; Start the hit-alien sound and flag the adjustment for the score.
; B contains the row, which determines the score value.
0A5F: 3A EF 20        LD      A,(gameMode)        ; Are we in ...
0A62: A7              AND     A                   ; ... game mode?
0A63: CA 7C 0A        JP      Z,$0A7C             ; No ... skip scoring in demo
0A66: 48              LD      C,B                 ; Hold row number
0A67: 06 08           LD      B,$08               ; Alien hit sound
0A69: CD FA 18        CALL    SoundBits3On        ; Enable sound
0A6C: 41              LD      B,C                 ; Restore row number
0A6D: 78              LD      A,B                 ; Into A
0A6E: CD 7C 09        CALL    AlienScoreValue     ; Look up the score for the alien
0A71: 7E              LD      A,(HL)              ; Get the score value
0A72: 21 F3 20        LD      HL,$20F3            ; Pointer to score delta
0A75: 36 00           LD      (HL),$00            ; Upper byte of score delta is "00"
0A77: 2B              DEC     HL                  ; Point to score delta LSB
0A78: 77              LD      (HL),A              ; Set score for hitting alien
0A79: 2B              DEC     HL                  ; Point to adjust-score-flag
0A7A: 36 01           LD      (HL),$01            ; The score will get changed elsewhere
0A7C: 21 62 20        LD      HL,$2062            ; Return exploding-alien descriptor
0A7F: C9              RET                         ; Out

Animate:
; Start the ISR moving the sprite. Return when done.
0A80: 3E 02           LD      A,$02               ; Start simple linear ...
0A82: 32 C1 20        LD      (isrSplashTask),A   ; ... sprite animation (splash)
0A85: D3 06           OUT     (WATCHDOG),A        ; Feed watchdog
0A87: 3A CB 20        LD      A,(splashReached)   ; Has the ...
0A8A: A7              AND     A                   ; ... sprite reached target?
0A8B: CA 85 0A        JP      Z,$0A85             ; No ... wait
0A8E: AF              XOR     A                   ; Stop ...
0A8F: 32 C1 20        LD      (isrSplashTask),A   ; ... ISR animation
0A92: C9              RET                         ; Done

PrintMessageDel:
; Print message from DE to screen at HL (length in C) with a
; delay between letters.
0A93: D5              PUSH    DE                  ; Preserve
0A94: 1A              LD      A,(DE)              ; Get character
0A95: CD FF 08        CALL    DrawChar            ; Draw character on screen
0A98: D1              POP     DE                  ; Preserve
0A99: 3E 07           LD      A,$07               ; Delay between letters
0A9B: 32 C0 20        LD      (isrDelay),A        ; Set counter
0A9E: 3A C0 20        LD      A,(isrDelay)        ; Get counter
0AA1: 3D              DEC     A                   ; Is it 1?
0AA2: C2 9E 0A        JP      NZ,$0A9E            ; No ... wait on it
0AA5: 13              INC     DE                  ; Next in message
0AA6: 0D              DEC     C                   ; All done?
0AA7: C2 93 0A        JP      NZ,PrintMessageDel  ; No ... do all
0AAA: C9              RET                         ; Out

SplashSquiggly:
0AAB: 21 50 20        LD      HL,$2050            ; Pointer to game-object 4 timer
0AAE: C3 4B 02        JP      $024B               ; Process squiggly-shot in demo mode

OneSecDelay:
; Delay 64 interrupts
0AB1: 3E 40           LD      A,$40               ; Delay of 64 (tad over 1 sec)
0AB3: C3 D7 0A        JP      WaitOnDelay         ; Do delay

TwoSecDelay:
; Delay 128 interrupts
0AB6: 3E 80           LD      A,$80               ; Delay of 80 (tad over 2 sec)
0AB8: C3 D7 0A        JP      WaitOnDelay         ; Do delay

SplashDemo:
0ABB: E1              POP     HL                  ; Drop the call to ABF and ...
0ABC: C3 72 00        JP      $0072               ; ... do a demo game loop without sound

ISRSplTasks:
; Different types of splash tasks managed by ISR in splash screens. The ISR
; calls this if in splash-mode. These may have been bit flags to allow all 3
; at the same time. Maybe it is just easier to do a switch with a rotate-to-carry.
;
0ABF: 3A C1 20        LD      A,(isrSplashTask)   ; Get the ISR task number
0AC2: 0F              RRCA                        ; In demo play mode?
0AC3: DA BB 0A        JP      C,SplashDemo        ; 1: Yes ... go do game play (without sound)
0AC6: 0F              RRCA                        ; Moving little alien from point A to B?
0AC7: DA 68 18        JP      C,SplashSprite      ; 2: Yes ... go move little alien from point A to B
0ACA: 0F              RRCA                        ; Shooting extra "C" with squiggly shot?
0ACB: DA AB 0A        JP      C,SplashSquiggly    ; 4: Yes ... go shoot extra "C" in splash
0ACE: C9              RET                         ; No task to do

; Message to center of screen.
; Only used in one place for "SPACE  INVADERS"
0ACF: 21 14 2B        LD      HL,$2B14            ; Near center of screen
0AD2: 0E 0F           LD      C,$0F               ; 15 bytes in message
0AD4: C3 93 0A        JP      PrintMessageDel     ; Print and out

WaitOnDelay:
; Wait on ISR counter to reach 0
0AD7: 32 C0 20        LD      (isrDelay),A        ; Delay counter
0ADA: 3A C0 20        LD      A,(isrDelay)        ; Get current delay
0ADD: A7              AND     A                   ; Zero yet?
0ADE: C2 DA 0A        JP      NZ,$0ADA            ; No ... wait on it
0AE1: C9              RET                         ; Out

IniSplashAni:
; Init the splash-animation block
0AE2: 21 C2 20        LD      HL,$20C2            ; The splash-animation descriptor
0AE5: 06 0C           LD      B,$0C               ; C bytes
0AE7: C3 32 1A        JP      BlockCopy           ; Block copy DE to descriptor

;=============================================================
; After initialization ... splash screens
0AEA: AF              XOR     A                   ; Make a 0
0AEB: D3 03           OUT     (SOUND1),A          ; Turn off sound
0AED: D3 05           OUT     (SOUND2),A          ; Turn off sound
0AEF: CD 82 19        CALL    $1982               ; Turn off ISR splash-task
0AF2: FB              EI                          ; Enable interrupts (using them for delays)
0AF3: CD B1 0A        CALL    OneSecDelay         ; One second delay
0AF6: 3A EC 20        LD      A,(splashAnimate)   ; Splash screen type
0AF9: A7              AND     A                   ; Set flags based on type
0AFA: 21 17 30        LD      HL,$3017            ; Screen coordinates (middle near top)
0AFD: 0E 04           LD      C,$04               ; 4 characters in "PLAY"
0AFF: C2 E8 0B        JP      NZ,$0BE8            ; Not 0 ... do "normal" PLAY
0B02: 11 FA 1C        LD      DE,$1CFA            ; The "PLAy" with an upside down 'Y'
0B05: CD 93 0A        CALL    PrintMessageDel     ; Print the "PLAy"
0B08: 11 AF 1D        LD      DE,$1DAF            ; "SPACE  INVADERS" message
0B0B: CD CF 0A        CALL    $0ACF               ; Print to middle-ish of screen
0B0E: CD B1 0A        CALL    OneSecDelay         ; One second delay
0B11: CD 15 18        CALL    DrawAdvTable        ; Draw "SCORE ADVANCE TABLE" with print delay
0B14: CD B6 0A        CALL    TwoSecDelay         ; Two second delay
0B17: 3A EC 20        LD      A,(splashAnimate)   ; Do splash ...
0B1A: A7              AND     A                   ; ... animations?
0B1B: C2 4A 0B        JP      NZ,$0B4A            ; Not 0 ... no animations
;
; Animate small alien replacing upside-down Y with correct Y
0B1E: 11 95 1A        LD      DE,$1A95            ; Animate sprite from Y=FE to Y=9E step -1
0B21: CD E2 0A        CALL    IniSplashAni        ; Copy to splash-animate structure
0B24: CD 80 0A        CALL    Animate             ; Wait for ISR to move sprite (small alien)
0B27: 11 B0 1B        LD      DE,$1BB0            ; Animate sprite from Y=98 to Y=FF step 1
0B2A: CD E2 0A        CALL    IniSplashAni        ; Copy to splash-animate structure
0B2D: CD 80 0A        CALL    Animate             ; Wait for ISR to move sprite (alien pulling upside down Y)
0B30: CD B1 0A        CALL    OneSecDelay         ; One second delay
0B33: 11 C9 1F        LD      DE,$1FC9            ; Animate sprite from Y=FF to Y=97 step 1
0B36: CD E2 0A        CALL    IniSplashAni        ; Copy to splash-animate structure
0B39: CD 80 0A        CALL    Animate             ; Wait for ISR to move sprite (alien pushing Y)
0B3C: CD B1 0A        CALL    OneSecDelay         ; One second delay
0B3F: 21 B7 33        LD      HL,$33B7            ; Where the splash alien ends up
0B42: 06 0A           LD      B,$0A               ; 10 rows
0B44: CD CB 14        CALL    ClearSmallSprite    ; Clear a one byte sprite at HL
0B47: CD B6 0A        CALL    TwoSecDelay         ; Two second delay
;
; Play demo
0B4A: CD D6 09        CALL    ClearPlayField      ; Clear playfield
0B4D: 3A FF 21        LD      A,(p1ShipsRem)      ; Number of ships for player-1
0B50: A7              AND     A                   ; If non zero ...
0B51: C2 5D 0B        JP      NZ,$0B5D            ; ... keep it (counts down between demos)
0B54: CD D1 08        CALL    GetShipsPerCred     ; Get number of ships from DIP settings
0B57: 32 FF 21        LD      (p1ShipsRem),A      ; Reset number of ships for player-1
0B5A: CD 7F 1A        CALL    RemoveShip          ; Remove a ship from stash and update indicators
;
0B5D: CD E4 01        CALL    CopyRAMMirror       ; Block copy ROM mirror to initialize RAM
0B60: CD C0 01        CALL    InitAliens          ; Initialize all player 1 aliens
0B63: CD EF 01        CALL    DrawShieldPl1       ; Draw shields for player 1 (to buffer)
0B66: CD 1A 02        CALL    RestoreShields1     ; Restore shields for player 1 (to screen)
0B69: 3E 01           LD      A,$01               ; ISR splash-task ...
0B6B: 32 C1 20        LD      (isrSplashTask),A   ; ... playing demo
0B6E: CD CF 01        CALL    DrawBottomLine      ; Draw playfield line
;
0B71: CD 18 16        CALL    PlrFireOrDemo       ; In demo ... process demo movement and always fire
0B74: CD F1 0B        CALL    $0BF1               ; Check player shot and aliens bumping edges of screen and hidden message
0B77: D3 06           OUT     (WATCHDOG),A        ; Feed watchdog
0B79: CD 59 0A        CALL    $0A59               ; Has demo player been hit?
0B7C: CA 71 0B        JP      Z,$0B71             ; No ... continue game
0B7F: AF              XOR     A                   ; Remove player shot ...
0B80: 32 25 20        LD      (plyrShotStatus),A  ; ... from activity
0B83: CD 59 0A        CALL    $0A59               ; Wait for demo player ...
0B86: C2 83 0B        JP      NZ,$0B83            ; ... to stop exploding
;
; Credit information
0B89: AF              XOR     A                   ; Turn off ...
0B8A: 32 C1 20        LD      (isrSplashTask),A   ; ... splash animation
0B8D: CD B1 0A        CALL    OneSecDelay         ; One second delay
0B90: CD 88 19        CALL    $1988               ; ** Something else at one time? Jump straight to clear-play-field
0B93: 0E 0C           LD      C,$0C               ; Message size
0B95: 21 11 2C        LD      HL,$2C11            ; Screen coordinates
0B98: 11 90 1F        LD      DE,$1F90            ; "INSERT  COIN"
0B9B: CD F3 08        CALL    PrintMessage        ; Print message
0B9E: 3A EC 20        LD      A,(splashAnimate)   ; Do splash ...
0BA1: FE 00           CP      $00                 ; ... animations?
0BA3: C2 AE 0B        JP      NZ,$0BAE            ; Not 0 ... not on this screen
0BA6: 21 11 33        LD      HL,$3311            ; Screen coordinates
0BA9: 3E 02           LD      A,$02               ; Character "C"
0BAB: CD FF 08        CALL    DrawChar            ; Put an extra "C" for "CCOIN" on the screen
0BAE: 01 9C 1F        LD      BC,$1F9C            ; "<1 OR 2 PLAYERS>  "
0BB1: CD 56 18        CALL    ReadPriStruct       ; Load the screen,pointer
0BB4: CD 4C 18        CALL    $184C               ; Print the message
0BB7: DB 02           IN      A,(INP2)            ; Display coin info (bit 7) ...
0BB9: 07              RLCA                        ; ... on demo screen?
0BBA: DA C3 0B        JP      C,$0BC3             ; 1 means no ... skip it
0BBD: 01 A0 1F        LD      BC,$1FA0            ; "*1 PLAYER  1 COIN "
0BC0: CD 3A 18        CALL    $183A               ; Load the descriptor
0BC3: CD B6 0A        CALL    TwoSecDelay         ; Print TWO descriptors worth
0BC6: 3A EC 20        LD      A,(splashAnimate)   ; Doing splash ...
0BC9: FE 00           CP      $00                 ; ... animation?
0BCB: C2 DA 0B        JP      NZ,$0BDA            ; Not 0 ... not on this screen
0BCE: 11 D5 1F        LD      DE,$1FD5            ; Animation for small alien to line up with extra "C"
0BD1: CD E2 0A        CALL    IniSplashAni        ; Copy the animation block
0BD4: CD 80 0A        CALL    Animate             ; Wait for the animation to complete
0BD7: CD 9E 18        CALL    $189E               ; Animate alien shot to extra "C"
0BDA: 21 EC 20        LD      HL,$20EC            ; Toggle ...
0BDD: 7E              LD      A,(HL)              ; ... the ...
0BDE: 3C              INC     A                   ; ... splash screen ...
0BDF: E6 01           AND     $01                 ; ... animation for ...
0BE1: 77              LD      (HL),A              ; ... next time
0BE2: CD D6 09        CALL    ClearPlayField      ; Clear play field
0BE5: C3 DF 18        JP      $18DF               ; Keep splashing

0BE8: 11 AB 1D        LD      DE,$1DAB            ; "PLAY" with normal 'Y'
0BEB: CD 93 0A        CALL    PrintMessageDel     ; Print it
0BEE: C3 0B 0B        JP      $0B0B               ; Continue with splash (HL will be pointing to next message)

0BF1: CD 0A 19        CALL    PlyrShotAndBump     ; Check if player is shot and aliens bumping the edge of screen
0BF4: C3 9A 19        JP      CheckHiddenMes      ; Check for hidden-message display sequence

MessageCorp:
; "TAITO COP"
0BF7: 13 00 08 13 0E 26 02 0E 0F

Diagnostics Routine

The very center 2K of the code map is an expansion area. It originally contained a 1K diagnostics routine beginning at 1000. The original code would check bit 0 of port 0 (wired to DIP4) and jump to this routine if the switch was flipped. The routine was removed in this Midway version of the code. And it was removed in later versions of the TAITO code line.

The original routine is shown here for reference.

0C00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0C20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0C40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0C60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0C80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0CA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0CC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0CE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

0D00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0D20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0D40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0D60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0D80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0DA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0DC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0DE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

0E00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0E20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0E40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0E60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0E80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0EA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0EC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0EE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

0F00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0F20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0F40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0F60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0F80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0FA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0FC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0FE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

; The original TAITO code had a self-check routine here. The opening jump was to E2, which was a
; check on bit 0 of port 0 (the DIP4 switch for self test). If the bit was set the code came here.
; When Midway branched the code, they left the check out.

1000: 00              NOP                         ; Three bytes for ...
1001: 00              NOP                         ; ... development code ...
1002: 00              NOP                         ; ... jump opcode
;
1003: AF              XOR     A                   ; Turn off ...
1004: D3 03           OUT     (SOUND1),A          ; ... sound effects (AMP ENABLE bit 5)
1006: 0E 03           LD      C,$03               ;
1008: 06 55           LD      B,$55               ;
100A: 21 00 20        LD      HL,$2000            ;
100D: 70              LD      (HL),B              ;
100E: 23              INC     HL                  ;
100F: 7C              LD      A,H                 ;
1010: FE 40           CP      $40                 ;
1012: C2 0D 10        JP      NZ,$100D            ; 
1015: 21 00 20        LD      HL,$2000            ;
1018: 7E              LD      A,(HL)              ;
1019: A8              XOR     B                   ;
101A: C2 90 11        JP      NZ,$1190            ; 
101D: 23              INC     HL                  ;
101E: 7C              LD      A,H                 ;
101F: FE 40           CP      $40                 ;
1021: C2 18 10        JP      NZ,$1018            ; 
1024: 06 AA           LD      B,$AA               ;
1026: 21 00 20        LD      HL,$2000            ;
1029: 70              LD      (HL),B              ;
102A: 23              INC     HL                  ;
102B: 7C              LD      A,H                 ;
102C: FE 40           CP      $40                 ;
102E: C2 29 10        JP      NZ,$1029            ; 
1031: 21 00 20        LD      HL,$2000            ;
1034: 7E              LD      A,(HL)              ;
1035: A8              XOR     B                   ;
1036: C2 90 11        JP      NZ,$1190            ; 
1039: 23              INC     HL                  ;
103A: 7C              LD      A,H                 ;
103B: FE 40           CP      $40                 ;
103D: C2 34 10        JP      NZ,$1034            ; 
1040: 0D              DEC     C                   ;
1041: C2 08 10        JP      NZ,$1008            ; 
1044: 21 00 20        LD      HL,$2000            ;
1047: 06 00           LD      B,$00               ;
1049: 78              LD      A,B                 ;
104A: 77              LD      (HL),A              ;
104B: 23              INC     HL                  ;
104C: 04              INC     B                   ;
104D: 78              LD      A,B                 ;
104E: FE FF           CP      $FF                 ;
1050: C2 55 10        JP      NZ,$1055            ; 
1053: 06 00           LD      B,$00               ;
1055: 7C              LD      A,H                 ;
1056: FE 40           CP      $40                 ;
1058: C2 49 10        JP      NZ,$1049            ; 
105B: 21 00 20        LD      HL,$2000            ;
105E: 06 00           LD      B,$00               ;
1060: 7E              LD      A,(HL)              ;
1061: A8              XOR     B                   ;
1062: C2 90 11        JP      NZ,$1190            ; 
1065: 04              INC     B                   ;
1066: 78              LD      A,B                 ;
1067: FE FF           CP      $FF                 ;
1069: C2 6E 10        JP      NZ,$106E            ; 
106C: 06 00           LD      B,$00               ;
106E: 23              INC     HL                  ;
106F: 7C              LD      A,H                 ;
1070: FE 40           CP      $40                 ;
1072: C2 60 10        JP      NZ,$1060            ; 
1075: 31 00 24        LD      SP,$2400            ;
1078: CD 83 11        CALL    $1183               ; 
107B: 11 48 13        LD      DE,$1348            ;
107E: 21 01 25        LD      HL,$2501            ;
1081: CD 55 11        CALL    $1155               ; 
1084: 21 01 27        LD      HL,$2701            ;
1087: CD 55 11        CALL    $1155               ; 
108A: 21 01 33        LD      HL,$3301            ;
108D: CD 55 11        CALL    $1155               ; 
1090: 21 07 2A        LD      HL,$2A07            ;
1093: 0E 0F           LD      C,$0F               ;
1095: 11 6F 13        LD      DE,$136F            ;
1098: D5              PUSH    DE                  ;
1099: CD 57 11        CALL    $1157               ; 
109C: D1              POP     DE                  ;
109D: 21 07 2E        LD      HL,$2E07            ;
10A0: 0E 0F           LD      C,$0F               ;
10A2: CD 57 11        CALL    $1157               ; 
10A5: 3E 1D           LD      A,$1D               ;
10A7: 21 0B 2E        LD      HL,$2E0B            ;
10AA: CD 66 11        CALL    $1166               ; 
10AD: 06 0B           LD      B,$0B               ;
10AF: 21 0E 34        LD      HL,$340E            ;
10B2: 11 7E 13        LD      DE,$137E            ;
10B5: 0E 06           LD      C,$06               ;
10B7: C5              PUSH    BC                  ;
10B8: CD 57 11        CALL    $1157               ; 
10BB: 01 FA 00        LD      BC,$00FA            ;
10BE: 09              ADD     HL,BC               ;
10BF: C1              POP     BC                  ;
10C0: 05              DEC     B                   ;
10C1: C2 B5 10        JP      NZ,$10B5            ; 
10C4: 06 02           LD      B,$02               ;
10C6: C5              PUSH    BC                  ;
10C7: 21 0D 34        LD      HL,$340D            ;
10CA: 22 00 20        LD      (waitOnDraw),HL     ; 
10CD: 3E 01           LD      A,$01               ;
10CF: F5              PUSH    AF                  ;
10D0: F6 20           OR      $20                 ;
10D2: D3 03           OUT     (SOUND1),A          ; 
10D4: CD 05 11        CALL    $1105               ; 
10D7: 3E 20           LD      A,$20               ;
10D9: D3 03           OUT     (SOUND1),A          ; 
10DB: CD 10 11        CALL    $1110               ; 
10DE: F1              POP     AF                  ;
10DF: 07              RLCA                        ;
10E0: FE 20           CP      $20                 ;
10E2: C2 CF 10        JP      NZ,$10CF            ; 
10E5: 3E 01           LD      A,$01               ;
10E7: F5              PUSH    AF                  ;
10E8: D3 05           OUT     (SOUND2),A          ; 
10EA: CD 05 11        CALL    $1105               ; 
10ED: AF              XOR     A                   ;
10EE: D3 05           OUT     (SOUND2),A          ; 
10F0: CD 10 11        CALL    $1110               ; 
10F3: F1              POP     AF                  ;
10F4: 07              RLCA                        ;
10F5: FE 40           CP      $40                 ;
10F7: C2 E7 10        JP      NZ,$10E7            ; 
10FA: C1              POP     BC                  ;
10FB: 05              DEC     B                   ;
10FC: C2 C6 10        JP      NZ,$10C6            ; 
10FF: CD 29 11        CALL    $1129               ; 
1102: C3 FF 10        JP      $10FF               ; 
1105: 2A 00 20        LD      HL,(waitOnDraw)     ; 
1108: 3E 0F           LD      A,$0F               ;
110A: CD 66 11        CALL    $1166               ; 
110D: C3 1F 11        JP      $111F               ; 
1110: CD 1F 11        CALL    $111F               ; 
1113: 2A 00 20        LD      HL,(waitOnDraw)     ; 
1116: 3E 28           LD      A,$28               ;
1118: CD 66 11        CALL    $1166               ; 
111B: 22 00 20        LD      (waitOnDraw),HL     ; 
111E: C9              RET                         ;
111F: 3E 60           LD      A,$60               ;
1121: CD CE 11        CALL    $11CE               ; 
1124: 3D              DEC     A                   ;
1125: C2 21 11        JP      NZ,$1121            ; 
1128: C9              RET                         ;
1129: F5              PUSH    AF                  ;
112A: 21 0E 2B        LD      HL,$2B0E            ;
112D: DB 01           IN      A,(INP1)            ; 
112F: CD 3C 11        CALL    $113C               ; 
1132: 21 0E 2F        LD      HL,$2F0E            ;
1135: DB 02           IN      A,(INP2)            ; 
1137: CD 3C 11        CALL    $113C               ; 
113A: F1              POP     AF                  ;
113B: C9              RET                         ;
113C: 06 08           LD      B,$08               ;
113E: C5              PUSH    BC                  ;
113F: E5              PUSH    HL                  ;
1140: 0F              RRCA                        ;
1141: F5              PUSH    AF                  ;
1142: 3E 28           LD      A,$28               ;
1144: DA 49 11        JP      C,$1149             ; 
1147: 3E 25           LD      A,$25               ;
1149: CD 66 11        CALL    $1166               ; 
114C: F1              POP     AF                  ;
114D: E1              POP     HL                  ;
114E: 23              INC     HL                  ;
114F: C1              POP     BC                  ;
1150: 05              DEC     B                   ;
1151: C2 3E 11        JP      NZ,$113E            ; 
1154: C9              RET                         ;
1155: 0E 0D           LD      C,$0D               ;
1157: 1A              LD      A,(DE)              ;
1158: D5              PUSH    DE                  ;
1159: E5              PUSH    HL                  ;
115A: CD 66 11        CALL    $1166               ; 
115D: E1              POP     HL                  ;
115E: 23              INC     HL                  ;
115F: D1              POP     DE                  ;
1160: 13              INC     DE                  ;
1161: 0D              DEC     C                   ;
1162: C2 57 11        JP      NZ,$1157            ; 
1165: C9              RET                         ;
1166: 11 00 12        LD      DE,$1200            ;
1169: E5              PUSH    HL                  ;
116A: 6F              LD      L,A                 ;
116B: 26 00           LD      H,$00               ;
116D: 29              ADD     HL,HL               ;
116E: 29              ADD     HL,HL               ;
116F: 29              ADD     HL,HL               ;
1170: 19              ADD     HL,DE               ;
1171: EB              EX      DE,HL               ;
1172: E1              POP     HL                  ;
1173: 06 08           LD      B,$08               ;
1175: C5              PUSH    BC                  ;
1176: 1A              LD      A,(DE)              ;
1177: 77              LD      (HL),A              ;
1178: 13              INC     DE                  ;
1179: 01 20 00        LD      BC,$0020            ;
117C: 09              ADD     HL,BC               ;
117D: C1              POP     BC                  ;
117E: 05              DEC     B                   ;
117F: C2 75 11        JP      NZ,$1175            ; 
1182: C9              RET                         ;
1183: 21 00 24        LD      HL,$2400            ;
1186: 36 00           LD      (HL),$00            ;
1188: 23              INC     HL                  ;
1189: 7C              LD      A,H                 ;
118A: FE 40           CP      $40                 ;
118C: C2 86 11        JP      NZ,$1186            ; 
118F: C9              RET                         ;
1190: 06 01           LD      B,$01               ;
1192: 0F              RRCA                        ;
1193: DA 9A 11        JP      C,$119A             ; 
1196: 04              INC     B                   ;
1197: C3 92 11        JP      $1192               ; 
119A: 7D              LD      A,L                 ;
119B: 21 D8 12        LD      HL,$12D8            ;
119E: 0F              RRCA                        ;
119F: D2 A5 11        JP      NC,$11A5            ; 
11A2: 21 B8 13        LD      HL,$13B8            ;
11A5: 78              LD      A,B                 ;
11A6: 07              RLCA                        ;
11A7: 07              RLCA                        ;
11A8: 07              RLCA                        ;
11A9: 47              LD      B,A                 ;
11AA: 58              LD      E,B                 ;
11AB: 16 00           LD      D,$00               ;
11AD: 19              ADD     HL,DE               ;
11AE: EB              EX      DE,HL               ;
11AF: 06 08           LD      B,$08               ;
11B1: 21 11 30        LD      HL,$3011            ;
11B4: 1A              LD      A,(DE)              ;
11B5: 77              LD      (HL),A              ;
11B6: 78              LD      A,B                 ;
11B7: 01 20 00        LD      BC,$0020            ;
11BA: 09              ADD     HL,BC               ;
11BB: 47              LD      B,A                 ;
11BC: 13              INC     DE                  ;
11BD: 05              DEC     B                   ;
11BE: C2 B4 11        JP      NZ,$11B4            ; 
11C1: 06 08           LD      B,$08               ;
11C3: 21 12 30        LD      HL,$3012            ;
11C6: 11 40 13        LD      DE,$1340            ;
11C9: D3 06           OUT     (WATCHDOG),A        ; 
11CB: C3 B4 11        JP      $11B4               ; 
11CE: CD 29 11        CALL    $1129               ; 
11D1: D3 06           OUT     (WATCHDOG),A        ; 
11D3: C9              RET                         ;
11D4: FF              RST     0X38                ;
11D5: FF              RST     0X38                ;
11D6: FF              RST     0X38                ;
11D7: FF              RST     0X38                ;
11D8: FF              RST     0X38                ;
11D9: FF              RST     0X38                ;
11DA: FF              RST     0X38                ;
11DB: FF              RST     0X38                ;
11DC: FF              RST     0X38                ;
11DD: FF              RST     0X38                ;
11DE: FF              RST     0X38                ;
11DF: FF              RST     0X38                ;
11E0: FF              RST     0X38                ;
11E1: FF              RST     0X38                ;
11E2: FF              RST     0X38                ;
11E3: FF              RST     0X38                ;
11E4: FF              RST     0X38                ;
11E5: FF              RST     0X38                ;
11E6: FF              RST     0X38                ;
11E7: FF              RST     0X38                ;
11E8: FF              RST     0X38                ;
11E9: FF              RST     0X38                ;
11EA: FF              RST     0X38                ;
11EB: FF              RST     0X38                ;
11EC: FF              RST     0X38                ;
11ED: FF              RST     0X38                ;
11EE: FF              RST     0X38                ;
11EF: FF              RST     0X38                ;
11F0: FF              RST     0X38                ;
11F1: FF              RST     0X38                ;
11F2: FF              RST     0X38                ;
11F3: FF              RST     0X38                ;
11F4: FF              RST     0X38                ;
11F5: FF              RST     0X38                ;
11F6: FF              RST     0X38                ;
11F7: FF              RST     0X38                ;
11F8: FF              RST     0X38                ;
11F9: FF              RST     0X38                ;
11FA: FF              RST     0X38                ;
11FB: FF              RST     0X38                ;
11FC: FF              RST     0X38                ;
11FD: FF              RST     0X38                ;
11FE: FF              RST     0X38                ;
11FF: FF              RST     0X38                ;
1200: 00              NOP                         ;
1201: 70              LD      (HL),B              ;
1202: 88              ADC     A,B                 ;
1203: A8              XOR     B                   ;
1204: E8              RET     PE                  ;
1205: 68              LD      L,B                 ;
1206: 08              EX      AF,AF'              ;
1207: F0              RET     P                   ;
1208: 00              NOP                         ;
1209: 20 50           JR      NZ,$125B            ; 
120B: 88              ADC     A,B                 ;
120C: 88              ADC     A,B                 ;
120D: F8              RET     M                   ;
120E: 88              ADC     A,B                 ;
120F: 88              ADC     A,B                 ;
1210: 00              NOP                         ;
1211: 78              LD      A,B                 ;
1212: 88              ADC     A,B                 ;
1213: 88              ADC     A,B                 ;
1214: 78              LD      A,B                 ;
1215: 88              ADC     A,B                 ;
1216: 88              ADC     A,B                 ;
1217: 78              LD      A,B                 ;
1218: 00              NOP                         ;
1219: 70              LD      (HL),B              ;
121A: 88              ADC     A,B                 ;
121B: 08              EX      AF,AF'              ;
121C: 08              EX      AF,AF'              ;
121D: 08              EX      AF,AF'              ;
121E: 88              ADC     A,B                 ;
121F: 70              LD      (HL),B              ;
1220: 00              NOP                         ;
1221: 78              LD      A,B                 ;
1222: 88              ADC     A,B                 ;
1223: 88              ADC     A,B                 ;
1224: 88              ADC     A,B                 ;
1225: 88              ADC     A,B                 ;
1226: 88              ADC     A,B                 ;
1227: 78              LD      A,B                 ;
1228: 00              NOP                         ;
1229: F8              RET     M                   ;
122A: 08              EX      AF,AF'              ;
122B: 08              EX      AF,AF'              ;
122C: 78              LD      A,B                 ;
122D: 08              EX      AF,AF'              ;
122E: 08              EX      AF,AF'              ;
122F: F8              RET     M                   ;
1230: 00              NOP                         ;
1231: F8              RET     M                   ;
1232: 08              EX      AF,AF'              ;
1233: 08              EX      AF,AF'              ;
1234: 78              LD      A,B                 ;
1235: 08              EX      AF,AF'              ;
1236: 08              EX      AF,AF'              ;
1237: 08              EX      AF,AF'              ;
1238: 00              NOP                         ;
1239: F0              RET     P                   ;
123A: 08              EX      AF,AF'              ;
123B: 08              EX      AF,AF'              ;
123C: 08              EX      AF,AF'              ;
123D: C8              RET     Z                   ;
123E: 88              ADC     A,B                 ;
123F: F0              RET     P                   ;
1240: 00              NOP                         ;
1241: 88              ADC     A,B                 ;
1242: 88              ADC     A,B                 ;
1243: 88              ADC     A,B                 ;
1244: F8              RET     M                   ;
1245: 88              ADC     A,B                 ;
1246: 88              ADC     A,B                 ;
1247: 88              ADC     A,B                 ;
1248: 00              NOP                         ;
1249: 70              LD      (HL),B              ;
124A: 20 20           JR      NZ,$126C            ; 
124C: 20 20           JR      NZ,$126E            ; 
124E: 20 70           JR      NZ,$12C0            ; 
1250: 00              NOP                         ;
1251: 80              ADD     A,B                 ;
1252: 80              ADD     A,B                 ;
1253: 80              ADD     A,B                 ;
1254: 80              ADD     A,B                 ;
1255: 80              ADD     A,B                 ;
1256: 88              ADC     A,B                 ;
1257: 70              LD      (HL),B              ;
1258: 00              NOP                         ;
1259: 88              ADC     A,B                 ;
125A: 48              LD      C,B                 ;
125B: 28 18           JR      Z,$1275             ; 
125D: 28 48           JR      Z,$12A7             ; 
125F: 88              ADC     A,B                 ;
1260: 00              NOP                         ;
1261: 08              EX      AF,AF'              ;
1262: 08              EX      AF,AF'              ;
1263: 08              EX      AF,AF'              ;
1264: 08              EX      AF,AF'              ;
1265: 08              EX      AF,AF'              ;
1266: 08              EX      AF,AF'              ;
1267: F8              RET     M                   ;
1268: 00              NOP                         ;
1269: 88              ADC     A,B                 ;
126A: D8              RET     C                   ;
126B: A8              XOR     B                   ;
126C: A8              XOR     B                   ;
126D: 88              ADC     A,B                 ;
126E: 88              ADC     A,B                 ;
126F: 88              ADC     A,B                 ;
1270: 00              NOP                         ;
1271: 88              ADC     A,B                 ;
1272: 88              ADC     A,B                 ;
1273: 98              SBC     B                   ;
1274: A8              XOR     B                   ;
1275: C8              RET     Z                   ;
1276: 88              ADC     A,B                 ;
1277: 88              ADC     A,B                 ;
1278: 00              NOP                         ;
1279: 70              LD      (HL),B              ;
127A: 88              ADC     A,B                 ;
127B: 88              ADC     A,B                 ;
127C: 88              ADC     A,B                 ;
127D: 88              ADC     A,B                 ;
127E: 88              ADC     A,B                 ;
127F: 70              LD      (HL),B              ;
1280: 00              NOP                         ;
1281: 78              LD      A,B                 ;
1282: 88              ADC     A,B                 ;
1283: 88              ADC     A,B                 ;
1284: 78              LD      A,B                 ;
1285: 08              EX      AF,AF'              ;
1286: 08              EX      AF,AF'              ;
1287: 08              EX      AF,AF'              ;
1288: 00              NOP                         ;
1289: 70              LD      (HL),B              ;
128A: 88              ADC     A,B                 ;
128B: 88              ADC     A,B                 ;
128C: 88              ADC     A,B                 ;
128D: A8              XOR     B                   ;
128E: 48              LD      C,B                 ;
128F: B0              OR      B                   ;
1290: 00              NOP                         ;
1291: 78              LD      A,B                 ;
1292: 88              ADC     A,B                 ;
1293: 88              ADC     A,B                 ;
1294: 78              LD      A,B                 ;
1295: 28 48           JR      Z,$12DF             ; 
1297: 88              ADC     A,B                 ;
1298: 00              NOP                         ;
1299: 70              LD      (HL),B              ;
129A: 88              ADC     A,B                 ;
129B: 08              EX      AF,AF'              ;
129C: 70              LD      (HL),B              ;
129D: 80              ADD     A,B                 ;
129E: 88              ADC     A,B                 ;
129F: 70              LD      (HL),B              ;
12A0: 00              NOP                         ;
12A1: F8              RET     M                   ;
12A2: 20 20           JR      NZ,$12C4            ; 
12A4: 20 20           JR      NZ,$12C6            ; 
12A6: 20 20           JR      NZ,$12C8            ; 
12A8: 00              NOP                         ;
12A9: 88              ADC     A,B                 ;
12AA: 88              ADC     A,B                 ;
12AB: 88              ADC     A,B                 ;
12AC: 88              ADC     A,B                 ;
12AD: 88              ADC     A,B                 ;
12AE: 88              ADC     A,B                 ;
12AF: 70              LD      (HL),B              ;
12B0: 00              NOP                         ;
12B1: 88              ADC     A,B                 ;
12B2: 88              ADC     A,B                 ;
12B3: 88              ADC     A,B                 ;
12B4: 88              ADC     A,B                 ;
12B5: 88              ADC     A,B                 ;
12B6: 50              LD      D,B                 ;
12B7: 20 00           JR      NZ,$12B9            ; 
12B9: 88              ADC     A,B                 ;
12BA: 88              ADC     A,B                 ;
12BB: 88              ADC     A,B                 ;
12BC: A8              XOR     B                   ;
12BD: A8              XOR     B                   ;
12BE: D8              RET     C                   ;
12BF: 88              ADC     A,B                 ;
12C0: 00              NOP                         ;
12C1: 88              ADC     A,B                 ;
12C2: 88              ADC     A,B                 ;
12C3: 50              LD      D,B                 ;
12C4: 20 50           JR      NZ,$1316            ; 
12C6: 88              ADC     A,B                 ;
12C7: 88              ADC     A,B                 ;
12C8: 00              NOP                         ;
12C9: 88              ADC     A,B                 ;
12CA: 88              ADC     A,B                 ;
12CB: 50              LD      D,B                 ;
12CC: 20 20           JR      NZ,$12EE            ; 
12CE: 20 20           JR      NZ,$12F0            ; 
12D0: 00              NOP                         ;
12D1: F8              RET     M                   ;
12D2: 80              ADD     A,B                 ;
12D3: 40              LD      B,B                 ;
12D4: 20 10           JR      NZ,$12E6            ; 
12D6: 08              EX      AF,AF'              ;
12D7: F8              RET     M                   ;
12D8: 00              NOP                         ;
12D9: 70              LD      (HL),B              ;
12DA: 88              ADC     A,B                 ;
12DB: C8              RET     Z                   ;
12DC: A8              XOR     B                   ;
12DD: 98              SBC     B                   ;
12DE: 88              ADC     A,B                 ;
12DF: 70              LD      (HL),B              ;
12E0: 00              NOP                         ;
12E1: 20 30           JR      NZ,$1313            ; 
12E3: 20 20           JR      NZ,$1305            ; 
12E5: 20 20           JR      NZ,$1307            ; 
12E7: 70              LD      (HL),B              ;
12E8: 00              NOP                         ;
12E9: 70              LD      (HL),B              ;
12EA: 88              ADC     A,B                 ;
12EB: 80              ADD     A,B                 ;
12EC: 60              LD      H,B                 ;
12ED: 10 08           DJNZ    $12F7               ; 
12EF: F8              RET     M                   ;
12F0: 00              NOP                         ;
12F1: F8              RET     M                   ;
12F2: 80              ADD     A,B                 ;
12F3: 40              LD      B,B                 ;
12F4: 60              LD      H,B                 ;
12F5: 80              ADD     A,B                 ;
12F6: 88              ADC     A,B                 ;
12F7: 70              LD      (HL),B              ;
12F8: 00              NOP                         ;
12F9: 40              LD      B,B                 ;
12FA: 60              LD      H,B                 ;
12FB: 50              LD      D,B                 ;
12FC: 48              LD      C,B                 ;
12FD: F8              RET     M                   ;
12FE: 40              LD      B,B                 ;
12FF: 40              LD      B,B                 ;
1300: 00              NOP                         ;
1301: F8              RET     M                   ;
1302: 08              EX      AF,AF'              ;
1303: 78              LD      A,B                 ;
1304: 80              ADD     A,B                 ;
1305: 80              ADD     A,B                 ;
1306: 88              ADC     A,B                 ;
1307: 70              LD      (HL),B              ;
1308: 00              NOP                         ;
1309: E0              RET     PO                  ;
130A: 10 08           DJNZ    $1314               ; 
130C: 78              LD      A,B                 ;
130D: 88              ADC     A,B                 ;
130E: 88              ADC     A,B                 ;
130F: 70              LD      (HL),B              ;
1310: 00              NOP                         ;
1311: F8              RET     M                   ;
1312: 80              ADD     A,B                 ;
1313: 40              LD      B,B                 ;
1314: 20 10           JR      NZ,$1326            ; 
1316: 10 10           DJNZ    $1328               ; 
1318: 00              NOP                         ;
1319: 70              LD      (HL),B              ;
131A: 88              ADC     A,B                 ;
131B: 88              ADC     A,B                 ;
131C: 70              LD      (HL),B              ;
131D: 88              ADC     A,B                 ;
131E: 88              ADC     A,B                 ;
131F: 70              LD      (HL),B              ;
1320: 00              NOP                         ;
1321: 70              LD      (HL),B              ;
1322: 88              ADC     A,B                 ;
1323: 88              ADC     A,B                 ;
1324: F0              RET     P                   ;
1325: 80              ADD     A,B                 ;
1326: 40              LD      B,B                 ;
1327: 38 00           JR      C,$1329             ; 
1329: 20 A8           JR      NZ,$12D3            ; 
132B: 70              LD      (HL),B              ;
132C: 20 70           JR      NZ,$139E            ; 
132E: A8              XOR     B                   ;
132F: 20 00           JR      NZ,$1331            ; 
1331: 10 20           DJNZ    $1353               ; 
1333: 40              LD      B,B                 ;
1334: 80              ADD     A,B                 ;
1335: 40              LD      B,B                 ;
1336: 20 10           JR      NZ,$1348            ; 
1338: 00              NOP                         ;
1339: 00              NOP                         ;
133A: 00              NOP                         ;
133B: 00              NOP                         ;
133C: 00              NOP                         ;
133D: 00              NOP                         ;
133E: 00              NOP                         ;
133F: 20 00           JR      NZ,$1341            ; 
1341: 00              NOP                         ;
1342: 00              NOP                         ;
1343: 00              NOP                         ;
1344: 00              NOP                         ;
1345: 00              NOP                         ;
1346: 00              NOP                         ;
1347: 00              NOP                         ;
1348: 26 0F           LD      H,$0F               ;
134A: 0B              DEC     BC                  ;
134B: 28 01           JR      Z,$134E             ; 
134D: 0C              INC     C                   ;
134E: 0C              INC     C                   ;
134F: 28 12           JR      Z,$1363             ; 
1351: 01 0D 13        LD      BC,$130D            ;
1354: 28 26           JR      Z,$137C             ; 
1356: 03              INC     BC                  ;
1357: 08              EX      AF,AF'              ;
1358: 05              DEC     B                   ;
1359: 03              INC     BC                  ;
135A: 0B              DEC     BC                  ;
135B: 28 09           JR      Z,$1366             ; 
135D: 0E 10           LD      C,$10               ;
135F: 0F              RRCA                        ;
1360: 12              LD      (DE),A              ;
1361: 14              INC     D                   ;
1362: 26 03           LD      H,$03               ;
1364: 08              EX      AF,AF'              ;
1365: 05              DEC     B                   ;
1366: 03              INC     BC                  ;
1367: 0B              DEC     BC                  ;
1368: 28 13           JR      Z,$137D             ; 
136A: 0F              RRCA                        ;
136B: 15              DEC     D                   ;
136C: 0E 04           LD      C,$04               ;
136E: 28 10           JR      Z,$1380             ; 
1370: 0F              RRCA                        ;
1371: 12              LD      (DE),A              ;
1372: 14              INC     D                   ;
1373: 1C              INC     E                   ;
1374: 28 28           JR      Z,$139E             ; 
1376: 1B              DEC     DE                  ;
1377: 1C              INC     E                   ;
1378: 1D              DEC     E                   ;
1379: 1E 1F           LD      E,$1F               ;
137B: 20 21           JR      NZ,$139E            ; 
137D: 22 25 15        LD      ($1525),HL          ; 
1380: 06 0F           LD      B,$0F               ;
1382: 27              DAA                         ;
1383: 06 25           LD      B,$25               ;
1385: 0D              DEC     C                   ;
1386: 09              ADD     HL,BC               ;
1387: 13              INC     DE                  ;
1388: 13              INC     DE                  ;
1389: 0C              INC     C                   ;
138A: 25              DEC     H                   ;
138B: 0C              INC     C                   ;
138C: 01 15 27        LD      BC,$2715            ;
138F: 08              EX      AF,AF'              ;
1390: 25              DEC     H                   ;
1391: 09              ADD     HL,BC               ;
1392: 0E 16           LD      C,$16               ;
1394: 27              DAA                         ;
1395: 08              EX      AF,AF'              ;
1396: 25              DEC     H                   ;
1397: 05              DEC     B                   ;
1398: 18 14           JR      $13AE               ; 
139A: 12              LD      (DE),A              ;
139B: 01 25 09        LD      BC,$0925            ;
139E: 0E 16           LD      C,$16               ;
13A0: 27              DAA                         ;
13A1: 1C              INC     E                   ;
13A2: 25              DEC     H                   ;
13A3: 09              ADD     HL,BC               ;
13A4: 0E 16           LD      C,$16               ;
13A6: 27              DAA                         ;
13A7: 1D              DEC     E                   ;
13A8: 25              DEC     H                   ;
13A9: 09              ADD     HL,BC               ;
13AA: 0E 16           LD      C,$16               ;
13AC: 27              DAA                         ;
13AD: 1E 25           LD      E,$25               ;
13AF: 09              ADD     HL,BC               ;
13B0: 0E 16           LD      C,$16               ;
13B2: 27              DAA                         ;
13B3: 1F              RRA                         ;
13B4: 25              DEC     H                   ;
13B5: 15              DEC     D                   ;
13B6: 06 0F           LD      B,$0F               ;
13B8: 27              DAA                         ;
13B9: 08              EX      AF,AF'              ;
13BA: 25              DEC     H                   ;
13BB: 16 09           LD      D,$09               ;
13BD: 04              INC     B                   ;
13BE: 27              DAA                         ;
13BF: 12              LD      (DE),A              ;
13C0: 20 50           JR      NZ,$1412            ; 
13C2: 88              ADC     A,B                 ;
13C3: 88              ADC     A,B                 ;
13C4: F8              RET     M                   ;
13C5: 88              ADC     A,B                 ;
13C6: 88              ADC     A,B                 ;
13C7: 00              NOP                         ;
13C8: 78              LD      A,B                 ;
13C9: 88              ADC     A,B                 ;
13CA: 88              ADC     A,B                 ;
13CB: 78              LD      A,B                 ;
13CC: 88              ADC     A,B                 ;
13CD: 88              ADC     A,B                 ;
13CE: 78              LD      A,B                 ;
13CF: 00              NOP                         ;
13D0: 70              LD      (HL),B              ;
13D1: 88              ADC     A,B                 ;
13D2: 08              EX      AF,AF'              ;
13D3: 08              EX      AF,AF'              ;
13D4: 08              EX      AF,AF'              ;
13D5: 88              ADC     A,B                 ;
13D6: 70              LD      (HL),B              ;
13D7: 00              NOP                         ;
13D8: 70              LD      (HL),B              ;
13D9: 90              SUB     B                   ;
13DA: 90              SUB     B                   ;
13DB: 90              SUB     B                   ;
13DC: 90              SUB     B                   ;
13DD: 90              SUB     B                   ;
13DE: 70              LD      (HL),B              ;
13DF: 00              NOP                         ;
13E0: E0              RET     PO                  ;
13E1: 20 20           JR      NZ,$1403            ; 
13E3: E0              RET     PO                  ;
13E4: 20 20           JR      NZ,$1406            ; 
13E6: E0              RET     PO                  ;
13E7: 00              NOP                         ;
13E8: 3E 02           LD      A,$02               ;
13EA: 02              LD      (BC),A              ;
13EB: 1E 02           LD      E,$02               ;
13ED: 02              LD      (BC),A              ;
13EE: 02              LD      (BC),A              ;
13EF: 00              NOP                         ;
13F0: 3C              INC     A                   ;
13F1: 02              LD      (BC),A              ;
13F2: 02              LD      (BC),A              ;
13F3: 02              LD      (BC),A              ;
13F4: 32 22 3C     ;LD    ($3C22),A          ;
13F7: 00              NOP                         ;
13F8: 22 22 22        LD      (+22),HL            ; 
13FB: 3E 22           LD      A,$22               ;
13FD: 22 22 00     ;LD    ($0022),HL         ;


;1000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;10A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;10C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;10E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;11A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;11C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;11E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;12A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;12C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;12E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1320: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1340: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;1380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;13A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;13C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
;13E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

DrawShiftedSprite:
; The only differences between this and EraseSimpleSprite is two CPL instructions in the latter and
; the use of AND instead of OR. NOP takes the same amount of time/space as CPL. So the two NOPs
; here make these two parallel routines the same size and speed.
;
1400: 00              NOP                         ; Time/size pad to match CPL in EraseShiftedSprite
1401: CD 74 14        CALL    CnvtPixNumber       ; Convert pixel number to coord and shift
1404: 00              NOP                         ; Time/size pad to match CPL in EraseShiftedSprite
1405: C5              PUSH    BC                  ; Hold count
1406: E5              PUSH    HL                  ; Hold start coordinate
1407: 1A              LD      A,(DE)              ; Get the picture bits
1408: D3 04           OUT     (SHFT_DATA),A       ; Store in shift register
140A: DB 03           IN      A,(SHFT_IN)         ; Read the shifted pixels
140C: B6              OR      (HL)                ; OR them onto the screen
140D: 77              LD      (HL),A              ; Store them back to screen
140E: 23              INC     HL                  ; Next colummn on screen
140F: 13              INC     DE                  ; Next in picture
1410: AF              XOR     A                   ; Shift over ...
1411: D3 04           OUT     (SHFT_DATA),A       ; ... to next byte in register (shift in 0)
1413: DB 03           IN      A,(SHFT_IN)         ; Read the shifted pixels
1415: B6              OR      (HL)                ; OR them onto the screen
1416: 77              LD      (HL),A              ; Store them back to screen
1417: E1              POP     HL                  ; Restore starting coordinate
1418: 01 20 00        LD      BC,$0020            ; Add 32 ...
141B: 09              ADD     HL,BC               ; ... to coordinate (move to next row)
141C: C1              POP     BC                  ; Restore count
141D: 05              DEC     B                   ; All done?
141E: C2 05 14        JP      NZ,$1405            ; No ... go do all rows
1421: C9              RET                         ; Done

1422: 00 00 ; ** Why?

EraseSimpleSprite:
; Clear a sprite from the screen (standard pixel number descriptor).
; ** We clear 2 bytes even though the draw-simple only draws one.
1424: CD 74 14        CALL    CnvtPixNumber       ; Convert pixel number in HL
1427: C5              PUSH    BC                  ; Hold
1428: E5              PUSH    HL                  ; Hold
1429: AF              XOR     A                   ; 0
142A: 77              LD      (HL),A              ; Clear screen byte
142B: 23              INC     HL                  ; Next byte
142C: 77              LD      (HL),A              ; Clear byte
142D: 23              INC     HL                  ; ** Is this to mimic timing? We increment then pop
142E: E1              POP     HL                  ; Restore screen coordinate
142F: 01 20 00        LD      BC,$0020            ; Add 1 row ...
1432: 09              ADD     HL,BC               ; ... to screen coordinate
1433: C1              POP     BC                  ; Restore counter
1434: 05              DEC     B                   ; All rows done?
1435: C2 27 14        JP      NZ,$1427            ; Do all rows
1438: C9              RET                         ; out

DrawSimpSprite:
; Display character to screen
; HL = screen coordinates
; DE = character data
; B = number of rows
1439: C5              PUSH    BC                  ; Preserve counter
143A: 1A              LD      A,(DE)              ; From character set ...
143B: 77              LD      (HL),A              ; ... to screen
143C: 13              INC     DE                  ; Next in character set
143D: 01 20 00        LD      BC,$0020            ; Next row ...
1440: 09              ADD     HL,BC               ; ... on screen
1441: C1              POP     BC                  ; Restore counter
1442: 05              DEC     B                   ; Decrement counter
1443: C2 39 14        JP      NZ,DrawSimpSprite   ; Do all
1446: C9              RET                         ; Out

1447: 00 00 00 00 00 00 00 00 00 00 00 ; ** Why?
                        
EraseShifted:
; Erases a shifted sprite from screen (like for player's explosion)
1452: CD 74 14        CALL    CnvtPixNumber       ; Convert pixel number in HL to coorinates with shift
1455: C5              PUSH    BC                  ; Hold BC
1456: E5              PUSH    HL                  ; Hold coordinate
1457: 1A              LD      A,(DE)              ; Get picture value
1458: D3 04           OUT     (SHFT_DATA),A       ; Value into shift register
145A: DB 03           IN      A,(SHFT_IN)         ; Read shifted sprite picture
145C: 2F              CPL                         ; Reverse it (erasing bits)
145D: A6              AND     (HL)                ; Erase the bits from the screen
145E: 77              LD      (HL),A              ; Store the erased pattern back
145F: 23              INC     HL                  ; Next column on screen
1460: 13              INC     DE                  ; Next in image
1461: AF              XOR     A                   ; Shift register over ...
1462: D3 04           OUT     (SHFT_DATA),A       ; ... 8 bits (shift in 0)
1464: DB 03           IN      A,(SHFT_IN)         ; Read 2nd byte of image
1466: 2F              CPL                         ; Reverse it (erasing bits)
1467: A6              AND     (HL)                ; Erase the bits from the screen
1468: 77              LD      (HL),A              ; Store the erased pattern back
1469: E1              POP     HL                  ; Restore starting coordinate
146A: 01 20 00        LD      BC,$0020            ; Add 32 ...
146D: 09              ADD     HL,BC               ; ... to next row
146E: C1              POP     BC                  ; Restore BC (count)
146F: 05              DEC     B                   ; All rows done?
1470: C2 55 14        JP      NZ,$1455            ; No ... erase all
1473: C9              RET                         ; Done

CnvtPixNumber:
; Convert pixel number in HL to screen coordinate and shift amount.
; HL gets screen coordinate.
; Hardware shift-register gets amount.
1474: 7D              LD      A,L                 ; Get X coordinate
1475: E6 07           AND     $07                 ; Shift by pixel position
1477: D3 02           OUT     (SHFTAMNT),A        ; Write shift amount to hardware
1479: C3 47 1A        JP      ConvToScr           ; HL = HL/8 + 2000 (screen coordinate)

RememberShields:
; In a multi-player game the player's shields are block-copied to and from RAM between turns.
; HL = screen pointer
; DE = memory buffer
; B = number of rows
; C = number of columns
147C: C5              PUSH    BC                  ; Hold counter
147D: E5              PUSH    HL                  ; Hold start
147E: 7E              LD      A,(HL)              ; From sprite ... (should be DE)
147F: 12              LD      (DE),A              ; ... to screen ... (should be HL)
1480: 13              INC     DE                  ; Next in sprite
1481: 23              INC     HL                  ; Next on screen
1482: 0D              DEC     C                   ; All columns done?
1483: C2 7E 14        JP      NZ,$147E            ; No ... do multi columns
1486: E1              POP     HL                  ; Restore screen start
1487: 01 20 00        LD      BC,$0020            ; Add 32 ...
148A: 09              ADD     HL,BC               ; ... to get to next row
148B: C1              POP     BC                  ; Pop the counters
148C: 05              DEC     B                   ; All rows done?
148D: C2 7C 14        JP      NZ,RememberShields  ; No ... do multi rows
1490: C9              RET                         ; Done

DrawSprCollision:
1491: CD 74 14        CALL    CnvtPixNumber       ; Convert pixel number to coord and shift
1494: AF              XOR     A                   ; Clear the ...
1495: 32 61 20        LD      (collision),A       ; ... collision-detection flag
1498: C5              PUSH    BC                  ; Hold count
1499: E5              PUSH    HL                  ; Hold screen
149A: 1A              LD      A,(DE)              ; Get byte
149B: D3 04           OUT     (SHFT_DATA),A       ; Write first byte to shift register
149D: DB 03           IN      A,(SHFT_IN)         ; Read shifted pattern
149F: F5              PUSH    AF                  ; Hold the pattern
14A0: A6              AND     (HL)                ; Any bits from pixel collide with bits on screen?
14A1: CA A9 14        JP      Z,$14A9             ; No ... leave flag alone
14A4: 3E 01           LD      A,$01               ; Yes ... set ...
14A6: 32 61 20        LD      (collision),A       ; ... collision flag
14A9: F1              POP     AF                  ; Restore the pixel pattern
14AA: B6              OR      (HL)                ; OR it onto the screen
14AB: 77              LD      (HL),A              ; Store new screen value
14AC: 23              INC     HL                  ; Next byte on screen
14AD: 13              INC     DE                  ; Next in pixel pattern
14AE: AF              XOR     A                   ; Write zero ...
14AF: D3 04           OUT     (SHFT_DATA),A       ; ... to shift register
14B1: DB 03           IN      A,(SHFT_IN)         ; Read 2nd half of shifted sprite
14B3: F5              PUSH    AF                  ; Hold pattern
14B4: A6              AND     (HL)                ; Any bits from pixel collide with bits on screen?
14B5: CA BD 14        JP      Z,$14BD             ; No ... leave flag alone
14B8: 3E 01           LD      A,$01               ; Yes ... set ...
14BA: 32 61 20        LD      (collision),A       ; ... collision flag
14BD: F1              POP     AF                  ; Restore the pixel pattern
14BE: B6              OR      (HL)                ; OR it onto the screen
14BF: 77              LD      (HL),A              ; Store new screen pattern
14C0: E1              POP     HL                  ; Starting screen coordinate
14C1: 01 20 00        LD      BC,$0020            ; Add 32 ...
14C4: 09              ADD     HL,BC               ; ... to get to next row
14C5: C1              POP     BC                  ; Restore count
14C6: 05              DEC     B                   ; All done?
14C7: C2 98 14        JP      NZ,$1498            ; No ... do all rows
14CA: C9              RET                         ; Done

ClearSmallSprite:
; Clear a one byte sprite at HL. B=number of rows.
14CB: AF              XOR     A                   ; 0
14CC: C5              PUSH    BC                  ; Preserve BC
14CD: 77              LD      (HL),A              ; Clear screen byte
14CE: 01 20 00        LD      BC,$0020            ; Bump HL ...
14D1: 09              ADD     HL,BC               ; ... one screen row
14D2: C1              POP     BC                  ; Restore
14D3: 05              DEC     B                   ; All done?
14D4: C2 CC 14        JP      NZ,$14CC            ; No ... clear all
14D7: C9              RET                         

PlayerShotHit:
; The player's shot hit something (or is being removed from play)
;
14D8: 3A 25 20        LD      A,(plyrShotStatus)  ; Player shot flag
14DB: FE 05           CP      $05                 ; Alien explosion in progress?
14DD: C8              RET     Z                   ; Yes ... ignore this function
14DE: FE 02           CP      $02                 ; Normal movement?
14E0: C0              RET     NZ                  ; No ... out
;
14E1: 3A 29 20        LD      A,(obj1CoorYr)      ; Get Yr coordinate of player shot
14E4: FE D8           CP      $D8                 ; Compare to 216 (40 from Top-rotated)
14E6: 47              LD      B,A                 ; Hold value for later
14E7: D2 30 15        JP      NC,$1530            ; Yr is within 40 from top initiate miss-explosion (shot flag 3)
14EA: 3A 02 20        LD      A,(alienIsExploding); Is an alien ...
14ED: A7              AND     A                   ; ... blowing up?
14EE: C8              RET     Z                   ; No ... out
;
14EF: 78              LD      A,B                 ; Get original Yr coordinate back to A
14F0: FE CE           CP      $CE                 ; Compare to 206 (50 from rotated top)
14F2: D2 79 15        JP      NC,$1579            ; Yr is within 50 from top? Yes ... saucer must be hit
14F5: C6 06           ADD     A,$06               ; Offset to coordinate for wider "explosion" picture
14F7: 47              LD      B,A                 ; Hold that
14F8: 3A 09 20        LD      A,(refAlienYr)      ; Ref alien Y coordianate

; If the lower 4 rows are all empty then the reference alien's Y coordinate will wrap around from 0 to F8.
; At this point the top row of aliens is in the shields and we will assume that everything is within
; the rack.

14FB: FE 90           CP      $90                 ; This is true if ...
14FD: D2 04 15        JP      NC,CodeBug1         ; ... aliens are down in the shields
1500: B8              CP      B                   ; Compare to shot's coordinate
1501: D2 30 15        JP      NC,$1530            ; Outside the rack-square ... do miss explosion

CodeBug1:
;
; We get here if the player's shot hit something within the rack area (a shot or an alien).
; Find the alien that is (or would be) where the shot hit. If there is no alien alive at the row/column
; thn the player hit an alien missile. If there is an alien then explode the alien.
;
; There is a code bug here, but it is extremely subtle. The algorithm for finding the row/column in the
; rack works by adding 16 to the reference coordinates (X for column, Y for row) until it passes or equals
; the target coordinates. This works great as long as the target point is within the alien's rack area.
; If the reference point is far to the right, the column number will be greater than 11, which messes
; up the column/row-to-pointer math.
;
; The entire rack of aliens is based on the lower left alien. Imagine all aliens are dead except the
; upper left. It wiggles down the screen and enters the players shields on the lower left where it begins
; to eat them. Imagine the player is under his own shields on the right side of the screen and fires a
; shot into his own shield.
;
; The alien is in the rack on row 4 (rows are numbered from bottom up starting with 0). The shot hits
; the shields below the alien's Y coordinate and gets correctly assigned to row 3. The alien is in the rack
; at column 0 (columns are numbered from left to right starting with 0). The shot hits the shields far to
; the right of the alien's X coordinate. The algorithm says it is in column 11. But 0-10 are the only
; correct values.
;
; The column/row-to-pointer math works by multiplying the row by 11 and adding the column. For the alien
; that is 11*4 + 0 = 44. For the shot that is 11*3 +11 = 44. The game thinks the shot hit the alien.
;
1504: 68              LD      L,B                 ; L now holds the shot coordinate (adjusted)
1505: CD 62 15        CALL    FindRow             ; Look up row number to B
1508: 3A 2A 20        LD      A,(obj1CoorXr)      ; Player's shot's Xr coordinate ...
150B: 67              LD      H,A                 ; ... to H
150C: CD 6F 15        CALL    FindColumn          ; Get alien's coordinate
150F: 22 64 20        LD      (expAlienYr),HL     ; Put it in the exploding-alien descriptor
1512: 3E 05           LD      A,$05               ; Flag alien explosion ...
1514: 32 25 20        LD      (plyrShotStatus),A  ; ... in progress
1517: CD 81 15        CALL    GetAlienStatPtr     ; Get descriptor for alien
151A: 7E              LD      A,(HL)              ; Is alien ...
151B: A7              AND     A                   ; ... alive
151C: CA 30 15        JP      Z,$1530             ; No ... must have been an alien shot
;
151F: 36 00           LD      (HL),$00            ; Make alien invader dead
1521: CD 5F 0A        CALL    ScoreForAlien       ; Makes alien explosion sound and adjust score
1524: CD 3B 1A        CALL    ReadDesc            ; Load 5 byte sprite descriptor
1527: CD D3 15        CALL    DrawSprite          ; Draw explosion sprite on screen
152A: 3E 10           LD      A,$10               ; Initiate alien-explosion
152C: 32 03 20        LD      (expAlienTimer),A   ; ... timer to 16
152F: C9              RET                         ; Out
;
; Player shot leaving playfield, hitting shield, or hitting an alien shot
1530: 3E 03           LD      A,$03               ; Mark ...
1532: 32 25 20        LD      (plyrShotStatus),A  ; ... player shot hit something other than alien
1535: C3 4A 15        JP      $154A               ; Finish up
;
AExplodeTime:
; Time down the alien explosion. Remove when done.
1538: 21 03 20        LD      HL,$2003            ; Decrement alien explosion ...
153B: 35              DEC     (HL)                ; ... timer
153C: C0              RET     NZ                  ; Not done  ... out
153D: 2A 64 20        LD      HL,(expAlienYr)     ; Pixel pointer for exploding alien
1540: 06 10           LD      B,$10               ; 16 row pixel
1542: CD 24 14        CALL    EraseSimpleSprite   ; Clear the explosion sprite from the screen
1545: 3E 04           LD      A,$04               ; 4 means that ...
1547: 32 25 20        LD      (plyrShotStatus),A  ; ... alien has exploded (remove from active duty)
;
154A: AF              XOR     A                   ; Turn off ...
154B: 32 02 20        LD      (alienIsExploding),A; ... alien-is-blowing-up flag
154E: 06 F7           LD      B,$F7               ; Turn off ...
1550: C3 DC 19        JP      SoundBits3Off       ; ... alien exploding sound

1553: 00                          
    
Cnt16s:
; Count number of 16s needed to bring reference (in A) up to target (in H).
; If the reference starts out beyond the target then we add 16s as long as
; the reference has a signed bit. But these aren't signed quantities. This
; doesn't make any sense. This counting algorithm produces questionable
; results if the reference is beyond the target.
;
1554: 0E 00           LD      C,$00               ; Count of 16s
1556: BC              CP      H                   ; Compare reference coordinate to target
1557: D4 90 15        CALL    NC,WrapRef          ; If reference is greater or equal then do something questionable ... see below
155A: BC              CP      H                   ; Compare reference coordinate to target
155B: D0              RET     NC                  ; If reference is greater or equal then done
155C: C6 10           ADD     A,$10               ; Add 16 to reference
155E: 0C              INC     C                   ; Bump 16s count
155F: C3 5A 15        JP      $155A               ; Keep testing

FindRow:
; L contains a Yr coordinate. Find the row number within the rack that corresponds
; to the Yr coordinate. Return the row coordinate in L and the row number in C.
;
1562: 3A 09 20        LD      A,(refAlienYr)      ; Reference alien Yr coordinate
1565: 65              LD      H,L                 ; Target Yr coordinate to H
1566: CD 54 15        CALL    Cnt16s              ; Count 16s needed to bring ref alien to target
1569: 41              LD      B,C                 ; Count to B
156A: 05              DEC     B                   ; Base 0
156B: DE 10           SBC     A,$10               ; The counting also adds 16 no matter what
156D: 6F              LD      L,A                 ; To coordinate
156E: C9              RET                         ; Done

FindColumn:
; H contains a Xr coordinate. Find the column number within the rack that corresponds
; to the Xr coordinate. Return the column coordinate in H and the column number in C.
;
156F: 3A 0A 20        LD      A,(refAlienXr)      ; Reference alien Yn coordinate
1572: CD 54 15        CALL    Cnt16s              ; Count 16s to bring Y to target Y
1575: DE 10           SBC     A,$10               ; Subtract off extra 16
1577: 67              LD      H,A                 ; To H
1578: C9              RET                         ; Done

1579: 3E 01           LD      A,$01               ; Mark flying ...
157B: 32 85 20        LD      (saucerHit),A       ; ... saucer has been hit
157E: C3 45 15        JP      $1545               ; Remove player shot

GetAlienStatPtr:
; B is row number. C is column number (starts at 1).
; Return pointer to alien-status flag for current player.
1581: 78              LD      A,B                 ; Hold original
1582: 07              RLCA                        ; *2
1583: 07              RLCA                        ; *4
1584: 07              RLCA                        ; *8
1585: 80              ADD     A,B                 ; *9
1586: 80              ADD     A,B                 ; *10
1587: 80              ADD     A,B                 ; *11
1588: 81              ADD     A,C                 ; Add row offset to column offset
1589: 3D              DEC     A                   ; -1
158A: 6F              LD      L,A                 ; Set LSB of HL
158B: 3A 67 20        LD      A,(playerDataMSB)   ; Set ...
158E: 67              LD      H,A                 ; ... MSB of HL with active player indicator
158F: C9              RET                         

WrapRef:
; This is called if the reference point is greater than the target point. I believe the goal is to
; wrap the reference back around until it is lower than the target point. But the algorithm simply adds
; until the sign bit of the the reference is 0. If the target is 2 and the reference is 238 then this
; algorithm moves the reference 238+16=244 then 244+16=4. Then the algorithm stops. But the reference is
; STILL greater than the target.
;
; Also imagine that the target is 20 and the reference is 40. The algorithm adds 40+16=56, which is not
; negative, so it stops there.
;
; I think the intended code is "JP NC" instead of "JP M", but even that doesn't make sense.
;
1590: 0C              INC     C                   ; Increase 16s count
1591: C6 10           ADD     A,$10               ; Add 16 to ref
1593: FA 90 15        JP      M,WrapRef           ; Keep going till result is positive
1596: C9              RET                         ; Out

RackBump:
; When rack bumps the edge of the screen then the direction flips and the rack
; drops 8 pixels. The deltaX and deltaY values are changed here. Interestingly
; if there is only one alien left then the right value is 3 instead of the
; usual 2. The left direction is always -2.
1597: 3A 0D 20        LD      A,(rackDirection)   ; Get rack direction
159A: A7              AND     A                   ; Moving right?
159B: C2 B7 15        JP      NZ,$15B7            ; No ... handle moving left
;
159E: 21 A4 3E        LD      HL,$3EA4            ; Line down the right edge of playfield
15A1: CD C5 15        CALL    $15C5               ; Check line down the edge
15A4: D0              RET     NC                  ; Nothing is there ... return
15A5: 06 FE           LD      B,$FE               ; Delta X of -2
15A7: 3E 01           LD      A,$01               ; Rack now moving right
;
15A9: 32 0D 20        LD      (rackDirection),A   ; Set new rack direction
15AC: 78              LD      A,B                 ; B has delta X
15AD: 32 08 20        LD      (refAlienDXr),A     ; Set new delta X
15B0: 3A 0E 20        LD      A,(rackDownDelta)   ; Set delta Y ...
15B3: 32 07 20        LD      (refAlienDYr),A     ; ... to drop rack by 8
15B6: C9              RET                         ; Done
;
15B7: 21 24 25        LD      HL,$2524            ; Line down the left edge of playfield
15BA: CD C5 15        CALL    $15C5               ; Check line down the edge
15BD: D0              RET     NC                  ; Nothing is there ... return
15BE: CD F1 18        CALL    $18F1               ; Get moving-right delta X value of 2 (3 if just one alien left)
15C1: AF              XOR     A                   ; Rack now moving left
15C2: C3 A9 15        JP      $15A9               ; Set rack direction
;
15C5: 06 17           LD      B,$17               ; Checking 23 bytes in a line up the screen from near the bottom
15C7: 7E              LD      A,(HL)              ; Get screen memory
15C8: A7              AND     A                   ; Is screen memory empty?
15C9: C2 6B 16        JP      NZ,$166B            ; No ... set carry flag and out
15CC: 23              INC     HL                  ; Next byte on screen
15CD: 05              DEC     B                   ; All column done?
15CE: C2 C7 15        JP      NZ,$15C7            ; No ... keep looking
15D1: C9              RET                         ; Return with carry flag clear

15D2: 00              NOP                         ; ** Why? Something optimized?
    
DrawSprite:
; Draw sprite at [DE] to screen at pixel position in HL
; The hardware shift register is used in converting pixel positions
; to screen coordinates.
15D3: CD 74 14        CALL    CnvtPixNumber       ; Convert pixel number to screen/shift
15D6: E5              PUSH    HL                  ; Preserve screen coordinate
15D7: C5              PUSH    BC                  ; Hold for a second
15D8: E5              PUSH    HL                  ; Hold for a second
15D9: 1A              LD      A,(DE)              ; From sprite data
15DA: D3 04           OUT     (SHFT_DATA),A       ; Write data to shift register
15DC: DB 03           IN      A,(SHFT_IN)         ; Read back shifted amount
15DE: 77              LD      (HL),A              ; Shifted sprite to screen
15DF: 23              INC     HL                  ; Adjacent cell
15E0: 13              INC     DE                  ; Next in sprite data
15E1: AF              XOR     A                   ; 0
15E2: D3 04           OUT     (SHFT_DATA),A       ; Write 0 to shift register
15E4: DB 03           IN      A,(SHFT_IN)         ; Read back remainder of previous
15E6: 77              LD      (HL),A              ; Write remainder to adjacent
15E7: E1              POP     HL                  ; Old screen coordinate
15E8: 01 20 00        LD      BC,$0020            ; Offset screen ...
15EB: 09              ADD     HL,BC               ; ... to next row
15EC: C1              POP     BC                  ; Restore count
15ED: 05              DEC     B                   ; All done?
15EE: C2 D7 15        JP      NZ,$15D7            ; No ... do all
15F1: E1              POP     HL                  ; Restore HL
15F2: C9              RET                         ; Done

CountAliens:
; Count number of aliens remaining in active game and return count 2082 holds the current count.
; If only 1, 206B gets a flag of 1 ** but ever nobody checks this
15F3: CD 11 16        CALL    GetPlayerDataPtr    ; Get active player descriptor
15F6: 01 00 37        LD      BC,$3700            ; B=55 aliens to check?
15F9: 7E              LD      A,(HL)              ; Get byte
15FA: A7              AND     A                   ; Is it a zero?
15FB: CA FF 15        JP      Z,$15FF             ; Yes ... don't count it
15FE: 0C              INC     C                   ; Count the live aliens
15FF: 23              INC     HL                  ; Next alien
1600: 05              DEC     B                   ; Count ...
1601: C2 F9 15        JP      NZ,$15F9            ; ... all alien indicators
1604: 79              LD      A,C                 ; Get the count
1605: 32 82 20        LD      (numAliens),A       ; Hold it
1608: FE 01           CP      $01                 ; Just one?
160A: C0              RET     NZ                  ; No keep going
160B: 21 6B 20        LD      HL,$206B            ; Set flag if ...
160E: 36 01           LD      (HL),$01            ; ... only one alien left
1610: C9              RET                         ; Out

GetPlayerDataPtr:
; Set HL with 2100 if player 1 is active or 2200 if player 2 is active
;
1611: 2E 00           LD      L,$00               ; Byte boundary
1613: 3A 67 20        LD      A,(playerDataMSB)   ; Active player number
1616: 67              LD      H,A                 ; Set HL to data
1617: C9              RET                         ; Done

PlrFireOrDemo:
; Initiate player fire if button is pressed.
; Demo commands are parsed here if in demo mode
1618: 3A 15 20        LD      A,(playerAlive)     ; Is there an active player?
161B: FE FF           CP      $FF                 ; FF = alive
161D: C0              RET     NZ                  ; Player has been shot - no firing
161E: 21 10 20        LD      HL,$2010            ; Get player ...
1621: 7E              LD      A,(HL)              ; ... task ...
1622: 23              INC     HL                  ; ... timer ...
1623: 46              LD      B,(HL)              ; ... value
1624: B0              OR      B                   ; Is the timer 0 (object active)?
1625: C0              RET     NZ                  ; No ... no firing till player object starts
1626: 3A 25 20        LD      A,(plyrShotStatus)  ; Does the player have ...
1629: A7              AND     A                   ; ... a shot on the screen?
162A: C0              RET     NZ                  ; Yes ... ignore
162B: 3A EF 20        LD      A,(gameMode)        ; Are we in ...
162E: A7              AND     A                   ; ... game mode?
162F: CA 52 16        JP      Z,$1652             ; No ... in demo mode ... constant firing in demo
1632: 3A 2D 20        LD      A,(fireBounce)      ; Is fire button ...
1635: A7              AND     A                   ; ... being held down?
1636: C2 48 16        JP      NZ,$1648            ; Yes ... wait for bounce
1639: CD C0 17        CALL    ReadInputs          ; Read active player controls
163C: E6 10           AND     $10                 ; Fire-button pressed?
163E: C8              RET     Z                   ; No ... out
163F: 3E 01           LD      A,$01               ; Flag
1641: 32 25 20        LD      (plyrShotStatus),A  ; Flag shot active
1644: 32 2D 20        LD      (fireBounce),A      ; Flag that fire button is down
1647: C9              RET                         ; Out
1648: CD C0 17        CALL    ReadInputs          ; Read active player controls
164B: E6 10           AND     $10                 ; Fire-button pressed?
164D: C0              RET     NZ                  ; Yes ... ignore
164E: 32 2D 20        LD      (fireBounce),A      ; Else ... clear flag
1651: C9              RET                         ; Out
; Handle demo (constant fire, parse demo commands)
1652: 21 25 20        LD      HL,$2025            ; Demo fires ...
1655: 36 01           LD      (HL),$01            ; ... constantly
1657: 2A ED 20        LD      HL,(demoCmdPtrLSB)  ; Demo command bufer
165A: 23              INC     HL                  ; Next position
165B: 7D              LD      A,L                 ; Command buffer ...
165C: FE 7E           CP      $7E                 ; ... wraps around
165E: DA 63 16        JP      C,$1663             ; ... Buffer from 1F74 to 1F7E
1661: 2E 74           LD      L,$74               ; ... overflow
1663: 22 ED 20        LD      (demoCmdPtrLSB),HL  ; Next demo command
1666: 7E              LD      A,(HL)              ; Get next command
1667: 32 1D 20        LD      (nextDemoCmd),A     ; Set command for movement
166A: C9              RET                         ; Done

166B: 37              SCF                         ; Set carry flag
166C: C9              RET                         ; Done

166D: AF              XOR     A                   ; 0
166E: CD 8B 1A        CALL    $1A8B               ; Print ZERO ships remain
1671: CD 10 19        CALL    CurPlyAlive         ; Get active-flag ptr for current player
1674: 36 00           LD      (HL),$00            ; Flag player is dead
1676: CD CA 09        CALL    $09CA               ; Get score descriptor for current player
1679: 23              INC     HL                  ; Point to high two digits
167A: 11 F5 20        LD      DE,$20F5            ; Current high score upper two digits
167D: 1A              LD      A,(DE)              ; Is player score greater ...
167E: BE              CP      (HL)                ; ... than high score?
167F: 1B              DEC     DE                  ; Point to LSB
1680: 2B              DEC     HL                  ; Point to LSB
1681: 1A              LD      A,(DE)              ; Go ahead and fetch high score lower two digits
1682: CA 8B 16        JP      Z,$168B             ; Upper two are the same ... have to check lower two
1685: D2 98 16        JP      NC,$1698            ; Player score is lower than high ... nothing to do
1688: C3 8F 16        JP      $168F               ; Player socre is higher ... go copy the new high score
;
168B: BE              CP      (HL)                ; Is lower digit higher? (upper was the same)
168C: D2 98 16        JP      NC,$1698            ; No ... high score is still greater than player's score
168F: 7E              LD      A,(HL)              ; Copy the new ...
1690: 12              LD      (DE),A              ; ... high score lower two digits
1691: 13              INC     DE                  ; Point to MSB
1692: 23              INC     HL                  ; Point to MSB
1693: 7E              LD      A,(HL)              ; Copy the new ...
1694: 12              LD      (DE),A              ; ... high score upper two digits
1695: CD 50 19        CALL    PrintHiScore        ; Draw the new high score
1698: 3A CE 20        LD      A,(twoPlayers)      ; Number of players
169B: A7              AND     A                   ; Is this a single player game?
169C: CA C9 16        JP      Z,$16C9             ; Yes ... short message
169F: 21 03 28        LD      HL,$2803            ; Screen coordinates
16A2: 11 A6 1A        LD      DE,$1AA6            ; "GAME OVER PLAYER< >"
16A5: 0E 14           LD      C,$14               ; 20 characters
16A7: CD 93 0A        CALL    PrintMessageDel     ; Print message
16AA: 25              DEC     H                   ; Back up ...
16AB: 25              DEC     H                   ; ... to player indicator
16AC: 06 1B           LD      B,$1B               ; "1"
16AE: 3A 67 20        LD      A,(playerDataMSB)   ; Player number
16B1: 0F              RRCA                        ; Is this player 1?
16B2: DA B7 16        JP      C,$16B7             ; Yes ... keep the digit
16B5: 06 1C           LD      B,$1C               ; Else ... set digit 2
16B7: 78              LD      A,B                 ; To A
16B8: CD FF 08        CALL    DrawChar            ; Print player number
16BB: CD B1 0A        CALL    OneSecDelay         ; Short delay
16BE: CD E7 18        CALL    $18E7               ; Get current player "alive" flag
16C1: 7E              LD      A,(HL)              ; Is player ...
16C2: A7              AND     A                   ; ... alive?
16C3: CA C9 16        JP      Z,$16C9             ; No ... skip to "GAME OVER" sequence
16C6: C3 ED 02        JP      $02ED               ; Switch players and game loop
;
16C9: 21 18 2D        LD      HL,$2D18            ; Screen coordinates
16CC: 11 A6 1A        LD      DE,$1AA6            ; "GAME OVER PLAYER< >"
16CF: 0E 0A           LD      C,$0A               ; Just the "GAME OVER" part
16D1: CD 93 0A        CALL    PrintMessageDel     ; Print message
16D4: CD B6 0A        CALL    TwoSecDelay         ; Long delay
16D7: CD D6 09        CALL    ClearPlayField      ; Clear center window
16DA: AF              XOR     A                   ; Now in ...
16DB: 32 EF 20        LD      (gameMode),A        ; ... demo mode
16DE: D3 05           OUT     (SOUND2),A          ; All sound off
16E0: CD D1 19        CALL    EnableGameTasks     ; Enable ISR game tasks
16E3: C3 89 0B        JP      $0B89               ; Print credit information and do splash

16E6: 31 00 24        LD      SP,$2400            ; Reset stack
16E9: FB              EI                          ; Enable interrupts
16EA: AF              XOR     A                   ; Flag ...
16EB: 32 15 20        LD      (playerAlive),A     ; ... player is shot
16EE: CD D8 14        CALL    PlayerShotHit       ; Player's shot collision detection
16F1: 06 04           LD      B,$04               ; Player has been hit ...
16F3: CD FA 18        CALL    SoundBits3On        ; ... sound
16F6: CD 59 0A        CALL    $0A59               ; Has flag been set?
16F9: C2 EE 16        JP      NZ,$16EE            ; No ... wait for the flag
16FC: CD D7 19        CALL    DsableGameTasks     ; Disable ISR game tasks
16FF: 21 01 27        LD      HL,$2701            ; Player's stash of ships
1702: CD FA 19        CALL    $19FA               ; Erase the stash of shps
1705: AF              XOR     A                   ; Print ...
1706: CD 8B 1A        CALL    $1A8B               ; ... a zero (number of ships)

1709: 06 FB           LD      B,$FB               ; Turn off ...
170B: C3 6B 19        JP      $196B               ; ... player shot sound

AShotReloadRate:
; Use the player's MSB to determine how fast the aliens reload their
; shots for another fire.
170E: CD CA 09        CALL    $09CA               ; Get score descriptor for active player
1711: 23              INC     HL                  ; MSB value
1712: 7E              LD      A,(HL)              ; Get the MSB value
1713: 11 B8 1C        LD      DE,$1CB8            ; Score MSB table
1716: 21 A1 1A        LD      HL,$1AA1            ; Corresponding fire reload rate table
1719: 0E 04           LD      C,$04               ; Only 4 entries (a 5th value of 7 is used after that)
171B: 47              LD      B,A                 ; Hold the score value
171C: 1A              LD      A,(DE)              ; Get lookup from table
171D: B8              CP      B                   ; Compare them
171E: D2 27 17        JP      NC,$1727            ; Equal or below ... use this table entry
1721: 23              INC     HL                  ; Next ...
1722: 13              INC     DE                  ; ... entry in table
1723: 0D              DEC     C                   ; Do all ...
1724: C2 1C 17        JP      NZ,$171C            ; ... 4 entries in the tables
1727: 7E              LD      A,(HL)              ; Load the shot reload value
1728: 32 CF 20        LD      (aShotReloadRate),A ; Save the value for use in shot routine
172B: C9              RET                         ; Done

; Shot sound on or off depending on 2025
ShotSound:
172C: 3A 25 20        LD      A,(plyrShotStatus)  ; Player shot flag
172F: FE 00           CP      $00                 ; Active shot?
1731: C2 39 17        JP      NZ,$1739            ; Yes ... go
1734: 06 FD           LD      B,$FD               ; Sound mask
1736: C3 DC 19        JP      SoundBits3Off       ; Mask off sound
;
1739: 06 02           LD      B,$02               ; Sound bit
173B: C3 FA 18        JP      SoundBits3On        ; OR on sound

173E: 00 00 ; ** Why?

TimeFleetSound:
; This called from the ISR times down the fleet and sets the flag at 2095 if
; the fleet needs a change in sound handling (new delay, new sound)
1740: 21 9B 20        LD      HL,$209B            ; Pointer to hold time for fleet
1743: 35              DEC     (HL)                ; Decrement hold time
1744: CC 6D 17        CALL    Z,$176D             ; If 0 turn fleet movement sound off
1747: 3A 68 20        LD      A,(playerOK)        ; Is player OK?
174A: A7              AND     A                   ; 1  means OK
174B: CA 6D 17        JP      Z,$176D             ; Player not OK ... fleet movement sound off and out
174E: 21 96 20        LD      HL,$2096            ; Current time on fleet sound
1751: 35              DEC     (HL)                ; Count down
1752: C0              RET     NZ                  ; Not time to change sound ... out
1753: 21 98 20        LD      HL,$2098            ; Current sound port 3 value
1756: 7E              LD      A,(HL)              ; Get value
1757: D3 05           OUT     (SOUND2),A          ; Set sounds
1759: 3A 82 20        LD      A,(numAliens)       ; Number of aliens on active screen
175C: A7              AND     A                   ; Is it zero?
175D: CA 6D 17        JP      Z,$176D             ; Yes ... turn off fleet movement sound and out
1760: 2B              DEC     HL                  ; (2097) Point to fleet timer reload
1761: 7E              LD      A,(HL)              ; Get fleet delay value
1762: 2B              DEC     HL                  ; (2096) Point to fleet timer
1763: 77              LD      (HL),A              ; Reload the timer
1764: 2B              DEC     HL                  ; Point to change-sound
1765: 36 01           LD      (HL),$01            ; (2095) time to change sound
1767: 3E 04           LD      A,$04               ; Set hold ...
1769: 32 9B 20        LD      (fleetSndHold),A    ; ... time for fleet sound
176C: C9              RET                         ; Done

176D: 3A 98 20        LD      A,(soundPort5)      ; Current sound port 3 value
1770: E6 30           AND     $30                 ; Mask off fleet movement sounds
1772: D3 05           OUT     (SOUND2),A          ; Set sounds
1774: C9              RET                         ; Out

FleetDelayExShip:
; This game-loop routine handles two sound functions. The routine does:
; 1) Time out the extra-ship awarded sound and turn it off when done
; 2) Load the fleet sound delay based on number of remaining aliens
; 3) Make the changing fleet sound
;
; The 2095 flag is set by the ISR and cleared here. The ISR does the timing and sets 2095 when it
; is time to make a new fleet sound.
;
1775: 3A 95 20        LD      A,(changeFleetSnd)  ; Time for new ...
1778: A7              AND     A                   ; ... fleet movement sound?
1779: CA AA 17        JP      Z,$17AA             ; No ... skip to extra-man timing
177C: 21 11 1A        LD      HL,$1A11            ; Number of aliens list coupled ...
177F: 11 21 1A        LD      DE,$1A21            ; ... with delay list
1782: 3A 82 20        LD      A,(numAliens)       ; Get the number of aliens on the screen
1785: BE              CP      (HL)                ; Compare it to the first list value
1786: D2 8E 17        JP      NC,$178E            ; Number of live aliens is higher than value ... use the delay
1789: 23              INC     HL                  ; Move to ...
178A: 13              INC     DE                  ; ... next list value
178B: C3 85 17        JP      $1785               ; Find the right delay
178E: 1A              LD      A,(DE)              ; Get the delay from the second list
178F: 32 97 20        LD      (fleetSndReload),A  ; Store the new alien sound delay
1792: 21 98 20        LD      HL,$2098            ; Get current state ...
1795: 7E              LD      A,(HL)              ; ... of sound port
1796: E6 30           AND     $30                 ; Mask off all fleet movement sounds
1798: 47              LD      B,A                 ; Hold the value
1799: 7E              LD      A,(HL)              ; Get current state
179A: E6 0F           AND     $0F                 ; This time ONLY the fleet movement sounds
179C: 07              RLCA                        ; Shift next to next sound
179D: FE 10           CP      $10                 ; Overflow?
179F: C2 A4 17        JP      NZ,$17A4            ; No ... keep it
17A2: 3E 01           LD      A,$01               ; Reset back to first sound
17A4: B0              OR      B                   ; Add fleet sounds to current sound value
17A5: 77              LD      (HL),A              ; Store new sound value
17A6: AF              XOR     A                   ; Restart ...
17A7: 32 95 20        LD      (changeFleetSnd),A  ; ... waiting on fleet time
;
17AA: 21 99 20        LD      HL,$2099            ; Sound timer for award extra ship
17AD: 35              DEC     (HL)                ; Time expired?
17AE: C0              RET     NZ                  ; No ... leave sound playing
17AF: 06 EF           LD      B,$EF               ; Turn off bit set with #$10 (award extra ship)
17B1: C3 DC 19        JP      SoundBits3Off       ; Stop sound and out

SndOffExtPly:
17B4: 06 EF           LD      B,$EF               ; Mask off sound bit 4 (Extended play)
17B6: 21 98 20        LD      HL,$2098            ; Current sound content
17B9: 7E              LD      A,(HL)              ; Get current sound bits
17BA: A0              AND     B                   ; Turn off extended play
17BB: 77              LD      (HL),A              ; Remember settings
17BC: D3 05           OUT     (SOUND2),A          ; Turn off extended play
17BE: C9              RET                         ; Out

17BF: 00 ; ** Why?

ReadInputs:
; Read control inputs for active player
17C0: 3A 67 20        LD      A,(playerDataMSB)   ; Get active player
17C3: 0F              RRCA                        ; Test player
17C4: D2 CA 17        JP      NC,$17CA            ; Player 2 ... read port 2
17C7: DB 01           IN      A,(INP1)            ; Player 1 ... read port 1
17C9: C9              RET                         ; Out
17CA: DB 02           IN      A,(INP2)            ; Get controls for player 2
17CC: C9              RET                         ; Out

; Check and handle TILT
CheckHandleTilt:
17CD: DB 02           IN      A,(INP2)            ; Read input port
17CF: E6 04           AND     $04                 ; Tilt?
17D1: C8              RET     Z                   ; No tilt ... return
17D2: 3A 9A 20        LD      A,(tilt)            ; Already in TILT handle?
17D5: A7              AND     A                   ; 1 = yes
17D6: C0              RET     NZ                  ; Yes ... ignore it now
17D7: 31 00 24        LD      SP,$2400            ; Reset stack
17DA: 06 04           LD      B,$04               ; Do this 4 times
17DC: CD D6 09        CALL    ClearPlayField      ; Clear center window
17DF: 05              DEC     B                   ; All done?
17E0: C2 DC 17        JP      NZ,$17DC            ; No ... do again
17E3: 3E 01           LD      A,$01               ; Flag ...
17E5: 32 9A 20        LD      (tilt),A            ; ... handling TILT
17E8: CD D7 19        CALL    DsableGameTasks     ; Disable game tasks
17EB: FB              EI                          ; Re-enable interrupts
17EC: 11 BC 1C        LD      DE,$1CBC            ; Message "TILT"
17EF: 21 16 30        LD      HL,$3016            ; Center of screen
17F2: 0E 04           LD      C,$04               ; Four letters
17F4: CD 93 0A        CALL    PrintMessageDel     ; Print "TILT"
17F7: CD B1 0A        CALL    OneSecDelay         ; Short delay
17FA: AF              XOR     A                   ; Zero
17FB: 32 9A 20        LD      (tilt),A            ; TILT handle over
17FE: 32 93 20        LD      (waitStartLoop),A   ; Back into splash screens
1801: C3 C9 16        JP      $16C9               ; Handle game over for player

CtrlSaucerSound:
1804: 21 84 20        LD      HL,$2084            ; Saucer on screen flag
1807: 7E              LD      A,(HL)              ; Is the saucer ...
1808: A7              AND     A                   ; ... on the screen?
1809: CA 07 07        JP      Z,$0707             ; No ... UFO sound off
180C: 23              INC     HL                  ; Saucer hit flag
180D: 7E              LD      A,(HL)              ; (2085) Get saucer hit flag
180E: A7              AND     A                   ; Is saucer in "hit" sequence?
180F: C0              RET     NZ                  ; Yes ... out
1810: 06 01           LD      B,$01               ; Retrigger saucer ...
1812: C3 FA 18        JP      SoundBits3On        ; ... sound (retrigger makes it warble?)
  
DrawAdvTable:
; Draw "SCORE ADVANCE TABLE"
1815: 21 10 28        LD      HL,$2810            ; 0x410 is 1040 rotCol=32, rotRow=16
1818: 11 A3 1C        LD      DE,$1CA3            ; "*SCORE ADVANCE TABLE*"
181B: 0E 15           LD      C,$15               ; 21 bytes in message
181D: CD F3 08        CALL    PrintMessage        ; Print message
1820: 3E 0A           LD      A,$0A               ; 10 bytes in every "=xx POINTS" string
1822: 32 6C 20        LD      (temp206C),A        ; Hold the count
1825: 01 BE 1D        LD      BC,$1DBE            ; Coordinate/sprite for drawing table
1828: CD 56 18        CALL    ReadPriStruct       ; Get HL=coordinate, DE=image
182B: DA 37 18        JP      C,$1837             ; Move on if done
182E: CD 44 18        CALL    $1844               ; Draw 16-byte sprite
1831: C3 28 18        JP      $1828               ; Do all in table
;
1834: CD B1 0A        CALL    OneSecDelay         ; One second delay
1837: 01 CF 1D        LD      BC,$1DCF            ; Coordinate/message for drawing table
183A: CD 56 18        CALL    ReadPriStruct       ; Get HL=coordinate, DE=message
183D: D8              RET     C                   ; Out if done
183E: CD 4C 18        CALL    $184C               ; Print message
1841: C3 3A 18        JP      $183A               ; Do all in table
;
1844: C5              PUSH    BC                  ; Hold BC
1845: 06 10           LD      B,$10               ; 16 bytes
1847: CD 39 14        CALL    DrawSimpSprite      ; Draw simple
184A: C1              POP     BC                  ; Restore BC
184B: C9              RET                         ; Out
;
184C: C5              PUSH    BC                  ; Hold BC
184D: 3A 6C 20        LD      A,(temp206C)        ; Count of 10 ...
1850: 4F              LD      C,A                 ; ... to C
1851: CD 93 0A        CALL    PrintMessageDel     ; Print the message with delay between letters
1854: C1              POP     BC                  ; Restore BC
1855: C9              RET                         ; Out

ReadPriStruct:
; Read a 4-byte print-structure pointed to by BC
; HL=Screen coordiante, DE=pointer to message
; If the first byte is FF then return with Carry Set, Carry Cleared otherwise.
1856: 0A              LD      A,(BC)              ; Get the screen LSB
1857: FE FF           CP      $FF                 ; Valid?
1859: 37              SCF                         ; If not Carry will be Set
185A: C8              RET     Z                   ; Return if 255
185B: 6F              LD      L,A                 ; Screen LSB to L
185C: 03              INC     BC                  ; Next
185D: 0A              LD      A,(BC)              ; Read screen MSB
185E: 67              LD      H,A                 ; Screen MSB to H
185F: 03              INC     BC                  ; Next
1860: 0A              LD      A,(BC)              ; Read message LSB
1861: 5F              LD      E,A                 ; Message LSB to E
1862: 03              INC     BC                  ; Next
1863: 0A              LD      A,(BC)              ; Read message MSB
1864: 57              LD      D,A                 ; Message MSB to D
1865: 03              INC     BC                  ; Next (for next print)
1866: A7              AND     A                   ; Clear Carry
1867: C9              RET                         ; Done

SplashSprite:
; Moves a sprite up or down in splash mode. Interrupt moves the sprite. When it reaches
; Y value in 20CA the flag at 20CB is raised. The image flips between two pictures every
; 4 movements.

1868: 21 C2 20        LD      HL,$20C2            ; Descriptor
186B: 34              INC     (HL)                ; Change image
186C: 23              INC     HL                  ; Point to delta-x
186D: 4E              LD      C,(HL)              ; Get delta-x
186E: CD D9 01        CALL    AddDelta            ; Add delta-X and delta-Y to X and Y
1871: 47              LD      B,A                 ; Current y coordinate
1872: 3A CA 20        LD      A,(splashTargetY)   ; Has sprite reached ...
1875: B8              CP      B                   ; ... target coordinate?
1876: CA 98 18        JP      Z,$1898             ; Yes ... flag and out
1879: 3A C2 20        LD      A,(splashAnForm)    ; Image number
187C: E6 04           AND     $04                 ; Watching bit 3 for flip delay
187E: 2A CC 20        LD      HL,(splashImRestLSB); Image
1881: C2 88 18        JP      NZ,$1888            ; Did bit 3 go to 0? No ... keep current image
1884: 11 30 00        LD      DE,$0030            ; 16*3 ...
1887: 19              ADD     HL,DE               ; ...  use other image form
1888: 22 C7 20        LD      (splashImageLSB),HL ; Image to descriptor structure
188B: 21 C5 20        LD      HL,$20C5            ; X,Y,Image descriptor
188E: CD 3B 1A        CALL    ReadDesc            ; Read sprite descriptor
1891: EB              EX      DE,HL               ; Image to DE, position to HL
1892: C3 D3 15        JP      DrawSprite          ; Draw the sprite

1895: 00 00 00                          

1898: 3E 01           LD      A,$01               ; Flag that sprite ...
189A: 32 CB 20        LD      (splashReached),A   ; ... reached location
189D: C9              RET                         ; Out

;Animate alien shot to extra "C" in splash
189E: 21 50 20        LD      HL,$2050            ; Task descriptor for game object 4 (squiggly shot)
18A1: 11 C0 1B        LD      DE,$1BC0            ; Task info for animate-shot-to-extra-C
18A4: 06 10           LD      B,$10               ; Block copy ...
18A6: CD 32 1A        CALL    BlockCopy           ; ... 16 bytes
18A9: 3E 02           LD      A,$02               ; Set shot sync ...
18AB: 32 80 20        LD      (shotSync),A        ; ... to run the squiggly shot
18AE: 3E FF           LD      A,$FF               ; Shot direction (-1)
18B0: 32 7E 20        LD      (alienShotDelta),A  ; Alien shot delta
18B3: 3E 04           LD      A,$04               ; Animate ...
18B5: 32 C1 20        LD      (isrSplashTask),A   ; ... shot
18B8: 3A 55 20        LD      A,(squShotStatus)   ; Has shot ...
18BB: E6 01           AND     $01                 ; ... collided?
18BD: CA B8 18        JP      Z,$18B8             ; No ... keep waiting
18C0: 3A 55 20        LD      A,(squShotStatus)   ; Wait ...
18C3: E6 01           AND     $01                 ; ... for explosion ...
18C5: C2 C0 18        JP      NZ,$18C0            ; ... to finish
18C8: 21 11 33        LD      HL,$3311            ; Here is where the extra C is
18CB: 3E 26           LD      A,$26               ; Space character
18CD: 00              NOP                         ; ** Why?
18CE: CD FF 08        CALL    DrawChar            ; Draw character
18D1: C3 B6 0A        JP      TwoSecDelay         ; Two second delay and out

; Initializiation comes here
;
init:
18D4: 31 00 24        LD      SP,$2400            ; Set stack pointer just below screen
18D7: 06 00           LD      B,$00               ; Count 256 bytes
18D9: CD E6 01        CALL    $01E6               ; Copy ROM to RAM
18DC: CD 56 19        CALL    DrawStatus          ; Print scores and credits
;
18DF: 3E 08           LD      A,$08               ; Set alien ...
18E1: 32 CF 20        LD      (aShotReloadRate),A ; ... shot reload rate
18E4: C3 EA 0A        JP      $0AEA               ; Top of splash screen loop

; Get player-alive flag for OTHER player
18E7: 3A 67 20        LD      A,(playerDataMSB)   ; Player data MSB
18EA: 21 E7 20        LD      HL,$20E7            ; Alive flags (player 1 and 2)
18ED: 0F              RRCA                        ; Bit 1=1 for player 1
18EE: D0              RET     NC                  ; Player 2 ... we have it ... out
18EF: 23              INC     HL                  ; Player 1's flag
18F0: C9              RET                         ; Done

; If there is one alien left then the right motion is 3 instead of 2. That's
; why the timing is hard to hit after the change.
18F1: 06 02           LD      B,$02               ; Rack moving right delta X
18F3: 3A 82 20        LD      A,(numAliens)       ; Number of aliens on screen
18F6: 3D              DEC     A                   ; Just one left?
18F7: C0              RET     NZ                  ; No ... use right delta X of 2
18F8: 04              INC     B                   ; Just one alien ... move right at 3 instead of 2
18F9: C9              RET                         ; Done

SoundBits3On:
; Add in bit for sound
18FA: 3A 94 20        LD      A,(soundPort3)      ; Current value of sound port
18FD: B0              OR      B                   ; Add in new sounds
18FE: 32 94 20        LD      (soundPort3),A      ; New value of sound port
1901: D3 03           OUT     (SOUND1),A          ; Write new value to sound hardware
1903: C9              RET                         

InitAliensP2:
1904: 21 00 22        LD      HL,$2200            ; Player 2 data area
1907: C3 C3 01        JP      $01C3               ; Initialize player 2 aliens

PlyrShotAndBump:
190A: CD D8 14        CALL    PlayerShotHit       ; Player's shot collision detection
190D: C3 97 15        JP      RackBump            ; Change alien deltaX and deltaY when rack bumps edges

CurPlyAlive:
; Get the current player's alive status
1910: 21 E7 20        LD      HL,$20E7            ; Alive flags
1913: 3A 67 20        LD      A,(playerDataMSB)   ; Player 1 or 2
1916: 0F              RRCA                        ; Will be 1 if player 1
1917: D8              RET     C                   ; Return if player 1
1918: 23              INC     HL                  ; Bump to player 2
1919: C9              RET                         ; Return

DrawScoreHead:
; Print score header " SCORE<1> HI-SCORE SCORE<2> "
191A: 0E 1C           LD      C,$1C               ; 28 bytes in message
191C: 21 1E 24        LD      HL,$241E            ; Screen coordinates
191F: 11 E4 1A        LD      DE,$1AE4            ; Score header message
1922: C3 F3 08        JP      PrintMessage        ; Print score header

1925: 21 F8 20        LD      HL,$20F8            ; Player 1 score descriptor
1928: C3 31 19        JP      DrawScore           ; Print score

192B: 21 FC 20        LD      HL,$20FC            ; Player 2 score descriptor
192E: C3 31 19        JP      DrawScore           ; Print score

DrawScore:
; Print score.
; HL = descriptor
1931: 5E              LD      E,(HL)              ; Get score LSB
1932: 23              INC     HL                  ; Next
1933: 56              LD      D,(HL)              ; Get score MSB
1934: 23              INC     HL                  ; Next
1935: 7E              LD      A,(HL)              ; Get coordinate LSB
1936: 23              INC     HL                  ; Next
1937: 66              LD      H,(HL)              ; Get coordiante MSB
1938: 6F              LD      L,A                 ; Set LSB
1939: C3 AD 09        JP      Print4Digits        ; Print 4 digits in DE

; Print message "CREDIT "
193C: 0E 07           LD      C,$07               ; 7 bytes in message
193E: 21 01 35        LD      HL,$3501            ; Screen coordinates
1941: 11 A9 1F        LD      DE,$1FA9            ; Message = "CREDIT "
1944: C3 F3 08        JP      PrintMessage        ; Print message

DrawNumCredits:
; Display number of credits on screen
1947: 3A EB 20        LD      A,(numCoins)        ; Number of credits
194A: 21 01 3C        LD      HL,$3C01            ; Screen coordinates
194D: C3 B2 09        JP      DrawHexByte         ; Character to screen

PrintHiScore:
1950: 21 F4 20        LD      HL,$20F4            ; Hi Score descriptor
1953: C3 31 19        JP      DrawScore           ; Print Hi-Score

DrawStatus:
; Print scores (with header) and credits (with label)
1956: CD 5C 1A        CALL    ClearScreen         ; Clear the screen
1959: CD 1A 19        CALL    DrawScoreHead       ; Print score header
195C: CD 25 19        CALL    $1925               ; Print player 1 score
195F: CD 2B 19        CALL    $192B               ; Print player 2 score
1962: CD 50 19        CALL    PrintHiScore        ; Print hi score
1965: CD 3C 19        CALL    $193C               ; Print credit lable
1968: C3 47 19        JP      DrawNumCredits      ; Number of credits

196B: CD DC 19        CALL    SoundBits3Off       ; From 170B with B=FB. Turn off player shot sound
196E: C3 71 16        JP      $1671               ; Update high-score if player's score is greater

1971: 3E 01           LD      A,$01               ; Set flag that ...
1973: 32 6D 20        LD      (invaded),A         ; ... aliens reached bottom of screen
1976: C3 E6 16        JP      $16E6               ; End of round

1979: CD D7 19        CALL    DsableGameTasks     ; Disable ISR game tasks
197C: CD 47 19        CALL    DrawNumCredits      ; Display number of credits on screen
197F: C3 3C 19        JP      $193C               ; Print message "CREDIT"

1982: 32 C1 20        LD      (isrSplashTask),A   ; Set ISR splash task
1985: C9              RET                         ; Done

; The original code (from TAITO) printed this message on the screen. When Midway branched the code
; they changed the logic so it isn't printed.

1986: 8B 19 ; Points to print TAITO CORPORATION message ... not sure why
               
1988: C3 D6 09        JP      ClearPlayField      ; Clear playfield and out

; Print "*TAITO CORPORATION*"
198B: 21 03 28        LD      HL,$2803            ; Screen coordinates
198E: 11 BE 19        LD      DE,$19BE            ; Message "*TAITO CORPORATION*"
1991: 0E 13           LD      C,$13               ; Messgae length
1993: C3 F3 08        JP      PrintMessage        ; Print message

; The original TAITO code:
;1985: C3 8B 19     JP    $198B              ;
;1988: CD D6 09     CALL  $09D6              ;
;198B: 21 03 28     LD    HL,$2803           ;
;198E: 11 BE 19     LD    DE,$19BE           ;
;1991: 0E 13        LD    C,$13              ;
;1993: C3 F3 08     JP    $08F3              ;

1996: 00 00 00 00 ; ** Why?
                         
CheckHiddenMes:
; There is a hidden message "TAITO COP" (with no "R") in the game. It can only be
; displayed in the demonstration game during the splash screens. You must enter
; 2 seqences of buttons. Timing is not critical. As long as you eventually get all
; the buttons up/down in the correct pattern then the game will register the
; sequence.
;
; 1st: 2start(down) 1start(up)   1fire(down) 1left(down) 1right(down)
; 2nd: 2start(up)   1start(down) 1fire(down) 1left(down) 1right(up)
;
; Unfortunately MAME does not deliver the simultaneous button presses correctly. You can see the message in
; MAME by changing 19A6 to 02 and 19B1 to 02. Then the 2start(down) is the only sequence.
;
199A: 3A 1E 20        LD      A,(hidMessSeq)      ; Has the 1st "hidden-message" sequence ...
199D: A7              AND     A                   ; ... been registered?
199E: C2 AC 19        JP      NZ,$19AC            ; Yes ... go look for the 2nd sequence
19A1: DB 01           IN      A,(INP1)            ; Get player inputs
19A3: E6 76           AND     $76                 ; 0111_0110 Keep 2Pstart, 1Pstart, 1Pshot, 1Pleft, 1Pright
19A5: D6 72           SUB     $72                 ; 0111_0010 1st sequence: 2Pstart, 1Pshot, 1Pleft, 1Pright
19A7: C0              RET     NZ                  ; Not first sequence ... out
19A8: 3C              INC     A                   ; Flag that 1st sequence ...
19A9: 32 1E 20        LD      (hidMessSeq),A      ; ... has been entered
19AC: DB 01           IN      A,(INP1)            ; Check inputs for 2nd sequence
19AE: E6 76           AND     $76                 ; 0111_0110 Keep 2Pstart, 1Pstart, 1Pshot, 1Pleft, 1Pright
19B0: FE 34           CP      $34                 ; 0011_0100 2nd sequence: 1Pstart, 1Pshot, 1Pleft
19B2: C0              RET     NZ                  ; If not second sequence ignore
19B3: 21 1B 2E        LD      HL,$2E1B            ; Screen coordinates
19B6: 11 F7 0B        LD      DE,$0BF7            ; Message = "TAITO COP" (no R)
19B9: 0E 09           LD      C,$09               ; Message length
19BB: C3 F3 08        JP      PrintMessage        ; Print message and out

MessageTaito:
; "*TAITO CORPORATION*"
19BE: 28 13 00 08 13 0E 26 02 0E 11 0F 0E 11      
19CB: 00 13 08 0E 0D 28

EnableGameTasks:
; Enable ISR game tasks
19D1: 3E 01           LD      A,$01               ; Set ISR ...
19D3: 32 E9 20        LD      (suspendPlay),A     ; ... game tasks enabled
19D6: C9              RET                         ; Done

DsableGameTasks:
; Disable ISR game tasks
; Clear 20E9 flag
19D7: AF              XOR     A                   ; Clear ISR game tasks flag
19D8: C3 D3 19        JP      $19D3               ; Save a byte (the RET)
19DB: 00                                          ; ** Here is the byte saved. I wonder if this was an optimizer pass.

SoundBits3Off:
; Turn off bit in sound port
19DC: 3A 94 20        LD      A,(soundPort3)      ; Current sound effects value
19DF: A0              AND     B                   ; Mask bits off
19E0: 32 94 20        LD      (soundPort3),A      ; Store new hold value
19E3: D3 03           OUT     (SOUND1),A          ; Change sounds
19E5: C9              RET                         ; Done

DrawNumShips:
; Show ships remaining in hold for the player
19E6: 21 01 27        LD      HL,$2701            ; Screen coordinates
19E9: CA FA 19        JP      Z,$19FA             ; None in reserve ... skip display
; Draw line of ships
19EC: 11 60 1C        LD      DE,$1C60            ; Player sprite
19EF: 06 10           LD      B,$10               ; 16 rows
19F1: 4F              LD      C,A                 ; Hold count
19F2: CD 39 14        CALL    DrawSimpSprite      ; Display 1byte sprite to screen
19F5: 79              LD      A,C                 ; Restore remaining
19F6: 3D              DEC     A                   ; All done?
19F7: C2 EC 19        JP      NZ,$19EC            ; No ... keep going
; Clear remainder of line
19FA: 06 10           LD      B,$10               ; 16 rows
19FC: CD CB 14        CALL    ClearSmallSprite    ; Clear 1byte sprite at HL
19FF: 7C              LD      A,H                 ; Get Y coordinate
1A00: FE 35           CP      $35                 ; At edge?
1A02: C2 FA 19        JP      NZ,$19FA            ; No ... do all
1A05: C9              RET                         ; Out

CompYToBeam:
;
; The ISRs set the upper bit of 2072 based on where the beam is. This is compared to the
; upper bit of an object's Y coordinate to decide whic ISR should handle it. When the
; beam passes the halfway point (or near it ... at scanline 96), the upper bit is cleared.
; When the beam reaches the end of the screen the upper bit is set.
;
; The task then runs in the ISR if the Y coordiante bit matches the 2072 flag. Objects that
; are at the top of the screen (upper bit of Y clear) run in the mid-screen ISR when
; the beam has moved to the bottom of the screen. Objects that are at the bottom of the screen
; (upper bit of Y set) run in the end-screen ISR when the beam is moving back to the top.
;
; The pointer to the object's Y coordinate is passed in DE. CF is set if the upper bits are
; the same (the calling ISR should execute the task).
;
1A06: 21 72 20        LD      HL,$2072            ; Get the ...
1A09: 46              LD      B,(HL)              ; ... beam position status
1A0A: 1A              LD      A,(DE)              ; Get the task structure flag
1A0B: E6 80           AND     $80                 ; Only upper bits count
1A0D: A8              XOR     B                   ; XOR them together
1A0E: C0              RET     NZ                  ; Not the same (CF cleared)
1A0F: 37              SCF                         ; Set the CF if the same
1A10: C9              RET                         ; Done

; Alien delay lists. First list is the number of aliens. The second list is the corresponding delay.
; This delay is only for the rate of change in the fleet's sound.
; The check takes the first num-aliens-value that is lower or the same as the actual num-aliens on screen.
;
; The game starts with 55 aliens. The aliens are move/drawn one per interrupt which means it
; takes 55 interrupts. The first delay value is 52 ... which is almost in sync with the number
; of aliens. It is a tad faster and you can observe the sound and steps getting out of sync.
;
1A11: 32 2B 24 1C 16 11 0D 0A 08 07 06 05 04 03 02 01
1A21: 34 2E 27 22 1C 18 15 13 10 0E 0D 0C 0B 09 07 05     
1A31: FF   ; ** Needless terminator. The list value "1" catches everything.

BlockCopy:
; Copy from [DE] to [HL] (b bytes)
1A32: 1A              LD      A,(DE)              ; Copy from [DE] to ...
1A33: 77              LD      (HL),A              ; ... [HL]
1A34: 23              INC     HL                  ; Next destination
1A35: 13              INC     DE                  ; Next source
1A36: 05              DEC     B                   ; Count in B
1A37: C2 32 1A        JP      NZ,BlockCopy        ; Do all
1A3A: C9              RET                         ; Done

ReadDesc:
; Load 5 bytes sprite descriptor from [HL]
1A3B: 5E              LD      E,(HL)              ; Descriptor ...
1A3C: 23              INC     HL                  ; ... sprite ...
1A3D: 56              LD      D,(HL)              ; ...
1A3E: 23              INC     HL                  ; ... picture
1A3F: 7E              LD      A,(HL)              ; Descriptor ...
1A40: 23              INC     HL                  ; ... screen ...
1A41: 4E              LD      C,(HL)              ; ...
1A42: 23              INC     HL                  ; ... location
1A43: 46              LD      B,(HL)              ; Number of bytes in sprite
1A44: 61              LD      H,C                 ; From A,C to ...
1A45: 6F              LD      L,A                 ; ... H,L
1A46: C9              RET                         ; Done

ConvToScr:
; The screen is organized as one-bit-per-pixel.
; In: HL contains pixel number (bbbbbbbbbbbbbppp)
; Convert from pixel number to screen coordinates (without shift)
; Shift HL right 3 bits (clearing the top 2 bits)
; and set the third bit from the left.
1A47: C5              PUSH    BC                  ; Hold B (will mangle)
1A48: 06 03           LD      B,$03               ; 3 shifts (divide by 8)
1A4A: 7C              LD      A,H                 ; H to A
1A4B: 1F              RRA                         ; Shift right (into carry, from doesn't matter)
1A4C: 67              LD      H,A                 ; Back to H
1A4D: 7D              LD      A,L                 ; L to A
1A4E: 1F              RRA                         ; Shift right (from/to carry)
1A4F: 6F              LD      L,A                 ; Back to L
1A50: 05              DEC     B                   ; Do all ...
1A51: C2 4A 1A        JP      NZ,$1A4A            ; ... 3 shifts
1A54: 7C              LD      A,H                 ; H to A
1A55: E6 3F           AND     $3F                 ; Mask off all but screen (less than or equal 3F)
1A57: F6 20           OR      $20                 ; Offset into RAM
1A59: 67              LD      H,A                 ; Back to H
1A5A: C1              POP     BC                  ; Restore B
1A5B: C9              RET                         ; Done

ClearScreen:
; Clear the screen
; Thanks to Mark Tankard for pointing out what this really does
1A5C: 21 00 24        LD      HL,$2400            ; Screen coordinate
1A5F: 36 00           LD      (HL),$00            ; Clear it
1A61: 23              INC     HL                  ; Next byte
1A62: 7C              LD      A,H                 ; Have we done ...
1A63: FE 40           CP      $40                 ; ... all the screen?
1A65: C2 5F 1A        JP      NZ,$1A5F            ; No ... keep going
1A68: C9              RET                         ; Out

RestoreShields:
; Logically OR the player's shields back onto the playfield
; DE = sprite
; HL = screen
; C = bytes per row
; B = number of rows
1A69: C5              PUSH    BC                  ; Preserve BC
1A6A: E5              PUSH    HL                  ; Hold for a bit
1A6B: 1A              LD      A,(DE)              ; From sprite
1A6C: B6              OR      (HL)                ; OR with screen
1A6D: 77              LD      (HL),A              ; Back to screen
1A6E: 13              INC     DE                  ; Next sprite
1A6F: 23              INC     HL                  ; Next on screen
1A70: 0D              DEC     C                   ; Row done?
1A71: C2 6B 1A        JP      NZ,$1A6B            ; No ... do entire row
1A74: E1              POP     HL                  ; Original start
1A75: 01 20 00        LD      BC,$0020            ; Bump HL by ...
1A78: 09              ADD     HL,BC               ; ... one screen row
1A79: C1              POP     BC                  ; Restore
1A7A: 05              DEC     B                   ; Row counter
1A7B: C2 69 1A        JP      NZ,RestoreShields   ; Do all rows
1A7E: C9              RET                         

RemoveShip:
; Remove a ship from the players stash and update the
; hold indicators on the screen.
1A7F: CD 2E 09        CALL    $092E               ; Get last byte from player data
1A82: A7              AND     A                   ; Is it 0?
1A83: C8              RET     Z                   ; Skip
1A84: F5              PUSH    AF                  ; Preserve number remaining
1A85: 3D              DEC     A                   ; Remove a ship from the stash
1A86: 77              LD      (HL),A              ; New number of ships
1A87: CD E6 19        CALL    DrawNumShips        ; Draw the line of ships
1A8A: F1              POP     AF                  ; Restore number
1A8B: 21 01 25        LD      HL,$2501            ; Screen coordinates
1A8E: E6 0F           AND     $0F                 ; Make sure it is a digit
1A90: C3 C5 09        JP      $09C5               ; Print number remaining

Data From Here Down

1A93: 00 00       

; Splash screen animation structure 1
; 00   Image form (increments each draw)
; 00   Delta X
; FF   Delta Y is -1
; B8   X coordinate
; FE   Y starting coordiante
; 1C20 Base image (small alien)
; 10   Size of image (16 bytes)
; 9E   Target Y coordiante
; 00   Reached Y flag
; 1C20 Base iamge (small alien)
1A95: 00 00 FF B8 FE 20 1C 10 9E 00 20 1C   

ShotReloadRate:
; The tables at 1CB8 and 1AA1 control how fast shots are created. The speed is based
; on the upper byte of the player's score. For a score of less than or equal 0200 then
; the fire speed is 30. For a score less than or equal 1000 the shot speed is 10. Less
; than or equal 2000 the speed is 0B. Less than or equal 3000 is 08. And anything
; above 3000 is 07.
;
; 1CB8: 02 10 20 30
;
1AA1: 30 10 0B 08                           
1AA5: 07           ; Fastest shot firing speed

MessageGOver:
; GAME OVER PLAYER< >"
1AA6: 06 00 0C 04 26 0E 15 04 11 26 26 0F   
1AB2: 0B 00 18 04 11 24 26 25               

MessageB1or2:
; "1 OR 2PLAYERS BUTTON"
1ABA: 1B 26 0E 11 26 1C 0F 0B 00 18 04      
1AC5: 11 12 26 01 14 13 13 0E 0D 26

Message1Only:
; "ONLY 1PLAYER BUTTON "
; Note the space on the end ... both alternatives are same length
1ACF: 0E 0D 0B 18 26 1B 0F 0B 00 18 04 11 26 26 
1ADD: 01 14 13 13 0E 0D 26                  

MessageScore:
; " SCORE<1> HI-SCORE SCORE<2>"
1AE4: 26 12 02 0E 11 04 24 1B 25 26 07 08   
1AF0: 3F 12 02 0E 11 04 26 12 02 0E 11 04   
1AFC: 24 1C 25 26                     

;-------------------------- RAM initialization -----------------------------
; Coppied to RAM (2000) C0 bytes as initialization.
; See the description of RAM at the top of this file for the details on this data.

1B00: 01 00 00 10 00 00 00 00 02 78 38 78 38 00 F8 00
1B10: 00 80 00 8E 02 FF 05 0C 60 1C 20 30 10 01 00 00   
1B20: 00 00 00 BB 03 00 10 90 1C 28 30 01 04 00 FF FF   
1B30: 00 00 02 76 04 00 00 00 00 00 04 EE 1C 00 00 03    
1B40: 00 00 00 B6 04 00 00 01 00 1D 04 E2 1C 00 00 03 
1B50: 00 00 00 82 06 00 00 01 06 1D 04 D0 1C 00 00 03
1B60: FF 00 C0 1C 00 00 10 21 01 00 30 00 12 00 00 00         

; These don't need to be copied over to RAM (see 1BA0 below).
MesssageP1:
; "PLAY PLAYER<1>"
1B70: 0F 0B 00 18 26 0F 0B 00 18 04 11 24 1B 25 FC 
1B7F: 00 

1B80: 01 FF FF 00 00 00 20 64 1D D0 29 18 02 54 1D 00               
1B90: 08 00 06 00 00 01 40 00 01 00 00 10 9E 00 20 1C                                 
 
; These don't need to be copied over to RAM I believe this to be a mistake. The constant at 01E4 is C0,
; which is the size of this mirror with the added sprite. It should be A0. I believe there was a macro
; to size this area and later the splash screens where put in. Some of the data spilled over into this
; and the macro automatically included it. No harm.

Alien Pulling Upside Down 'Y'

; Alien sprite type C pulling upside down Y
AlienSprCYA:
; ........
; **......
; ..*.....
; ...****.
; ..*.*...
; **..*...
; ...*....
; .*.**...
; *.****..
; ...*.**.
; ..******
; ..******
; ...*.**.
; *.****..
; .*.**...
; ........
1BA0: 00 03 04 78 14 13 08 1A 3D 68 FC FC 68 3D 1A 00                                    

1BB0: 00 00 01 B8 98 A0 1B 10 FF 00 A0 1B 00 00 00 00                                    
;--------------------------- End of initialization copy -------------------------


; Shot descriptor for splash shooting the extra "C"
1BC0: 00 10 00 0E 05 00 00 00 00 00 07 D0 1C C8 9B 03
AlienSprCYB:
; Alien sprite C pulling upside down Y. Note the difference between this and the first picutre
; above. The Y is closer to the ship. This gives the effect of the Y kind of "sticking" in the
; animation.
; ........
; ........
; **......
; ..*.....
; ...****.
; ..*.*...
; **.*....
; *..**...
; .*.***..
; *.**.**.
; .*.*****
; .*.*****
; *.**.**.
; .*.***..
; *..**...
; ........
;
1BD0: 00 00 03 04 78 14 0B 19 3A 6D FA FA 6D 3A 19 00                                    

; More RAM initialization copied by 18D9
1BE0: 00 00 00 00 00 00 00 00 00 01 00 00 01 74 1F 00                                    
1BF0: 80 00 00 00 00 00 1C 2F 00 00 1C 27 00 00 1C 39 

AlienSprA:

Alien Images

; Alien sprite type A,B, and C at positions 0
;  ........ ........ ........
;  ........ ........ ........
;  *..***.. ........ ........
;  *..****. ...****. ........
;  .*.****. *.***... *..**...
;  .***.**. .*****.* .*.***..
;  ..**.*** ..**.**. *.**.**.
;  .*.***** ..****.. .*.*****
;  .*.***** ..****.. .*.*****
;  ..**.*** ..****.. *.**.**.
;  .***.**. ..**.**. .*.***..
;  .*.****. .*****.* *..**...
;  *..****. *.***... ........
;  *..***.. ...****. ........
;  ........ ........ ........
;  ........ ........ ........
1C00: 00 00 39 79 7A 6E EC FA FA EC 6E 7A 79 39 00 00 
1C10: 00 00 00 78 1D BE 6C 3C 3C 3C 6C BE 1D 78 00 00 
1C20: 00 00 00 00 19 3A 6D FA FA 6D 3A 19 00 00 00 00 

AlienSprB:
; Alien sprite type A,B, and C at positions 1
;  ........ ........ ........
;  ........ ........ ........
;  ...***.. ........ ........
;  .*.****. .***.... ........
;  *******. ...**... .*.**...
;  *.**.**. .*****.* *.****..
;  ..**.*** *.**.**. ...*.**.
;  .*.***** *.****.. ..******
;  .*.***** ..****.. ..******
;  ..**.*** *.****.. ...*.**.
;  *.**.**. *.**.**. *.****..
;  *******. .*****.* .*.**...
;  .*.****. ...**... ........
;  ...***.. .***.... ........
;  ........ ........ ........
;  ........ ........ ........
1C30: 00 00 38 7A 7F 6D EC FA FA EC 6D 7F 7A 38 00 00 
1C40: 00 00 00 0E 18 BE 6D 3D 3C 3D 6D BE 18 0E 00 00 
1C50: 00 00 00 00 1A 3D 68 FC FC 68 3D 1A 00 00 00 00 

Player Sprite

PlayerSprite:
;  ........
;  ........
;  ****....
;  *****...
;  *****...
;  *****...
;  *****...
;  *******.
;  ********
;  *******.
;  *****...
;  *****...
;  *****...
;  *****...
;  ****....
;  ........
1C60: 00 00 0F 1F 1F 1F 1F 7F FF 7F 1F 1F 1F 1F 0F 00 


PlrBlowupSprites:
;  ........
;  ..*.....
;  *.......
;  **..*...
;  **......
;  ***.....
;  **..**.*
;  ****....
;  ****.*..
;  **......
;  ****.*..
;  *..*..*.
;  ..*.....
;  **......
;  ........
;  *.......
;
1C70: 00 04 01 13 03 07 B3 0F 2F 03 2F 49 04 03 00 01 
;
;  ......*.
;  ...*....
;  *.*.....
;  **...*.*
;  .*.*....
;  **......
;  **.**.*.
;  ****....
;  ***..*..
;  ***..*..
;  **.*....
;  **.*..*.
;  ......*.
;  ..*....*
;  *...*...
;  ...*..*.
1C80: 40 08 05 A3 0A 03 5B 0F 27 27 0B 4B 40 84 11 48 

Player Shot Sprite

PlayerShotSpr:
1C90: 0F    ; ++++....

Player Shot Exploding

ShotExploding:
; *..**..*
; ..****..
; .******.
; *.****..
; ..****.*
; .*****..
; ..*****.
; *..**..*
1C91: 99 3C 7E 3D BC 3E 7C 99     
      
Message10Pts:
; Ran out of space at 1DFE
1C99: 27 1B 1A 26 0F 0E 08 0D 13 12    ; "=10 POINTS"

MessageAdv:
; "*SCORE ADVANCE TABLE*"
1CA3: 28 12 02 0E 11 04 26 00                                 
1CAB: 03 15 00 0D 02 04 26 13                                 
1CB3: 00 01 0B 04 28                                    


AReloadScoreTab:
; The tables at 1CB8 and 1AA1 control how fast shots are created. The speed is based
; on the upper byte of the player's score. For a score of less than or equal 0200 then
; the fire speed is 30. For a score less than or equal 1000 the shot speed is 10. Less
; than or equal 2000 the speed is 0B. Less than or equal 3000 is 08. And anything
; above 3000 is 07.
;
; 1AA1: 30 10 0B 08
; 1AA5: 07           ; Fastest shot firing speed
;
1CB8: 02 10 20 30                           

MessageTilt:
1CBC: 13 08 0B 13   ; "TILT"

Alien Exploding Sprite

; Alien exploding sprite
AlienExplode:
;  ........
;  ...*....
;  *..*..*.
;  .*...*..
;  ..*.*...
;  *......*
;  .*....*.
;  ........
;  .*....*.
;  *......*
;  ..*.*...
;  .*...*..
;  *..*..*.
;  ...*....
;  ........
;  ........
1CC0: 00 08 49 22 14 81 42 00 42 81 14 22 49 08 00 00 

Squigly Shot Sprite

; Squigly shot picture in 4 animation frames
SquiglyShot:
1CD0: 44   ; ..*...*.
1CD1: AA   ; .*.*.*.*
1CD2: 10   ; ....*...

1CD3: 88   ; ...*...*
1CD4: 54   ; ..*.*.*.
1CD5: 22   ; .*...*..

1CD6: 10   ; ....*...
1CD7: AA   ; .*.*.*.*
1CD8: 44   ; ..*...*.
                                 
1CD9: 22   ; .*...*..
1CDA: 54   ; ..*.*.*.
1CDB: 88   ; ...*...*

Alien Shot Exploding

; Alien shot exploding
AShotExplo:      
; .*.*..*.
; *.*.*...
; .*****.*
; ******..
; .****.*.
; *.*..*..
1CDC: 4A 15 BE 3F 5E 25                                

Plunger Shot Sprite

; Alien shot ... the plunger looking one
PlungerShot:
1CE2: 04  ; ..*.....
1CE3: FC  ; ..******
1CE4: 04  ; ..*.....

1CE5: 10  ; ....*...
1CE6: FC  ; ..******
1CE7: 10  ; ....*...

1CE8: 20  ; .....*..
1CE9: FC  ; ..******
1CEA: 20  ; .....*..

1CEB: 80  ; .......*
1CEC: FC  ; ..******
1CED: 80  ; .......*

Rolling Shot Sprite

; Alien shot ... the rolling one
RollShot:
1CEE: 00  ; ........
1CEF: FE  ; .*******
1CF0: 00  ; ........

1CF1: 24  ; ..*..*..
1CF2: FE  ; .*******
1CF3: 12  ; .*..*...

1CF4: 00  ; ........
1CF5: FE  ; .*******
1CF6: 00  ; ........

1CF7: 48  ; ...*..*.
1CF8: FE  ; .*******
1CF9: 90  ; ....*..*
               
MessagePlayUY:
1CFA: 0F 0B 00 29    ; "PLAy" with an upside down 'Y' for splash screen
                      
1CFE: 00 00        
                            
ColFireTable:
; This table decides which column a shot will fall from. The column number is read from the
; table (1-11) and the pointer increases for the shot type. For instance, the "squiggly" shot
; will fall from columns in this order: 0B, 01, 06, 03. If you play the game you'll see that
; order.
;
; The "plunger" shot uses index 00-0F (inclusive)
; The "squiggly" shot uses index 06-14 (inclusive)
; The "rolling" shot targets the player
1D00: 01 07 01 01 01 04 0B 01 06 03 01 01 0B 09 02 08                                    
1D10: 02 0B 04 07 0A    
;
; This appears to be part of the column-firing table, but it is never used.
; Perhaps this was originally intended for the "rolling" shot but then the
; "rolling" was change to target the player specifically.
1D15: 05 02 05 04 06 07 08 0A 06 0A 03              

Shield Image

ShieldImage:
; Shield image pattern. 2 x 22 = 44 bytes.
;
;************....
;*************...
;**************..
;***************.
;****************
;..**************
;...*************
;....************
;....************
;....************
;....************
;....************
;....************
;....************
;...*************
;..**************
;****************
;****************
;***************.
;**************..
;*************...
;************....
;
1D20: FF 0F FF 1F FF 3F FF 7F FF FF FC FF F8 FF F0 FF F0 FF F0 FF F0 FF                                    
1D36: F0 FF F0 FF F0 FF F8 FF FC FF FF FF FF FF FF 7F FF 3F FF 1F FF 0F                                    


1D4C: 05 10 15 30  ; Table of possible saucer scores
1D50: 94 97 9A 9D  ; Table of corresponding string prints for each possible score

SaucerScrTab:
; 208D points here to the score given when the saucer is shot. It advances
; every time the player-shot is removed. The code wraps after 15, but there
; are 16 values in this table. This is a bug in the code at 044E (thanks to
; Colin Dooley for finding this).
;
; Thus the one and only 300 comes up every 15 shots (after an initial 8).
1D54: 10 05 05 10 15 10 10 05 30 10 10 10 05 15 10 05                                 

Flying Saucer Sprite

SpriteSaucer:
; ........
; ........
; ........
; ........
; ..*.....
; ..**....
; .****...
; ***.**..
; .*****..
; ..*****.
; ..*.***.
; .******.
; .******.
; ..*.***.
; ..*****.
; .*****..
; ***.**..
; .****...
; ..**....
; ..*.....
; ........
; ........
; ........
; ........
1D64: 00 00 00 00 04 0C 1E 37 3E 7C 74 7E 7E 74 7C 3E 37 1E 0C 04 00 00 00 00

SpriteSaucerExp:
;........
;.*...*..
;........
;*.*..*.*
;......*.
;...*....
;...**..*
;*.****..
;.**.**.*
;..****..
;.**.**..
;*.***...
;....*...
;...*..*.
;.*...**.
;.**.**.*
;*.***...
;...**..*
;...*....
;.*....*.
;....*..*
;...*....
;........
;........
1D7C: 00 22 00 A5 40 08 98 3D B6 3C 36 1D 10 48 62 B6 1D 98 08 42 90 08 00 00  
         
SaucSoreStr:
1D94: 26 1F 1A  ; _50
1D97: 1B 1A 1A  ; 100
1D9A: 1B 1F 1A  ; 150
1D9D: 1D 1A 1A  ; 300

AlienScores:
; Score table for hitting alien type
1DA0: 10 ; Bottom 2 rows
1DA1: 20 ; Middle row
1DA2: 30 ; Highest row
         
AlienStartTable:
; Starting Y coordinates for aliens at beginning of rounds. The first round is initialized to $78 at 07EA.
; After that this table is used for 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, and 9th. The 10th starts over at
; 1DA3 (60).
1DA3: 60                                    
1DA4: 50                                    
1DA5: 48                                    
1DA6: 48                                    
1DA7: 48                                    
1DA8: 40                                    
1DA9: 40                                    
1DAA: 40   
                                 
MessagePlayY:
1DAB: 0F 0B 00 18   ; "PLAY" with normal Y

MessageInvaders:
; "SPACE  INVADERS"
1DAF: 12 0F 00 02 04 26 26 08 0D 15 00 03 04 11 12 

; Tables used to draw "SCORE ADVANCE TABLE" information
1DBE: 0E 2C 68 1D           ; Flying Saucer
1DC2: 0C 2C 20 1C           ; Alien C, sprite 0
1DC6: 0A 2C 40 1C           ; Alien B, sprite 1
1DCA: 08 2C 00 1C           ; Alien A, sprite 0
1DCE: FF                    ; End of list
;
AlienScoreTable:
1DCF: 0E 2E E0 1D           ; "=? MYSTERY"
1DD3: 0C 2E EA 1D           ; "=30 POINTS"
1DD7: 0A 2E F4 1D           ; "=20 POINTS"
1DDB: 08 2E 99 1C           ; "=10 POINTS"
1DDF: FF                    ; End of list

MessageMyst:
1DE0: 27 38 26 0C 18 12 13 04 11 18   ; "=? MYSTERY"

Message30Pts:
1DEA: 27 1D 1A 26 0F 0E 08 0D 13 12   ; "=30 POINTS"

Message20Pts:
1DF4: 27 1C 1A 26 0F 0E 08 0D 13 12   ; "=20 POINTS"

; Ran out of space here. The "=10" message is up at 1C99. That keeps
; the font table firmly at 1E00.

1DFE: 00 00 ; Padding to put font table at 1E00

Text Character Sprites

; 8 byte sprites
; The screen is turned so rotate these pictures counter-clockwise.
; Some of the font characters at the end were never needed. The ROM overwrites these characters with
; data near the end. For instance, 1F90 would be a character but has the "INSERT COIN" message. The "?"
; character is at 1FC0 and is used in messages as is 1FF8 "-". The "light colored" tiles in the grid below
; show the character slots that have been repurposed.
Characters:
1E00: 00 1F 24 44 24 1F 00 00  ; ........ ........ ........ ........ ........ ........ ........ ........
1E08: 00 7F 49 49 49 36 00 00  ; *****... *******. .*****.. *******. *******. *******. .*****.. *******.
1E10: 00 3E 41 41 41 22 00 00  ; ..*..*.. *..*..*. *.....*. *.....*. *..*..*. ...*..*. *.....*. ...*....
1E18: 00 7F 41 41 41 3E 00 00  ; ..*...*. *..*..*. *.....*. *.....*. *..*..*. ...*..*. *.....*. ...*....
1E20: 00 7F 49 49 49 41 00 00  ; ..*..*.. *..*..*. *.....*. *.....*. *..*..*. ...*..*. *.*...*. ...*....
1E28: 00 7F 48 48 48 40 00 00  ; *****... .**.**.. .*...*.. .*****.. *.....*. ......*. ***...*. *******.
1E30: 00 3E 41 41 45 47 00 00  ; ........ ........ ........ ........ ........ ........ ........ ........
1E38: 00 7F 08 08 08 7F 00 00  ; ........ ........ ........ ........ ........ ........ ........ ........

1E40: 00 00 41 7F 41 00 00 00  ; ........ ........ ........ ........ ........ ........ ........ ........
1E48: 00 02 01 01 01 7E 00 00  ; ........ .*...... *******. *******. *******. *******. .*****.. *******.
1E50: 00 7F 08 14 22 41 00 00  ; *.....*. *....... ...*.... *....... .....*.. ....*... *.....*. ...*..*.
1E58: 00 7F 01 01 01 01 00 00  ; *******. *....... ..*.*... *....... ...**... ...*.... *.....*. ...*..*.
1E60: 00 7F 20 18 20 7F 00 00  ; *.....*. *....... .*...*.. *....... .....*.. ..*..... *.....*. ...*..*.
1E68: 00 7F 10 08 04 7F 00 00  ; ........ .******. *.....*. *....... *******. *******. .*****.. ....**..
1E70: 00 3E 41 41 41 3E 00 00  ; ........ ........ ........ ........ ........ ........ ........ ........
1E78: 00 7F 48 48 48 30 00 00  ; ........ ........ ........ ........ ........ ........ ........ ........

1E80: 00 3E 41 45 42 3D 00 00  ; ........ ........ ........ ........ ........ ........ ........ ........
1E88: 00 7F 48 4C 4A 31 00 00  ; .*****.. *******. .*..**.. ......*. .******. ..*****. *******. **...**.
1E90: 00 32 49 49 49 26 00 00  ; *.....*. ...*..*. *..*..*. ......*. *....... .*...... .*...... ..*.*...
1E98: 00 40 40 7F 40 40 00 00  ; *.*...*. ..**..*. *..*..*. *******. *....... *....... ..**.... ...*....
1EA0: 00 7E 01 01 01 7E 00 00  ; .*....*. .*.*..*. *..*..*. ......*. *....... .*...... .*...... ..*.*...
1EA8: 00 7C 02 01 02 7C 00 00  ; *.****.. *...**.. .**..*.. ......*. .******. ..*****. *******. **...**.
1EB0: 00 7F 02 0C 02 7F 00 00  ; ........ ........ ........ ........ ........ ........ ........ ........
1EB8: 00 63 14 08 14 63 00 00  ; ........ ........ ........ ........ ........ ........ ........ ........

1EC0: 00 60 10 0F 10 60 00 00  ; ........ ........ ........ ........ ........ ........ ........ ........
1EC8: 00 43 45 49 51 61 00 00  ; .....**. **....*. .*****.. ........ **...*.. .*....*. ..**.... .*..***.
1ED0: 00 3E 45 49 51 3E 00 00  ; ....*... *.*...*. *.*...*. *....*.. *.*...*. *.....*. ..*.*... *...*.*.
1ED8: 00 00 21 7F 01 00 00 00  ; ****.... *..*..*. *..*..*. *******. *..*..*. *..*..*. ..*..*.. *...*.*.
1EE0: 00 23 45 49 49 31 00 00  ; ....*... *...*.*. *...*.*. *....... *..*..*. *..**.*. *******. *...*.*.
1EE8: 00 42 41 49 59 66 00 00  ; .....**. *....**. .*****.. ........ *...**.. .**..**. ..*..... .***..*.
1EF0: 00 0C 14 24 7F 04 00 00  ; ........ ........ ........ ........ ........ ........ ........ ........
1EF8: 00 72 51 51 51 4E 00 00  ; ........ ........ ........ ........ ........ ........ ........ ........

1F00: 00 1E 29 49 49 46 00 00  ; ........ ........ ........ ........ ........ ........ ........ ........
1F08: 00 40 47 48 50 60 00 00  ; .****... ......*. .**.**.. *...**.. ...*.... ........ ........ ..*.*...
1F10: 00 36 49 49 49 36 00 00  ; *..*.*.. ***...*. *..*..*. *..*..*. ..*.*... *.....*. ........ ..*.*...
1F18: 00 31 49 49 4A 3C 00 00  ; *..*..*. ...*..*. *..*..*. *..*..*. .*...*.. .*...*.. ........ ..*.*...
1F20: 00 08 14 22 41 00 00 00  ; *..*..*. ....*.*. *..*..*. .*.*..*. *.....*. ..*.*... ........ ..*.*...
1F28: 00 00 41 22 14 08 00 00  ; .**...*. .....**. .**.**.. ..****.. ........ ...*.... ........ ..*.*...
1F30: 00 00 00 00 00 00 00 00  ; ........ ........ ........ ........ ........ ........ ........ ........
1F38: 00 14 14 14 14 14 00 00  ; ........ ........ ........ ........ ........ ........ ........ ........

1F40: 00 22 14 7F 14 22 00 00  ; ........ ........
1F48: 00 03 04 78 04 03 00 00  ; .*...*.. **......
                               ; ..*.*... ..*.....
                               ; *******. ...****.
                               ; ..*.*... ..*.....
                               ; .*...*.. **......
                               ; ........ ........
                               ; ........ ........

MessageP1or2:
1F50: 24 1B 26 0E 11 26 1C 26  ; "<1 OR 2 PLAYERS>  "
1F58: 0F 0B 00 18 04 11 12 25               
1F60: 26 26 

Message1Coin:
1F62: 28 1B 26 0F 0B 00 18 04  ; "*1 PLAYER  1 COIN "
1F6A: 11 26 26 1B 26 02 0E 08 
1F72: 0D 26                           

DemoCommands:
; (1=Right, 2=Left)
1F74: 01 01 00 00 01 00 02 01 00 02 01 00

Alien Sprite Carrying 'Y'

; Small alien pushing Y back onto screen
AlienSprCA:
; .....**.
; ....*...
; ****....
; ....*...
; .....**.
; ....**..
; ...**...
; .*.**...
; *.****..
; ...*.**.
; ..******
; ..******
; ...*.**.
; *.****..
; .*.**...
; ........
                
1F80: 60 10 0F 10 60 30 18 1A 3D 68 FC FC 68 3D 1A 00               

MessageCoin:
1F90: 08 0D 12 04 11 13 26 26 02 0E 08 0D   ; "INSERT  COIN"
                          
CreditTable:
1F9C: 0D 2A 50 1F                 ; "<1 OR 2 PLAYERS>  " to screen at 2A0D
1FA0: 0A 2A 62 1F                 ; "*1 PLAYER  1 COIN " to screen at 2A0A
1FA4: 07 2A E1 1F                 ; "*2 PLAYERS 2 COINS" to screen at 2A07
1FA8: FF                          ; Terminates "table print"

MessageCredit:
1FA9: 02 11 04 03 08 13 26       ; "CREDIT " (with space on the end)

AlienSprCB:
; ........
; .....**.
; ....*...
; ****....
; ....*...
; .....**.
; ...***..
; *..**...
; .*.***..
; *.**.**.
; .*.*****
; .*.*****
; *.**.**.
; .*.***..
; *..**...
; ........
1FB0: 00 60 10 0F 10 60 38 19 3A 6D FA FA 6D 3A 19 00               

1FC0: 00 20 40 4D 50 20 00 00               ; "?"

1FC8: 00 

; Splash screen animation structure 3
; 00   Image form (increments each draw)
; 00   Delta X
; FF   Delta Y is -1
; B8   X coordinate
; FF   Y starting coordiante
; 1F80 Base image (small alien with Y)
; 10   Size of image (16 bytes)
; 97   Target Y coordiante
; 00   Reached Y flag
; 1F80 Base iamge (small alien with Y)
;
1FC9: 00 00 FF B8 FF 80 1F 10 97 00 80 1F 

; Splash screen animation structure 4
; 00   Image form (increments each draw)
; 00   Delta X
; 01   Delta Y is 1
; D0   X coordinate
; 22   Y starting coordiante
; 1C20 Base image (small alien)
; 10   Size of image (16 bytes)
; 94   Target Y coordiante
; 00   Reached Y flag
; 1C20 Base iamge (small alien)
;
1FD5: 00 00 01 D0 22 20 1C 10 94 00 20 1C 

Message2Coins:
1FE1: 28 1C 26 0F 0B 00 18 04    ; "*2 PLAYERS 2 COINS"
1FE9: 11 12 26 1C 26 02 0E 08 
1FF1: 0D 12                              

MessagePush:
1FF3: 0F 14 12 07 26             ; "PUSH " (with space on the end)

1FF8: 00 08 08 08 08 08 00 00               ; 3F:"-"