0000- 5 0000- 6 ; ***************************************************************************** 0000- 7 ; MK14 Space Invaders game 0000- 8 ; Rev 2.0 0000- 9 ; Written by Ian Reynolds Dec 2022 for the SBASM 8060 assembler 0000- 10 ; 0000- 11 ; Requires continuous memory from 0x200 to 0x7FF and base RAM at 0xF00 0000- 12 ; INS8154 setup is specific to the RelView MK14 VDU module, so may need adjustment for operation with 0000- 13 ; other MK14 VDU cards 0000- 14 ; For correct operation the VDU TOPPAGE signal needs to be connected to PS1, to use 2 adjacent pages of video RAM 0000- 15 ; 0000- 16 ; You have 5 lives 0000- 17 ; When you clear all invaders from the screen a new set of invaders appear 0000- 18 ; Hitting an invader gets you 1 point, up to a maximum 999 points 0000- 19 ; The invaders are rotated across the screen. After 14 rotations the invaders drop down a row 0000- 20 ; 0000- 21 ; Keys: 1 to move shooter left 0000- 22 ; 2 to shoot a bullet 0000- 23 ; 3 to move shooter right 0000- 24 ; GO to restart game once all lives are used 0000- 25 ; 0000- 26 ; All characters on screen are defined by constants, so easy to customise 0000- 27 ; 0000- 28 ; Visit the UK Vintage Radio Forums, Vintage Computers, for updates 0000- 29 ; 0000- 30 ; https://www.vintage-radio.net/ My username is Realtime 0000- 31 ; 0000- 32 ; ***************************************************************************** 0000- 33 ; CHANGE LOG V2 0000- 34 ; Title text changed to MK14 INVADERS V2 0000- 35 ; 3 digit points counter 0000- 36 ; SCORE changed to HITS 0000- 37 ; Bullet character changed from : to " 0000- 38 ; Sound triggers added using INS8154 Port A for 0000- 39 ; Invader hit, Shooter hit, Bullet fired and Invader move 0000- 40 ; Abort key function removed to save space 0000- 41 ;****************************************************************************** 0000- 42 0000- 43 ;Game Constants 0200- 44 DISPL .EQ 0x0200 ; Start of VDU frame store 0400- 45 PROG .EQ 0x0400 ; Start of program memory 0F20- 46 VAR .EQ 0x0F20 ; Place variables in base RAM 0800- 47 INS8154 .EQ 0x0800 ; MK14 I/O chip base address 0020- 48 Port_A .EQ 0x20 ; INS8154 Port A Output register write address 0021- 49 Port_B .EQ 0x21 ; INS8154 Port B Output register write address 002D- 50 Char_Border .EQ 0x2D ; '-' 0020- 51 Char_Space .EQ 0x20 ; ' ' 001C- 52 Char_InvL .EQ 0x1C ; '\' 002F- 53 Char_InvR .EQ 0x2F ; '/' 0001- 54 Char_Shooter .EQ 0x01 ; 'A' 0022- 55 Char_Bullet .EQ 0x22 ; '"' 002A- 56 Char_Bomb .EQ 0x2A ; '*' 0023- 57 Char_Block .EQ 0x23 ; '#' 0003- 58 Shoot_Y .EQ DISPL/256+1 ; Lower page of video RAM 00D0- 59 Shoot_X_pos .EQ 0xD0 ; 3rd to last row 00F0- 60 Score_line .EQ 0xF0 ; Last row 0010- 61 Title_line .EQ 0x10 ; Top row above border 0061- 62 Block_L .EQ 0x61 ; Low byte of position of Blocks 0003- 63 Block_H .EQ DISPL/256+1 ; High byte of position of Blocks 0000- 64 0000- 65 ; Game Variables 0000- 66 Shoot_X .EQ 0x00 ; x-address of shooter (0x0-0xF) 0001- 67 Bullet_X .EQ 0x01 ; x-position of the bullet 0002- 68 Bullet_Y .EQ 0x02 ; y-position of the bullet 0003- 69 Bullet_ON .EQ 0x03 ; non-zero if bullet is active 0004- 70 Bomb_X .EQ 0x04 ; x-position of bomb 0005- 71 Bomb_Y .EQ 0x05 ; y-position of bomb 0006- 72 Bomb_ON .EQ 0x06 ; non-zero if bomb is active 0007- 73 Game_over .EQ 0x07 ; non-zero if game over 0008- 74 Lives .EQ 0x08 ; number of shooter lives left 0009- 75 Points_L .EQ 0x09 ; Points counter Low byte (BCD) 000A- 76 Points_H .EQ 0x0A ; Points counter High byte (BCD) 000B- 77 Rot_loops .EQ 0x0B ; Count down. When zero the invaders are rotated left 000C- 78 Drop_row .EQ 0x0C ; Count down. When zero the invaders can be dropped down one row 000D- 79 Inv_row1L .EQ 0x0D ; Address of first row of invaders 000E- 80 Inv_row1H .EQ 0x0E ; Address of first row of invaders 000F- 81 Inv_row2L .EQ 0x0F ; Address of second row of invaders 0010- 82 Inv_row2H .EQ 0x10 ; Address of second row of invaders 0011- 83 Inv_row3L .EQ 0x11 ; Address of second row of invaders 0012- 84 Inv_row3H .EQ 0x12 ; Address of second row of invaders 0013- 85 Count1 .EQ 0x13 ; General purpose loop counter 0014- 86 Count2 .EQ 0x14 ; General purpose loop counter 0015- 87 Det_Inv .EQ 0x15 ; Non-zero when invaders detected on screen 0016- 88 Ret_H .EQ 0x16 ; High byte of return-to-monitor address (ABORT) 0017- 89 Ret_L .EQ 0x17 ; Low byte of return-to-monitor address (ABORT) 0018- 90 Sound1 .EQ 0x18 ; Holds the latest sound event 0019- 91 Sound2 .EQ 0x19 ; Pulse extender for sound event 0000- 92 0000- 93 ; **************************************************************************** 0000- 94 0400- 95 .OR PROG 0400- 96 0400- 97 ENTER: 0400- 98 0400-C4 0F 99 ( 10) LDI VAR/256 0402-36 100 ( 8) XPAH P2 0403-C4 20 101 ( 10) LDI VAR\256 0405-32 102 ( 8) XPAL P2 0406- 103 0406- 104 ; XPAH P3 ; Store return to monitor address - ABORT function removed to save code space 0406- 105 ; ST Ret_H(P2) 0406- 106 ; XPAL P3 0406- 107 ; ST Ret_L(P2) 0406- 108 0406- 109 ; Set up INS8154 0406- 110 ; The following assumes the RealView MK14 VDU is being used, with INS8154 Port B 0406- 111 ; Other VDU's may require different set up byte 0406- 112 0406-C4 08 113 ( 10) LDI INS8154/256 ; Base address of I/O device 0408-37 114 ( 8) XPAH P3 0409-C4 00 115 ( 10) LDI INS8154\256 040B-33 116 ( 8) XPAL P3 040C-C4 0F 117 ( 10) LDI 0x0F ; 040E-CB 22 118 ( 18) ST 0x22(P3) ; Port A output definition register, bit7-bit4 inputs, bit3 to bit0 outputs 0410-C4 08 119 ( 10) LDI 0x08 ; 0412-CB 23 120 ( 18) ST 0x23(P3) ; Port B output definition register - bit3 (VDUOFF) as output, all others as inputs 0414-C4 00 121 ( 10) LDI 0x00 0416-CB 20 122 ( 18) ST Port_A(P3) ; Initialise port A - all off (Port A defaults to basic I/O mode after a reset) 0418-C4 F7 123 ( 10) LDI 0xF7 ; Set VDU control bits - Enable VDU only. All other controls are via RealView DIP switches 041A-CB 21 124 ( 18) ST Port_B(P3) ; Set port B outputs (Port B is always in basic I/O mode) 041C- 125 ; 041C- 126 ; Port A Sound Event Bits (all active low for aprox 150ms) 041C- 127 ; Bit 0: Shooter fired bullet 041C- 128 ; Bit 1: Invader hit 041C- 129 ; Bit 2: Shooter killed 041C- 130 ; Bit 3: Invaders move sideways 041C- 131 ; 041C- 132 ; Port B is set to all bits logic '1' except VDUOFF 041C- 133 ; DIP switches to be used to set VDU configuration 041C- 134 ; SW1: OFF (PS1 = logic 1) 041C- 135 ; SW2: OFF (PS2 = logic 1) 041C- 136 ; SW3: ON (PS3 = logic 0) 041C- 137 ; SW4: ON (PS4 = logic 0) 041C- 138 ; SW5: OFF (VDUOFF = 1. This allows the 8154 to control VDUOFF, wich is needed for the fast loader) 041C- 139 ; SW6: ON (GR/nChar = 0) 041C- 140 ; SW7: OFF (REVPAGES = 1) 041C- 141 ; SW8: ON (INVERT = 0) 041C- 142 ; SW9: ON (SRAM Enabled) 041C- 143 ; SW10: ON (TOPPAGE connected to PS1) 041C- 144 041C- 145 ; Port B bit 7 = PS3 - set to '1' \ 041C- 146 ; Port B bit 6 = PS1 - set to '1' \ Sets the video RAM address 041C- 147 ; Port B bit 5 = PS2 - set to '1' / PS1 must be logic '1' to allow it to be controlled by the TOPPAGE signal 041C- 148 ; Port B bit 4 = PS4 - set to '1' / 041C- 149 ; Port B bit 3 = VDUOFF - set to '0' for VDU on 041C- 150 ; Port B bit 2 = Graphics/nCharacters - set to '1' for character mode 041C- 151 ; Port B bit 1 = REVPAGES - set to '1' for 0x200 at top of the screen (0x300 at bottom) 041C- 152 ; Port B bit 0 = INVERT - set to '1' for white on black video 041C- 153 041C- 154 ; LDI 0x00 ; or lower FLAG2 for other card designs 041C- 155 ; CAS 041C- 156 041C- 157 START: 041C- 158 041C- 159 ; These variables get set only for first round of a game 041C-C4 00 160 ( 10) LDI 0x00 041E-CA 09 161 ( 18) ST Points_L(P2) ; Zero points 0420-CA 0A 162 ( 18) ST Points_H(P2) 0422-CA 07 163 ( 18) ST Game_over(P2) ; Game not over 0424-C4 05 164 ( 10) LDI 0x05 ; ************************************************************* 0426-CA 08 165 ( 18) ST Lives(P2) ; Five shooter lives 0428-CA 00 166 ( 18) ST Shoot_X(P2) ; Place shooter at left middle of screen 042A-C4 40 167 ( 10) LDI 0x40 042C-CA 0D 168 ( 18) ST Inv_row1L(P2) ; Set display position for 1st row of invaders 042E-C4 60 169 ( 10) LDI 0x60 0430-CA 0F 170 ( 18) ST Inv_row2L(P2) ; Set display position for 2nd row of invaders 0432-C4 80 171 ( 10) LDI 0x80 0434-CA 11 172 ( 18) ST Inv_row3L(P2) ; Set display position for 3rd row of invaders 0436-C4 02 173 ( 10) LDI DISPL/256 0438-CA 0E 174 ( 18) ST Inv_row1H(P2) ; Place all invaders in top half of screen 043A-CA 10 175 ( 18) ST Inv_row2H(P2) 043C-CA 12 176 ( 18) ST Inv_row3H(P2) 043E- 177 043E- 178 INVADE: 043E- 179 ;================================================ 043E- 180 ; Create the start-up screen 043E- 181 ;================================================ 043E- 182 ; Fill display with spaces 043E-C4 02 183 ( 10) LDI DISPL/256 ; lower display memory page high byte 0440-35 184 ( 8) XPAH P1 0441-C4 00 185 ( 10) LDI DISPL\256 ; lower display memory page low byte 0443-31 186 ( 8) XPAL P1 ; P1 now points to start of display 0444- 187 SC1: 0444-C4 20 188 ( 10) LDI Char_Space ; space character to clear screen 0446-CD 01 189 ( 18) ST @1(P1) ; store and auto increment by 1 0448-35 190 ( 8) XPAH P1 0449-E4 04 191 ( 10) XRI DISPL/256+2 ; XOR for comparison 044B-98 05 192 (9/11) JZ SC2 ; Is P1_H equal to (Display Start + 2x256)? if yes then finished clearing RAM 044D-E4 04 193 ( 10) XRI DISPL/256+2 ; Restore P1_H 044F-35 194 ( 8) XPAH P1 0450-90 F2 195 ( 11) JMP SC1 0452- 196 0452- 197 ; Fill the third line (using P1) of display with '-' 0452- 198 ; Fill the 2nd to last line (using P2) of display with '-' 0452- 199 SC2: 0452-C4 02 200 ( 10) LDI DISPL/256 0454-35 201 ( 8) XPAH P1 0455-C4 20 202 ( 10) LDI 0x20 0457-31 203 ( 8) XPAL P1 ; P1 contains start address of 2nd display row 0458-C4 03 204 ( 10) LDI DISPL/256+1 045A-37 205 ( 8) XPAH P3 045B-C4 E0 206 ( 10) LDI Shoot_X_pos+0x10 045D-33 207 ( 8) XPAL P3 ; P2 contains start address of 2nd to last display row 045E- 208 SC3: 045E-C4 2D 209 ( 10) LDI Char_Border ; upper and lower boarder character 0460-CD 01 210 ( 18) ST @1(P1) 0462-CF 01 211 ( 18) ST @1(P3) 0464-31 212 ( 8) XPAL P1 0465-E4 30 213 ( 10) XRI 0x30 ; XOR for comparison of 16 characters placed (P1_L started at 0x20) 0467-98 05 214 (9/11) JZ SC4 ; Is P1_L equal to 0x10? if yes then finished border rows 0469-E4 30 215 ( 10) XRI 0x30 ; Restore P1_L 046B-31 216 ( 8) XPAL P1 046C-90 F0 217 ( 11) JMP SC3 046E- 218 046E- 219 ; Draw the protection blocks 046E- 220 SC4: 046E-C4 03 221 ( 10) LDI Block_H ; Top Of Blocks 0470-35 222 ( 8) XPAH P1 0471-C4 61 223 ( 10) LDI Block_L 0473-31 224 ( 8) XPAL P1 0474-C4 03 225 ( 10) LDI 0x03 ; 3 rows of block 0476-CA 13 226 ( 18) ST Count1(P2) 0478- 227 SC5: 0478-C4 03 228 ( 10) LDI 0x03 047A-CA 14 229 ( 18) ST Count2(P2) ; 3 blocks per line 047C- 230 SC6: 047C-C4 23 231 ( 10) LDI Char_Block ; Block # 047E-CD 01 232 ( 18) ST @1(P1) ; 3 characters wide 0480-CD 01 233 ( 18) ST @1(P1) 0482-CD 01 234 ( 18) ST @1(P1) 0484-C5 02 235 ( 18) LD @2(P1) ; 2 spaces 0486-BA 14 236 ( 22) DLD Count2(P2) 0488-9C F2 237 (9/11) JNZ SC6 048A-C5 11 238 ( 18) LD @0x11(P1) ; jump a display line 048C-BA 13 239 ( 22) DLD Count1(P2) 048E-9C E8 240 (9/11) JNZ SC5 0490- 241 0490- 242 ; Draw the Invaders 0490-C2 0E 243 ( 18) LD Inv_row1H(P2) ; Top Of invaders 0492-35 244 ( 8) XPAH P1 0493-C2 0D 245 ( 18) LD Inv_row1L(P2) 0495-31 246 ( 8) XPAL P1 0496-C4 03 247 ( 10) LDI 0x03 ; 3 rows of invaders 0498-CA 13 248 ( 18) ST Count1(P2) 049A- 249 SC7: 049A-C4 04 250 ( 10) LDI 0x04 049C-CA 14 251 ( 18) ST Count2(P2) 049E- 252 SC8: 049E-C4 1C 253 ( 10) LDI Char_InvL 04A0-CD 01 254 ( 18) ST @0x01(P1) 04A2-C4 2F 255 ( 10) LDI Char_InvR 04A4-CD 03 256 ( 18) ST @0x03(P1) 04A6-BA 14 257 ( 22) DLD Count2(P2) 04A8-9C F4 258 (9/11) JNZ SC8 04AA- 259 SC9: 04AA-C5 10 260 ( 18) LD @0x10(P1) ; Move screen position on 20 bytes 04AC-BA 13 261 ( 22) DLD Count1(P2) 04AE-9C EA 262 (9/11) JNZ SC7 ; repeat 04B0- 263 04B0- 264 ; Place the shooter 04B0-C4 D0 265 ( 10) LDI Shoot_X_pos 04B2-DA 00 266 ( 18) OR Shoot_X(P2) ; move shooter to middle of line 04B4-31 267 ( 8) XPAL P1 04B5-C4 03 268 ( 10) LDI Shoot_Y 04B7-35 269 ( 8) XPAH P1 04B8-C4 01 270 ( 10) LDI Char_Shooter 04BA-C9 00 271 ( 18) ST (P1) ; display shooter 04BC- 272 04BC- 273 ; Output Title text 04BC- 274 SC11: 04BC-C4 07 275 ( 10) LDI Title_text/256 ; Get start address of Title text block 04BE-37 276 ( 8) XPAH P3 04BF-C4 CB 277 ( 10) LDI Title_text\256 04C1-33 278 ( 8) XPAL P3 04C2-C4 02 279 ( 10) LDI DISPL/256 04C4-35 280 ( 8) XPAH P1 04C5-C4 10 281 ( 10) LDI Title_line 04C7-31 282 ( 8) XPAL P1 04C8-C4 02 283 ( 10) LDI 0x02 04CA-CA 14 284 ( 18) ST Count2(P2) 04CC- 285 SC12: 04CC-C7 01 286 ( 18) LD @1(P3) 04CE-98 04 287 (9/11) JZ SC13 04D0-CD 01 288 ( 18) ST @1(P1) ; copy it to screen 04D2-90 F8 289 ( 11) JMP SC12 04D4- 290 ;Output score line text 04D4- 291 SC13: 04D4-C4 03 292 ( 10) LDI DISPL/256+1 04D6-35 293 ( 8) XPAH P1 04D7-C4 F0 294 ( 10) LDI Score_line 04D9-31 295 ( 8) XPAL P1 ; Set pointer to last line of display 04DA-BA 14 296 ( 22) DLD Count2(P2) 04DC-9C EE 297 (9/11) JNZ SC12 04DE- 298 04DE- 299 ;================================================ 04DE- 300 ; Initialise variables for each round of the game 04DE- 301 ;================================================ 04DE-C4 00 302 ( 10) LDI 0x00 04E0-CA 18 303 ( 18) ST Sound1(P2) ; Clear any sound events 04E2-CA 03 304 ( 18) ST Bullet_ON(P2) ; Bullet not active 04E4-CA 06 305 ( 18) ST Bomb_ON(P2) ; Bomb not active 04E6-C4 03 306 ( 10) LDI Shoot_Y ; Initial offset for bullet firing 04E8-CA 02 307 ( 18) ST Bullet_Y(P2) 04EA-C4 0E 308 ( 10) LDI 0x0E 04EC-CA 15 309 ( 18) ST Det_Inv(P2) ; Reset invaders on screen flag (any non zero value) 04EE-CA 0B 310 ( 18) ST Rot_loops(P2) ; Number of game loops before invaders are rotated 04F0-CA 0C 311 ( 18) ST Drop_row(P2) ; Number of rotates before invaders drop down a row 04F2-C4 C9 312 ( 10) LDI 0xC9 04F4-CA 01 313 ( 18) ST Bullet_X(P2) ; Initial X position of bullet 04F6- 314 04F6- 315 ; Bomb_X, Bomb_Y, Rot_bytes, Count1, Count2 get initialised elsewhere on first use 04F6- 316 04F6- 317 ;================================================ 04F6- 318 ; MAIN GAME LOOP 04F6- 319 ;================================================ 04F6- 320 ; Fire bullet upwards 04F6- 321 ;================================================ 04F6- 322 FB0: 04F6-C2 03 323 ( 18) LD Bullet_ON(P2) 04F8-98 75 324 (9/11) JZ FB_EXIT 04FA-C2 02 325 ( 18) LD Bullet_Y(P2) ; get display position of Bullet 04FC-35 326 ( 8) XPAH P1 04FD-C2 01 327 ( 18) LD Bullet_X(P2) 04FF-31 328 ( 8) XPAL P1 0500-C1 00 329 ( 18) LD (P1) ; get character from display RAM at bullet position (before bullet gets displayed) 0502-E4 20 330 ( 10) XRI Char_Space ; is it a space (background)? 0504-9C 18 331 (9/11) JNZ FB1 0506-C4 22 332 ( 10) LDI Char_Bullet ; Place bullet character on screen 0508-C9 00 333 ( 18) ST (P1) 050A-C4 20 334 ( 10) LDI Char_Space 050C-C9 10 335 ( 18) ST 0x10(P1) ; replace previous position with a space 050E-C2 01 336 ( 18) LD Bullet_X(P2) ; Get position of bullet 0510-33 337 ( 8) XPAL P3 0511-C2 02 338 ( 18) LD Bullet_Y(P2) 0513-37 339 ( 8) XPAH P3 0514-C7 F0 340 ( 18) LD @-0x10(P3) ; Move position to the next row above 0516-37 341 ( 8) XPAH P3 ; and store 0517-CA 02 342 ( 18) ST Bullet_Y(P2) 0519-33 343 ( 8) XPAL P3 051A-CA 01 344 ( 18) ST Bullet_X(P2) 051C-90 51 345 ( 11) JMP FB_EXIT 051E- 346 FB1: 051E-C1 00 347 ( 18) LD (P1) ; get character from display RAM at bullet position 0520-E4 23 348 ( 10) XRI Char_Block ; is it part of the defences? 0522-98 39 349 (9/11) JZ FB_END 0524-C1 00 350 ( 18) LD (P1) ; get character from display RAM at bullet position 0526-E4 1C 351 ( 10) XRI Char_InvL ; is it an invader? 0528-9C 06 352 (9/11) JNZ FB2 052A-C4 20 353 ( 10) LDI Char_Space 052C-C9 01 354 ( 18) ST 0x01(P1) ; clear one character to right of bullet position 052E-90 0A 355 ( 11) JMP FB22 0530- 356 FB2: 0530-C1 00 357 ( 18) LD (P1) ; get character from display RAM at bullet position 0532-E4 2F 358 ( 10) XRI Char_InvR ; is it an invader? 0534-9C 15 359 (9/11) JNZ FB3 0536-C4 20 360 ( 10) LDI Char_Space 0538-C9 FF 361 ( 18) ST -1(P1) ; clear one character to left of bullet position 053A- 362 FB22: 053A-C4 02 363 ( 10) LDI 0x02 053C-CA 18 364 ( 18) ST Sound1(P2) ; Store invader hit sound event (0x02) 053E-C2 09 365 ( 18) LD Points_L(P2) ; Increment points 0540-02 366 ( 5) CCL 0541-EC 01 367 ( 15) DAI 0x01 ; Decimal add - i.e. BCD counter 0543-CA 09 368 ( 18) ST Points_L(P2) 0545-9C 16 369 (9/11) JNZ FB_END 0547-AA 0A 370 ( 22) ILD Points_H(P2) ; Increment high points (no upper limit check to save space) 0549-90 12 371 ( 11) JMP FB_END 054B- 372 FB3: 054B- 373 ; Uncomment next 3 lines for bullet to get destroyed by collision with a bomb 054B-C1 00 374 ( 18) LD (P1) ; get character from display RAM at bullet position 054D-E4 2A 375 ( 10) XRI Char_Bomb ; is it a bomb? 054F-98 0C 376 (9/11) JZ FB_END 0551- 377 FB4: 0551-C1 00 378 ( 18) LD (P1) 0553-E4 2D 379 ( 10) XRI Char_Border ; Has it reached the top of screen 0555-9C 18 380 (9/11) JNZ FB_EXIT 0557-C4 20 381 ( 10) LDI Char_Space 0559-C9 10 382 ( 18) ST 0x10(P1) ; clear previous bullet position 055B-90 06 383 ( 11) JMP BULLET_OFF 055D- 384 FB_END: 055D-C4 20 385 ( 10) LDI Char_Space 055F-C9 00 386 ( 18) ST (P1) ; clear screen at bullet position 0561-C9 10 387 ( 18) ST 0x10(P1) ; replace previous position with a space 0563- 388 BULLET_OFF: 0563-C4 00 389 ( 10) LDI 0x00 0565-CA 03 390 ( 18) ST Bullet_ON(P2) ; Set bullet to inactive 0567-C4 C7 391 ( 10) LDI 0xC7 0569-CA 01 392 ( 18) ST Bullet_X(P2) ; Set initial offset for bullet firing 056B-C4 03 393 ( 10) LDI Shoot_Y 056D-CA 02 394 ( 18) ST Bullet_Y(P2) 056F- 395 FB_EXIT: 056F- 396 056F- 397 ;================================================ 056F- 398 ; Move the shooter 056F- 399 ;================================================ 056F-C4 03 400 ( 10) LDI Shoot_Y ; Determine where Shooter should be 0571-35 401 ( 8) XPAH P1 0572-C2 00 402 ( 18) LD Shoot_X(P2) 0574-DC D0 403 ( 10) ORI Shoot_X_pos 0576-31 404 ( 8) XPAL P1 0577-C4 01 405 ( 10) LDI Char_Shooter 0579-C9 00 406 ( 18) ST (P1) ; Place the shooter 057B-C4 20 407 ( 10) LDI Char_Space 057D-C9 FF 408 ( 18) ST -1(P1) ; clear to left of shooter to overwrite old position 057F-C2 00 409 ( 18) LD Shoot_X(P2) 0581-E4 0F 410 ( 10) XRI 0x0F 0583-98 04 411 (9/11) JZ DB0 ; If shooter is not at far right then clear to right to overwrite old position 0585-C4 20 412 ( 10) LDI Char_Space 0587-C9 01 413 ( 18) ST 1(P1) 0589- 414 0589- 415 ;================================================ 0589- 416 ; Drop Bomb 0589- 417 ;================================================ 0589- 418 DB0: 0589-C2 06 419 ( 18) LD Bomb_ON(P2) 058B-98 5A 420 (9/11) JZ DB_EXIT 058D-C2 05 421 ( 18) LD Bomb_Y(P2) ; get display position of Bomb 058F-35 422 ( 8) XPAH P1 0590-C2 04 423 ( 18) LD Bomb_X(P2) 0592-31 424 ( 8) XPAL P1 0593-C1 00 425 ( 18) LD (P1) ; get character from display RAM at bomb position (before bomb gets displayed) 0595-E4 20 426 ( 10) XRI Char_Space ; is it a space (background)? 0597-9C 18 427 (9/11) JNZ DB1 0599-C4 2A 428 ( 10) LDI Char_Bomb 059B-C9 00 429 ( 18) ST (P1) ; Place Bomb on screen 059D-C4 20 430 ( 10) LDI Char_Space 059F-C9 F0 431 ( 18) ST -0x10(P1) ; Clear previous position 05A1-C2 04 432 ( 18) LD Bomb_X(P2) 05A3-33 433 ( 8) XPAL P3 05A4-C2 05 434 ( 18) LD Bomb_Y(P2) 05A6-37 435 ( 8) XPAH P3 05A7-C7 10 436 ( 18) LD @0x10(P3) ; Move position of Bomb to the next row 05A9-37 437 ( 8) XPAH P3 05AA-CA 05 438 ( 18) ST Bomb_Y(P2) 05AC-33 439 ( 8) XPAL P3 05AD-CA 04 440 ( 18) ST Bomb_X(P2) 05AF-90 36 441 ( 11) JMP DB_EXIT 05B1- 442 DB1: 05B1-C1 00 443 ( 18) LD (P1) ; get character from display RAM at Bomb position 05B3-E4 23 444 ( 10) XRI Char_Block ; is it part of the defences? 05B5-98 26 445 (9/11) JZ DB_END 05B7- 446 DB3: 05B7-C1 00 447 ( 18) LD (P1) ; get character from display RAM at Bomb position 05B9-E4 01 448 ( 10) XRI Char_Shooter ; is it the shooter? 05BB-9C 0E 449 (9/11) JNZ DB4 05BD-C4 04 450 ( 10) LDI 0x04 05BF-CA 18 451 ( 18) ST Sound1(P2) ; Shooter killed sound event (0x04) 05C1-BA 08 452 ( 22) DLD Lives(P2) ; Decrement number of Lives 05C3-9C 18 453 (9/11) JNZ DB_END ; If lives=0 then game over 05C5-C4 01 454 ( 10) LDI 0x01 05C7-CA 07 455 ( 18) ST Game_over(P2) ; Set game over 05C9-90 18 456 ( 11) JMP BOMB_OFF 05CB- 457 DB4: 05CB- 458 ; Uncomment next 3 lines for bomb to get destroyed by collision with a bullet 05CB-C1 00 459 ( 18) LD (P1) ; get character from display RAM at Bomb position 05CD-E4 22 460 ( 10) XRI Char_Bullet ; is it a bullet? 05CF-98 0C 461 (9/11) JZ DB_END 05D1- 462 DB5: 05D1-C1 00 463 ( 18) LD (P1) 05D3-E4 2D 464 ( 10) XRI Char_Border ; has the bomb reached the bottom of screen? 05D5-9C 10 465 (9/11) JNZ DB_EXIT 05D7-C4 20 466 ( 10) LDI Char_Space 05D9-C9 F0 467 ( 18) ST -0x10(P1) ; Clear previous position 05DB-90 06 468 ( 11) JMP BOMB_OFF 05DD- 469 DB_END: 05DD-C4 20 470 ( 10) LDI Char_Space 05DF-C9 00 471 ( 18) ST (P1) ; Clear Bomb from screen 05E1-C9 F0 472 ( 18) ST -0x10(P1) 05E3- 473 BOMB_OFF: 05E3-C4 00 474 ( 10) LDI 0x00 05E5-CA 06 475 ( 18) ST Bomb_ON(P2) ; Set Bomb to inactive 05E7- 476 05E7- 477 DB_EXIT: 05E7- 478 05E7- 479 ;================================================ 05E7- 480 ; Display Lives and Hits (3 nibbles) 05E7- 481 ;================================================ 05E7-C4 03 482 ( 10) LDI Shoot_Y ; Determine position of score line on display 05E9-35 483 ( 8) XPAH P1 05EA-C4 F6 484 ( 10) LDI Score_line+0x06 05EC-31 485 ( 8) XPAL P1 05ED-C2 08 486 ( 18) LD Lives(P2) ; Get Lives 05EF-F4 30 487 ( 11) ADI 0x30 ; Convert to number character 05F1-CD 09 488 ( 18) ST @0x09(P1) ; Display Lives and move P1 to Points position 05F3- 489 05F3-C2 09 490 ( 18) LD Points_L(P2) ; Get points lower byte (BCD counter) 05F5-D4 0F 491 ( 10) ANI 0x0F ; Mask off lower nibble 05F7-F4 30 492 ( 11) ADI 0x30 ; Convert to number character 05F9-C9 00 493 ( 18) ST (P1) ; Display number and increment pointer 05FB-C2 09 494 ( 18) LD Points_L(P2) ; Reload points lower byte 05FD-D4 F0 495 ( 10) ANI 0xF0 ; Mask off upper nibble 05FF-1C 496 ( 5) SR ; Shift right 4 times 0600-1C 497 ( 5) SR 0601-1C 498 ( 5) SR 0602-1C 499 ( 5) SR 0603-F4 30 500 ( 11) ADI 0x30 ; Convert to number character 0605-C9 FF 501 ( 18) ST -1(P1) ; Display number 0607-C2 0A 502 ( 18) LD Points_H(P2) ; Get high byte 0609-D4 0F 503 ( 10) ANI 0x0F ; Mask lower nibble 060B-F4 30 504 ( 11) ADI 0x30 ; Convert to number character 060D-C9 FE 505 ( 18) ST -2(P1) ; Dislay number 060F- 506 060F- 507 ;================================================ 060F- 508 ; Scan upwards for an invader above shooter X position and enable drop bomb 060F- 509 ;================================================ 060F-C2 06 510 ( 18) LD Bomb_ON(P2) ; if Bomb already dispatched then exit 0611-9C 28 511 (9/11) JNZ SU_EXIT 0613-C2 00 512 ( 18) LD Shoot_X(P2) ; get position of shooter 0615-31 513 ( 8) XPAL P1 0616-C4 03 514 ( 10) LDI Shoot_Y 0618-35 515 ( 8) XPAH P1 0619- 516 SU0: 0619-C1 00 517 ( 18) LD (P1) ; get character from display RAM at scan position 061B-E4 1C 518 ( 10) XRI Char_InvL ; is it an invader? 061D-98 10 519 (9/11) JZ SU1 061F-C1 00 520 ( 18) LD (P1) ; get character from display RAM at scan position 0621-E4 2F 521 ( 10) XRI Char_InvR ; is it an invader 0623-98 0A 522 (9/11) JZ SU1 0625-C1 00 523 ( 18) LD (P1) ; get character from display RAM at scan position 0627-E4 2D 524 ( 10) XRI Char_Border ; has the scan reached the top of the display? If yes, exit as no invader found above the shooter 0629-98 10 525 (9/11) JZ SU_EXIT 062B-C5 F0 526 ( 18) LD @-0x10(P1) ; decrement to the next row above and repeat 062D-90 EA 527 ( 11) JMP SU0 062F- 528 SU1: 062F-C5 20 529 ( 18) LD @0x20(P1) ; move down 2 rows 0631-35 530 ( 8) XPAH P1 ; Align bomb release position with detected invader 0632-CA 05 531 ( 18) ST Bomb_Y(P2) 0634-31 532 ( 8) XPAL P1 0635-CA 04 533 ( 18) ST Bomb_X(P2) 0637-C4 01 534 ( 10) LDI 0x01 0639-CA 06 535 ( 18) ST Bomb_ON(P2) ; Enable bomb drop 063B- 536 SU_EXIT: 063B- 537 063B- 538 ;================================================ 063B- 539 ; Check if game is over, otherwise rotate each row of invaders 063B- 540 ;================================================ 063B-C2 07 541 ( 18) LD Game_over(P2) 063D-9C 04 542 (9/11) JNZ RT1 ; IF not zero then game over so don't move the invaders 063F-BA 0B 543 ( 22) DLD Rot_loops(P2) 0641-98 07 544 (9/11) JZ RT2 ; IF rotation loop counter not zero then don't move the invaders 0643- 545 RT1: 0643-C4 07 37 C4 10 33 3F 546 JS P3,RT10 ; Use JS as a long jump to RT10. There is no return from RT10 064A- 547 RT2: 064A-C2 03 548 ( 18) LD Bullet_ON(P2) ; If the bullet is enabled then blank it while rotating 064C-98 0A 549 (9/11) JZ RT3 064E-C2 02 550 ( 18) LD Bullet_Y(P2) 0650-35 551 ( 8) XPAH P1 0651-C2 01 552 ( 18) LD Bullet_X(P2) 0653-31 553 ( 8) XPAL P1 0654-C4 20 554 ( 10) LDI Char_Space 0656-C9 10 555 ( 18) ST 0x10(P1) 0658- 556 RT3: 0658-C2 06 557 ( 18) LD Bomb_ON(P2) ; If the Bomb is enabled then blank it while rotating 065A-98 0A 558 (9/11) JZ RT4 065C-C2 05 559 ( 18) LD Bomb_Y(P2) 065E-35 560 ( 8) XPAH P1 065F-C2 04 561 ( 18) LD Bomb_X(P2) 0661-31 562 ( 8) XPAL P1 0662-C4 20 563 ( 10) LDI Char_Space 0664-C9 F0 564 ( 18) ST -0x10(P1) 0666- 565 RT4: 0666-C4 0E 566 ( 10) LDI 0x0E 0668-CA 0B 567 ( 18) ST Rot_loops(P2) ; Re-initialise the rotation counter 066A- 568 066A- 569 ; check if any invaders left on screen 066A-C4 00 570 ( 10) LDI 0x00 ; Reset Invaders detected flag (zero means none detected) 066C-CA 15 571 ( 18) ST Det_Inv(P2) 066E-C4 60 572 ( 10) LDI 0x60 ; The complete set of invaders spans 0x60 locations on the display 0670-CA 13 573 ( 18) ST Count1(P2) ; initialise counter 0672-C2 12 574 ( 18) LD Inv_row3H(P2) 0674-35 575 ( 8) XPAH P1 0675-C2 11 576 ( 18) LD Inv_row3L(P2) 0677-DC 0F 577 ( 10) ORI 0x0F ; P1 now points to last position in last row of invaders 0679-31 578 ( 8) XPAL P1 067A- 579 RT5: 067A-C1 00 580 ( 18) LD (P1) ; Determine if any of the 0x60 locations contain an invader character 067C-E4 1C 581 ( 10) XRI Char_InvL 067E-98 06 582 (9/11) JZ RT6 0680-C5 FF 583 ( 18) LD @-1(P1) 0682-E4 2F 584 ( 10) XRI Char_InvR 0684-9C 04 585 (9/11) JNZ RT7 0686- 586 RT6: 0686-C4 01 587 ( 10) LDI 0x01 ; Invaders detected 0688-CA 15 588 ( 18) ST Det_Inv(P2) ; The result in Det_Inv will be 0x01 if any invaders are on screen 068A- 589 RT7: 068A-BA 13 590 ( 22) DLD count1(P2) 068C-9C EC 591 (9/11) JNZ RT5 068E- 592 ; Rotate all rows 068E-C4 08 593 ( 10) LDI 0x08 0690-CA 18 594 ( 18) ST Sound1(P2) ; Store Invaders moving sound event (0x08) 0692-C2 0D 595 ( 18) LD Inv_row1L(P2) ; Each row of invaders has it's own pointer register defining where it is on screen 0694-31 596 ( 8) XPAL P1 0695-C2 0E 597 ( 18) LD Inv_row1H(P2) 0697-35 598 ( 8) XPAH P1 0698-C4 07 37 C4 AD 33 3F 599 JS P3,SFT_L ; Rotate row 1 069F-C2 0F 600 ( 18) LD Inv_row2L(P2) 06A1-31 601 ( 8) XPAL P1 06A2-C2 10 602 ( 18) LD Inv_row2H(P2) 06A4-35 603 ( 8) XPAH P1 06A5-C4 07 37 C4 AD 33 3F 604 JS P3,SFT_L ; Rotate row 2 06AC-C2 11 605 ( 18) LD Inv_row3L(P2) 06AE-31 606 ( 8) XPAL P1 06AF-C2 12 607 ( 18) LD Inv_row3H(P2) 06B1-35 608 ( 8) XPAH P1 06B2-C4 07 37 C4 AD 33 3F 609 JS P3,SFT_L ; Rotate row 3 06B9- 610 06B9- 611 ;================================================ 06B9- 612 ; Move invaders down one row 06B9- 613 ;================================================ 06B9-BA 0C 614 ( 22) DLD Drop_row(P2) ; Decrment loop counter 06BB-9C 54 615 (9/11) JNZ RT10 ; If count is zero then drop invaders down a row, else exit 06BD-C2 0E 616 ( 18) LD Inv_row1H(P2) ; Check if invaders have reached low threshold 06BF-E4 02 617 ( 10) XRI DISPL/256 06C1-9C 0A 618 (9/11) JNZ RT8 06C3-C2 0D 619 ( 18) LD Inv_row1L(P2) 06C5-D4 E0 620 ( 10) ANI 0xE0 06C7-E4 E0 621 ( 10) XRI 0xE0 06C9-9C 02 622 (9/11) JNZ RT8 ; Jump to drop function 06CB-90 44 623 ( 11) JMP RT10 ; If Invader top row is at 0x02Ex then don't drop down any more 06CD- 624 RT8: 06CD-C4 0B 625 ( 10) LDI 0x0B 06CF-CA 0C 626 ( 18) ST Drop_row(P2) ; Reset the drop loop counter 06D1-C4 60 627 ( 10) LDI 0x60 ; The complete set of invaders spans 0x60 locations on the display 06D3-CA 13 628 ( 18) ST Count1(P2) ; initialise counter 06D5-C2 12 629 ( 18) LD Inv_row3H(P2) 06D7-35 630 ( 8) XPAH P1 06D8-C2 11 631 ( 18) LD Inv_row3L(P2) 06DA-DC 0F 632 ( 10) ORI 0x0F ; P1 points to last position in last row of invaders 06DC-31 633 ( 8) XPAL P1 06DD- 634 RT9: 06DD-C1 00 635 ( 18) LD (P1) ; Move display block down one row (0x10 locations) 06DF-C9 10 636 ( 18) ST 0x10(P1) 06E1-C5 FF 637 ( 18) LD @-1(P1) 06E3-BA 13 638 ( 22) DLD count1(P2) 06E5-9C F6 639 (9/11) JNZ RT9 06E7- 640 06E7-C2 0E 641 ( 18) LD Inv_row1H(P2) ; Increment row 1 pointer by 0x10 locations 06E9-37 642 ( 8) XPAH P3 06EA-C2 0D 643 ( 18) LD Inv_row1L(P2) 06EC-33 644 ( 8) XPAL P3 06ED-C7 10 645 ( 18) LD @0x10(P3) 06EF-33 646 ( 8) XPAL P3 06F0-CA 0D 647 ( 18) ST Inv_row1L(P2) 06F2-37 648 ( 8) XPAH P3 06F3-CA 0E 649 ( 18) ST Inv_row1H(P2) 06F5- 650 06F5-C2 10 651 ( 18) LD Inv_row2H(P2) ; Increment row 2 pointer by 0x10 locations 06F7-37 652 ( 8) XPAH P3 06F8-C2 0F 653 ( 18) LD Inv_row2L(P2) 06FA-33 654 ( 8) XPAL P3 06FB-C7 10 655 ( 18) LD @0x10(P3) 06FD-33 656 ( 8) XPAL P3 06FE-CA 0F 657 ( 18) ST Inv_row2L(P2) 0700-37 658 ( 8) XPAH P3 0701-CA 10 659 ( 18) ST Inv_row2H(P2) 0703- 660 0703-C2 12 661 ( 18) LD Inv_row3H(P2) ; Increment row 3 pointer by 0x10 locations 0705-37 662 ( 8) XPAH P3 0706-C2 11 663 ( 18) LD Inv_row3L(P2) 0708-33 664 ( 8) XPAL P3 0709-C7 10 665 ( 18) LD @0x10(P3) 070B-33 666 ( 8) XPAL P3 070C-CA 11 667 ( 18) ST Inv_row3L(P2) 070E-37 668 ( 8) XPAH P3 070F-CA 12 669 ( 18) ST Inv_row3H(P2) 0711- 670 0711- 671 ;================================================ 0711- 672 ; Jump to reload start screen and continue with game if all invaders have been cleared 0711- 673 ;================================================ 0711- 674 RT10: 0711-C2 15 675 ( 18) LD Det_Inv(P2) ; Check if any invaders detected on screen (non zero) 0713-9C 07 676 (9/11) JNZ G_OVER 0715-C4 04 37 C4 3D 33 3F 677 JS P3,INVADE ; JS used as a long jump. No return from INVADE 071C- 678 071C- 679 ;================================================ 071C- 680 ; Check game over flag 071C- 681 ;================================================ 071C- 682 G_OVER: 071C-C2 07 683 ( 18) LD Game_over(P2) ; If flag set then game is over (Lives=0) 071E-98 1A 684 (9/11) JZ KBD ; Otherwise scan the keyboard 0720-C4 00 685 ( 10) LDI 0x00 ; Set Bullet and Bomb off 0722-CA 03 686 ( 18) ST Bullet_ON(P2) 0724-CA 06 687 ( 18) ST Bomb_ON(P2) 0726- 688 0726- 689 ; Output game-_ed text 0726- 690 GO0: 0726-C4 07 691 ( 10) LDI End_text/256 ; Get start address of Game Over text 0728-37 692 ( 8) XPAH P3 0729-C4 EA 693 ( 10) LDI End_text\256 072B-33 694 ( 8) XPAL P3 072C-C4 02 695 ( 10) LDI DISPL/256 072E-35 696 ( 8) XPAH P1 072F-C4 E3 697 ( 10) LDI 0xE3 0731-31 698 ( 8) XPAL P1 0732- 699 GO1: 0732-C7 01 700 ( 18) LD @1(P3) ; copy it to screen 0734-98 04 701 (9/11) JZ KBD 0736-CD 01 702 ( 18) ST @1(P1) 0738-90 F8 703 ( 11) JMP GO1 073A- 704 073A- 705 ;================================================ 073A- 706 ; scan keyboard for 1,2,3, GO, (ABORT disabled to save code space) 073A- 707 ;================================================ 073A- 708 KBD: 073A-C4 0D 709 ( 10) LDI 0x0D ; point to MK14 display/keyboard 073C-37 710 ( 8) XPAH P3 073D-C4 00 711 ( 10) LDI 0x00 073F-33 712 ( 8) XPAL P3 0740-C4 00 713 ( 10) LDI 0x00 0742-CB 00 714 ( 18) ST (P3) ; Set all display segments to off 0744-C2 07 715 ( 18) LD Game_over(P2) ; If Game over flag is set then only test GO and ABORT keys 0746-9C 38 716 (9/11) JNZ TEST_GO 0748- 717 TEST_1: ; Move shooter left 0748-C3 01 718 ( 18) LD 1(P3) ; read keypad 0x0D01 (Key 1) 074A-DC 0F 719 ( 10) ORI 0x0F ; Mask top 4 bits 074C-E4 7F 720 ( 10) XRI 0x7F ; Result will be zero if key pressed 074E-9C 06 721 (9/11) JNZ TEST_2 0750-C2 00 722 ( 18) LD Shoot_X(P2) ; get current shooter position 0752-98 02 723 (9/11) JZ TEST_2 ; If it's already zero then can't move left 0754-BA 00 724 ( 22) DLD Shoot_X(P2) 0756- 725 TEST_2: ; Shoot bullet 0756-C3 02 726 ( 18) LD 2(P3) ; read keypad 0x0D02 (Key 2) 0758-DC 0F 727 ( 10) ORI 0x0F ; Mask top 4 bits 075A-E4 7F 728 ( 10) XRI 0x7F ; Result will be zero if key pressed 075C-9C 12 729 (9/11) JNZ TEST_3 075E-C2 03 730 ( 18) LD Bullet_ON(P2) ; if bullet already in action then ignore key press 0760-9C 0E 731 (9/11) JNZ TEST_3 0762-C4 01 732 ( 10) LDI 0x01 0764-CA 03 733 ( 18) ST Bullet_ON(P2) ; set bullet active 0766-CA 18 734 ( 18) ST Sound1(P2) ; Bullet fired sound stored (0x01) 0768-C2 01 735 ( 18) LD Bullet_X(P2) ; Set bullet release position to Shooter X position 076A-D4 F0 736 ( 10) ANI 0xF0 ; Keep top 4 bits that define the row 076C-E2 00 737 ( 18) XOR Shoot_X(P2) ; add current shooter X position 076E-CA 01 738 ( 18) ST Bullet_X(P2) ; update position 0770- 739 TEST_3: ; Move shooter right 0770-C3 03 740 ( 18) LD 3(P3) ; read keypad 0x0D03 (Key 3) 0772-DC 0F 741 ( 10) ORI 0x0F ; Mask top 4 bits 0774-E4 7F 742 ( 10) XRI 0x7F ; Result will be zero if key pressed 0776-9C 17 743 (9/11) JNZ TEST_ABORT 0778-C2 00 744 ( 18) LD Shoot_X(P2) ; get current shooter position 077A-E4 0F 745 ( 10) XRI 0x0F 077C-98 11 746 (9/11) JZ TEST_ABORT ; If it's already 15 then can't move right 077E-AA 00 747 ( 22) ILD Shoot_X(P2) 0780- 748 TEST_GO: ; New Game 0780-C3 02 749 ( 18) LD 2(P3) ; read keypad 0x0D02 (Key GO) 0782-DC 0F 750 ( 10) ORI 0x0F ; Mask top 4 bits 0784-E4 DF 751 ( 10) XRI 0xDF ; Result will be zero if key pressed 0786-9C 07 752 (9/11) JNZ TEST_ABORT 0788-C4 04 37 C4 1B 33 3F 753 JS P3,START ; Use JS as a long jump to START, to restart the game 078F- 754 TEST_ABORT: ; Abort to Monitor *** commented out to free up some space *** 078F- 755 ; LD 4(P3) ; read keypad 0x0D04 (Key ABORT) 078F- 756 ; ORI 0x0F ; Mask top 4 bits 078F- 757 ; XRI 0xDF ; Result will be zero if key pressed 078F- 758 ; JNZ SND_EV 078F- 759 ; LD Ret_H(P2) ; Reinstate the monitor entry point 078F- 760 ; XPAH P3 078F- 761 ; LD Ret_L(P2) 078F- 762 ; XPAL P3 078F- 763 ; XPPC P3 ; return to the monitor 078F- 764 078F- 765 ; Delay and generate sound event output 078F- 766 SND_EV: 078F-C4 08 767 ( 10) LDI INS8154/256 0791-37 768 ( 8) XPAH P3 0792-C4 00 769 ( 10) LDI INS8154\256 0794-33 770 ( 8) XPAL P3 0795-C2 18 771 ( 18) LD Sound1(P2) ; Get current sound event 0797-DA 19 772 ( 18) OR Sound2(P2) ; extend pulse to 140ms (2 game cycles) 0799-E4 0F 773 ( 10) XRI 0x0F ; invert to provide active low sound event strobes 079B-CB 20 774 ( 18) ST Port_A(P3) ; output on Port A 079D-C2 18 775 ( 18) LD Sound1(P2) ; Get current sound event 079F-CA 19 776 ( 18) ST Sound2(P2) ; store in sound 2 for pulse extension 07A1-C4 00 777 ( 10) LDI 0x00 07A3-CA 18 778 ( 18) ST Sound1(P2) ; Reset sound event 07A5- 779 07A5-8F 80 780 ( 13+) DLY 0x80 ; Main game loop-delay 07A7-C4 04 37 C4 F5 33 3F 781 JS P3,FB0 ; Use JS as a long jump to FB0, the main loop 07AE- 782 07AE- 783 ;================================================ 07AE- 784 ; Subroutine to shift left a row of invaders, twice 07AE- 785 ;================================================ 07AE- 786 SFT_L: 07AE-C4 02 787 ( 10) LDI 0x02 ; Do it twice to avoid half an invader being displayed 07B0-CA 13 788 ( 18) ST Count1(P2) 07B2- 789 SL1: 07B2-C4 0F 790 ( 10) LDI 0x0F ; 15 lcoations rotated left ... 07B4-CA 14 791 ( 18) ST Count2(P2) 07B6-C1 00 792 ( 18) LD (P1) 07B8-01 793 ( 7) XAE ; with the 16th location temporarily stored in the Extension register 07B9- 794 SL2: 07B9-C1 01 795 ( 18) LD 1(P1) ; Do the rotate 07BB-CD 01 796 ( 18) ST @1(P1) 07BD-BA 14 797 ( 22) DLD Count2(P2) 07BF-9C F8 798 (9/11) JNZ SL2 07C1-01 799 ( 7) XAE ; place 16th postion 07C2-C9 00 800 ( 18) ST (P1) 07C4-C5 F1 801 ( 18) LD @-0x0F(P1) 07C6-BA 13 802 ( 22) DLD Count1(P2) 07C8-9C E8 803 (9/11) JNZ SL1 07CA-3F 804 ( 7) RET P3 07CB- 805 07CB- 806 ;================================================ 07CB- 807 ; Lines of Text for writing to display. EOL is 0x00 07CB- 808 ;================================================ 07CB-0D 0B 31 34 20 09 0E 16 01 04 05 12 13 20 16 32 00 809 Title_text .DB 0x0D,0x0B,0x31,0x34,0x20,0x09,0x0E,0x16,0x01,0x04,0x05,0x12,0x13,0x20,0x16,0x32,0x00 ; MK14 INVADERS V2 07DC-0C 09 16 05 13 3A 20 20 08 09 14 13 3A 00 810 Score_text .DB 0x0C,0x09,0x16,0x05,0x13,0x3A,0x20,0x20,0x08,0x09,0x14,0x13,0x3A,0x00 ; LIVES: HITS: 07EA-20 10 12 05 13 13 20 07 0F 20 00 811 End_text .DB 0x20,0x10,0x12,0x05,0x13,0x13,0x20,0x07,0x0F,0x20,0x00 ; PRESS GO 07F5- 812 ; End_text .DB 0x07,0x01,0x0D,0x05,0x20,0x0F,0x16,0x05,0x12,0x20,0x20,0x20,0x20,0x20 ; GAME OVER 07F5- 813 ; Go_text .DB 0x20,0x20,0x10,0x12,0x05,0x13,0x13,0x20,0x07,0x0F,0x20,0x00 ; PRESS GO 07F5- 814