Space Invaders
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:"-"