--- /dev/null
+http://computerarcheology.com/Arcade/SpaceInvaders/Code.html
+
+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:"-"