A.N.A.L.O.G. ISSUE 30 / MAY 1985 / PAGE 56
Unnaturally heavy rainfall has caused a landslide in the area of Boulder, Colorado. The debris has created an effective earth dam, which is keeping the water from the storm from flowing away…thereby threatening to flood the town.
Boulder has hired your demolition company to clear away the rubble. Because of the unsure footing on the pile, it has been decided to clear away the rocks with bombs dropped from aircraft flying above.
Before typing anything, look at the listings accompanying this article.
Listing 1 is the BASIC data and data checking routine. This listing is used to create both cassette and disk versions of Boulder Bombers. The data statements are listed in hexadecimal (base 16), so that the program will fit in 16K cassette systems.
Listing 2 is the assembly language source code for the game of Boulder Bombers, created with the OSS MAC/65 assembler. You don’t have to type this listing to play the game! It is included for readers interested in assembly language.
Follow the instructions below to make either a cassette or disk version of Boulder Bombers.
Boulder Bombers is a cooperative/competitive game for one or two players. The number of players is chosen using the SELECT key.
You start the game in a hot air balloon, flying high above the rock-filled canyon. Bombs are dropped by pressing the joystick trigger buttons. When half of the rocks are gone, you will automatically switch to quicker planes. When the entire canyon is cleared of rocks, you advance to the next level, where everything goes faster.
At the start of Boulder Bombers, you are allotted three bombs, shown next to your score at the bottom of the screen. You are penalized bombs whenever you make a miss or fail to attempt a drop on a pass over the canyon.
Extra bombs are awarded at 1000, 3000, 5000, 7000 and, finally, at 9000 points. Up to three bombs will be shown on the screen at a time, but extras earned will be kept in reserve. When you miss with your last bomb, the game ends.
The worth of rocks cleared varies, depending upon their original depth: red-2, yellow-4, blue-6.
Boulder Bombers may be paused by hitting the space bar. Play is resumed by moving either joystick. Commence earth-moving operations!
At twenty-one, Mark Price has been working with computers for five years. He currently attends college in Southern California, where he is working on a degree in computer science. A member of S.B.A.C.E., his interests include programming, speech synthesis and graphics development.
10 REM *** BOULDER BOMBERS *** 20 TRAP 20:? "MAKE CASSETTE (0), OR DISK (1)";:INPUT DSK:IF DSK>1 THEN 20 30 TRAP 40000:DATA 0,1,2,3,4,5,6,7,8,9 ,0,0,0,0,0,0,0,10,11,12,13,14,15 40 DIM DAT$(91),HEX(22):FOR X=0 TO 22: READ N:HEX(X)=N:NEXT X:LINE=990:RESTOR E 1000:TRAP 120:? "CHECKING DATA" 50 LINE=LINE+10:? "LINE:";LINE:READ DA T$:IF LEN(DAT$)<>90 THEN 220 60 DATLIN=PEEK(183)+PEEK(184)*256:IF D ATLIN<>LINE THEN ? "LINE ";LINE;" MISS ING!":END 70 FOR X=1 TO 89 STEP 2:D1=ASC(DAT$(X, X))-48:D2=ASC(DAT$(X+1,X+1))-48:BYTE=H EX(D1)*16+HEX(D2) 80 IF PASS=2 THEN PUT #1,BYTE:NEXT X:R EAD CHKSUM:GOTO 50 90 TOTAL=TOTAL+BYTE:IF TOTAL>999 THEN TOTAL=TOTAL-1000 100 NEXT X:READ CHKSUM:IF TOTAL=CHKSUM THEN 50 110 GOTO 220 120 IF PEEK(195)<>6 THEN 220 130 IF PASS=0 THEN 170 140 IF NOT DSK THEN 160 150 PUT #1,224:PUT #1,2:PUT #1,225:PUT #1,2:PUT #1,0:PUT #1,32:CLOSE #1:END 160 FOR X=1 TO 104:PUT #1,0:NEXT X:CLO SE #1:END 170 IF NOT DSK THEN 200 180 ? "INSERT DISK WITH DOS, PRESS RET URN";:DIM IN$(1):INPUT IN$:OPEN #1,8,0 ,"D:AUTORUN.SYS" 190 PUT #1,255:PUT #1,255:PUT #1,0:PUT #1,32:PUT #1,111:PUT #1,40:GOTO 210 200 ? "READY CASSETTE AND PRESS RETURN ";:OPEN #1,8,128,"C:":RESTORE 230:FOR X=1 TO 40:READ N:PUT #1,N:NEXT X 210 ? :? "WRITING FILE":PASS=2:LINE=99 0:RESTORE 1000:TRAP 120:GOTO 50 220 ? "BAD DATA: LINE ";LINE:END 230 DATA 0,18,216,31,255,31,169,0,141, 47,2,169,60,141,2,211,169,0,141,231,2, 133,14,169,56,141,232,2 240 DATA 133,15,169,0,133,10,169,32,13 3,11,24,96 1000 DATA A26FBDFC279D002CCA10F7A9008D 0ED4A9348D16D0A9288D17D0A9848D18D0A9C4 8D19D0A9008D1AD0A2039D08,415 1010 DATA D0CA10FAA9288D12D0A9848D13D0 A9C88D14D0A9C88D15D0A9308D07D4A93E8D00 D4A9038D1DD0A070B900E099,358 1020 DATA 002CC8D0F7B900E199002DC8D0F7 A92C8D09D4A900A0229912008810FAA02799FC 298810FA204B25A9008D08D2,550 1030 DATA A9038D0FD2A938852DA948852EA9 2C852BA9CC852CA9008D00D48D05D285158D07 D2207925A9AE8D02D4A9258D,475 1040 DATA 03D4A9FF8513A90185148519A900 8518A93E8D00D4A9038512AD1FD02903C901D0 15AD1FD02902F0F9A51A4901,76 1050 DATA 851A1869118D2926D004C902F015 A518D00BAD0AD22901AABDAC258517201D244C CD20AD1FD02901F0F9A90385,502 1060 DATA 13A90085198D00D4A2029D59269D 6326CA10F7A9108D5C268D6626A202A9CD9D5E 269D6826CA10F7A903852985,215 1070 DATA 2AA91185278528A51A0A0A0AA207 A8B99A259D4F26C8CA10F6A9D18D02D4A9258D 03D4A93E8D00D4204B25A903,855 1080 DATA 85178512A90185148532A92A8531 207925A90085188D06D2A92C852BA9CC852C8D 1ED0A908851BA513C9AFF005,394 1090 DATA 38E9048513A201B51FD0034C3423 BD06D0D0034CE7222907D0034CBD22A9008534 B51F38E96729F88533063306,595 1100 DATA 33263418653385339002E634B52B 38E92F4A4A18653385339002E6341869FC8533 A53469298534A000B133F004,765 1110 DATA C9049022C8B133F004C9049019A0 28B133F004C904900FC8B133D0034CE722C904 90034CE7220A8516A9009133,433 1120 DATA A53138E9018531B002C632A9FE85 15BCAA25A51618795926995926A9038516B959 26F023C91A901A38E90A9959,108 1130 DATA 2688C6163014B95926D002A91018 6901995926D0DDC8E616D0D8A9598533A92685 348AF00BA90A186533853390,898 1140 DATA 02E634A000B133D93A26F004B009 9011C8C004D0F0F00AA003B133993A268810F8 BCAA25B95626D527D014F629,78 1150 DATA B529C904B00A187DAA25A8A9CD99 5A26F627F62FB52FC51BD02A8A1869368534B5 1F8533A005A90091338810FB,985 1160 DATA 8A0AA8A9009900D29901D2951FB5 2FD04D2062254C2E238A1869368534B51F8533 A900A00591338810FBF625B5,513 1170 DATA 254A4A4A4A851618751FC9C4B0C5 951F8533A005B9602C91338810F88A0AA8A516 18752395239900D2A9A838E5,241 1180 DATA 169901D2CA30424C9C21B529F0F6 8A18E51AD01BA5143008B52BC94490E6B006B5 2BC9B8B0DEAD0AD2290FF007,561 1190 DATA D0D5BD10D0D0D0B52D186908951F A9009525952FF621A9329523D0BB8D1ED0201D 24A515F012C615C61549F08D,794 1200 DATA 04D24A4A4A4A498F8D05D2AD1FD0 C907F0034C9420A531D007A532D0034C6321AD FC02C921D01AA9008D01D28D,615 1210 DATA 03D28D05D2AD00D3C9FFF0F9A9FF 8DFC028DF202A512290FF0034C9A21A927851D A908851EA96418651D8533A9,948 1220 DATA 2B69008534A000B133F01EAAA028 B133D0178A9133A000989133A53338E9288533 B002C634C61E300FA53338E9,563 1230 DATA 288533B002C634C61E10CDC61D10 B84C9A21A518D035A517C903F00CA9968D06D2 A9248D07D2D023A9008D06D2,456 1240 DATA A9028D07D2A201B52D85338A1869 348534A00FB9502C91338810F8CA10E9E612A5 122517D061A52B186514852B,918 1250 DATA 8D00D08D02D0A51449FE18652C85 2C8D01D08D03D0A517C901D03FA5122902F039 A514851CA201B52D85338A18,443 1260 DATA 69348534A51229040A8516A51C29 101865168616AAA000BD302C9133E8C8C008D0 F5A51C49FE851CA616CA10CD,915 1270 DATA A20FA41388D0FDCAD0F8A9018518 A52BC92CF004C9CCD055A9008D05D28D07D285 158518A201B51FF007B52FD0,504 1280 DATA 03206225B521D003206225CA10EB 207925A61AA5291875296519F025A51449FE85 14A62DA42E862E842DA90385,640 1290 DATA 12A532D00EA531C995B008A90185 17A904851B606868A9088516A2FFA0FFAD1FD0 C907D00A88D0F6CAD0F1C616,269 1300 DATA 10EB4C9420A000B96C2699242AC8 D0F7A091B96B2799232B88D0F760B529F012D6 29B529C903B00A187DAA25A8,578 1310 DATA A900995B2660A900A89900349900 3599003699003788D0F1851F8520852185228D 01D28D03D260B2A5B4B5B0AD,390 1320 DATA AFA39280B2A5B9A1ACB0030D0103 707070462F2670707070707070707044242A04 040404040404040447F32506,97 1330 DATA 0641AE2570707070707070707070 70707044242A040404040404040404462F2670 060641D1258080E2EFF5ECE4,37 1340 DATA E5F28080E2EFEDE2E5F2F3808000 0000627900006D61726B007072696365000000 0000000000302C2139253233,159 1350 DATA 1A00110000000000000000000028 2927281A0000000010000000000000302C2139 253200110000000000000000,690 1360 DATA 0000000000000000000000000000 00000000000000000000010101010101010101 010101010101010101010101,711 1370 DATA 0101010101010101010101010101 01010101018501010101010101010101010101 010101010101010101010101,888 1380 DATA 0101010101010101010101010185 84850101010101010101010101010101010101 010101010101010101010101,328 1390 DATA 0101010101010184858485020202 02020202020202020202020202020202020202 020202020202020202020202,933 1400 DATA 0202848584848502020202020202 02020202020202020202020202020202020202 020202020202020284848584,196 1410 DATA 8485020202020202020202020202 02020202020202020202020202020202020202 020202848485848484850303,461 1420 DATA 0303030303038503030303030303 03030303030303850303030303030303848484 858484848503030303030303,890 1430 DATA 8484850385030303030303030385 03848485030303030303038484848584848484 850303030303848484848484,998 1440 DATA 8503030303030384848484848485 03030303038484848485848484848485030303 848484848484848485030303,750 1450 DATA 0384848484848484848503030384 84848484850000000000000000545454545454 5400A8A8A8A8A8A8A800FCFC,12 1460 DATA FCFCFCFCFC00FFFFFFFFFFFFFFFF FCFCFCFCFCFCFCFC000001033FD3FE80000001 83BFD37E00000080C0FCCB7F,550 1470 DATA 01000080C1FDCB7E003C7EFF00FF FF7E3C1824241818000000A040E0E0E0400000 6C7C387C7C7C381000000000,427
.OPT NOLIST ;*********************** ;* * ;* 'BOULDER BOMBERS' * ;* by * ;* Mark Price * ;* * ;*********************** ; ; ZERO-PAGE VARIABLES ; *= $12 ; CLOCK .DS 1 DELYVAL .DS 1 DIR .DS 1 EXPLODE .DS 1 HOLDIT .DS 1 MASK .DS 1 ONSCR .DS 1 PLAY .DS 1 PLAYERS .DS 1 RKILL .DS 1 TDIR .DS 1 XCOUNT .DS 1 YCOUNT .DS 1 BMBDRP .DS 2 BRUN .DS 2 DRPFREQ .DS 2 DRPRATE .DS 2 FREMEN .DS 2 BOMBS .DS 2 PLYRX .DS 2 PLYRY .DS 2 RCKHIT .DS 2 ROCKS .DS 2 SCRPTR .DS 2 ; ; KEYBOARD VARIABLES ; CH = $02FC CH1 = $02F2 ; PMAREA = $3000 PL0 = PMAREA+1024 PL1 = PL0+256 PL2 = PL1+256 PL3 = PL2+256 ; ROMCH = $E000 ;ROM CHR SET CHARS = $2C00 ;MY CHR SET ; ; SYSTEM EQUATES ; AUDCTL = $D208 AUDC1 = $D201 AUDC2 = $D203 AUDC3 = $D205 AUDC4 = $D207 AUDF1 = $D200 AUDF3 = $D204 AUDF4 = $D206 CHBASE = $D409 COLBAK = $D01A COLPF0 = $D016 COLPF1 = $D017 COLPF2 = $D018 COLPF3 = $D019 COLPM0 = $D012 COLPM1 = $D013 COLPM2 = $D014 COLPM3 = $D015 CONSOL = $D01F DLIST = $D402 DMACTL = $D400 SDMCTL = $022F GRACTL = $D01D HITCLR = $D01E HPOSP0 = $D000 HPOSP1 = $D001 HPOSP2 = $D002 HPOSP3 = $D003 NMIEN = $D40E PL2PF = $D006 PMBASE = $D407 PORTA = $D300 RANDOM = $D20A SIZEP0 = $D008 SKCTL = $D20F TRIG0 = $D010 ; *= $2000 ; INIT LDX #111 ;COPY MY CHARS MYCHRS LDA MYCHARS,X STA CHARS,X DEX BPL MYCHRS LDA #0 ;DISABLE VBI STA NMIEN LDA #$34 ;SET COLORS STA COLPF0 LDA #$28 STA COLPF1 LDA #$84 STA COLPF2 LDA #$C4 STA COLPF3 LDA #0 STA COLBAK LDX #3 ;INIT PLAYERS STWIDTH STA SIZEP0,X DEX BPL STWIDTH LDA #$28 STA COLPM0 LDA #$84 STA COLPM1 LDA #$C8 STA COLPM2 LDA #$C8 STA COLPM3 LDA # >PMAREA STA PMBASE LDA #$3E STA DMACTL LDA #3 STA GRACTL LDY #112 ;INIT CHR SET SETCH1 LDA ROMCH,Y STA CHARS,Y INY BNE SETCH1 SETCH2 LDA ROMCH+256,Y STA CHARS+256,Y INY BNE SETCH2 LDA # >CHARS STA CHBASE LDA #0 ;INIT VARS LDY #SCRPTR+1-CLOCK ZEROVAR STA CLOCK,Y DEY BPL ZEROVAR LDY #$27 ;SET SCREEN DISP CLRTOP STA CANYON,Y DEY BPL CLRTOP JSR SETSCRN LDA #0 ;INIT SOUND STA AUDCTL LDA #3 STA SKCTL LDA #56 ;SET PLAYER STA PLYRY ; LANES LDA #72 STA PLYRY+1 ; RESTART LDA #44 ;SET PLAYER STA PLYRX ; START LDA #204 ; POSITIONS STA PLYRX+1 LDA #0 ;TURN OFF SCREEN STA DMACTL STA AUDC3 ; EXPLOSIONS, STA EXPLODE STA AUDC4 ; AND BKG SOUND JSR PMCLR ;CLEAR PLAYERS LDA # <DLIST1 ;SET TITLE STA DLIST ; SCREEN LDA # >DLIST1 STA DLIST+1 LDA #$FF ;SET GAME SPEED STA DELYVAL ; FOR TITLES LDA #1 ;SET START DIR STA DIR STA PLAY ;SET PLAY FALSE LDA #0 ;PLAYERS NOT STA ONSCR ; ON SCREEN LDA #$3E ;TURN SCREEN STA DMACTL ; BACK ON LDA #3 ; INIT CLOCK STA CLOCK GTCNSL LDA CONSOL ;CHECK CONSOL AND #3 ; SWITCHES CMP #1 ;SELECT PRESSED? BNE CHKSTRT ; NO, TRY START SELECT LDA CONSOL ; YES, WAIT FOR AND #2 ; KEY RELEASE BEQ SELECT LDA PLAYERS ;CHANGE # OF EOR #1 ; PLAYERS STA PLAYERS CLC ADC #$11 ; & SET ON SCREEN STA SCNOPLR BNE MOVET ;(MOVE PLAYERS) CHKSTRT CMP #2 ;IF START THEN BEQ START ; START GAME MOVET LDA ONSCR ;IF ON SCREEN, BNE MOVIT ; THEN MOVE LDA RANDOM ;ELSE, PICK OUT AND #1 ; NEW SHIP TYPE TAX LDA MASKS,X STA MASK ; & SET IT MOVIT JSR MOVEPLR ;MOVE PLAYERS JMP GTCNSL ;DO CHECK AGAIN ; START LDA CONSOL ;WAIT FOR KEY AND #1 ; RELEASE BEQ START LDA #3 ;SET GAME SPEED STA DELYVAL ; TO $FF+$04 LDA #0 ;SET PLAY TRUE STA PLAY STA DMACTL ;TURN OFF SCREEN LDX #2 ;SET SCORES TO ZEROSCR STA SCORE1,X ; ZERO STA SCORE2,X DEX BPL ZEROSCR LDA #$10 STA SCORE1+3 STA SCORE2+3 LDX #2 ;SET BOMBS LEFT LDA #$CD ; TO THREE STBMBC STA BOMB1,X STA BOMB2,X DEX BPL STBMBC LDA #3 STA BOMBS STA BOMBS+1 LDA #$11 ;SET NEXT FREE STA FREMEN ; BOMB AT 1000 STA FREMEN+1 LDA PLAYERS ;SET SECOND ASL A ; PLAYER MESSAGE ASL A ; TO 'PLAYER 2' ASL A ; OR 'COMPUTER' LDX #7 TAY STP2MS LDA P2COMPT,Y STA P2MSG,X INY DEX BPL STP2MS LDA # <DLIST2 ;SET DLIST STA DLIST ; TO GAME LDA # >DLIST2 ; SCREEN STA DLIST+1 LDA #$3E ;TURN ON SCREEN STA DMACTL ; NEWSCRN JSR SETSCRN ;SET CANYON LDA #3 ;SET TYPE TO STA MASK ; BALLOON STA CLOCK ;AND BEGIN CLOCK LDA #1 STA DIR ;DIR = RIGHT STA ROCKS+1 ;ROCKS IN LDA #42 ; CANYON=298 STA ROCKS JSR PMCLR ;CLEAR PLAYERS LDA #0 ;SET PLAYERS ON STA ONSCR ; SCREEN=FALSE STA AUDF4 LDA #44 ;SET START STA PLYRX ; POSITIONS LDA #204 ; OF PLAYERS STA PLYRX+1 STA HITCLR ;CLEAR HITS LDA #8 ;#ROCKS PER BOMB STA RKILL ; (MAX) =8 LDA DELYVAL ;SPEED UP THE CMP #$AF ; GAME JUST A BIT BEQ BMBLOOP ; (UNLESS ALREADY SEC ; AT MAX SPEED) SBC #4 STA DELYVAL ; ; BOMB MOVEMONT, HIT CHECKS, ; SCORE AND HIGHSCORE SET ; BMBLOOP LDX #1 ;GET PLAYER INDEX BMBNLOP LDA BMBDRP,X ;IF BOMB NOT BNE CHKHITS ; DROPPED JMP CHKDRP ; CHECK TRIG CHKHITS LDA PL2PF,X ;BOMB HIT BNE CKHROK ; ANYTHING? JMP LWRBMB ; NO,MOVE BOMB CKHROK AND #7 ;IF HIT ONLY BNE BHITRK ; COLOR 3, IT JMP KILLBMB ; GETS ERASED BHITRK LDA #0 ;SET POINTER STA SCRPTR+1 ; INTO SCREEN LDA BMBDRP,X ; RAM WHERE THE SEC ; ROCK HIT IS. SBC #103 ;1ST, GET BOMB'S AND #$F8 ; Y-POS TRANS- STA SCRPTR ; LATED INTO ASL SCRPTR ; ROW NUMBER ASL SCRPTR ;AND MULTIPLY IT ROL SCRPTR+1 ; BY 40 CLC ADC SCRPTR STA SCRPTR BCC GTP0 INC SCRPTR+1 GTP0 LDA PLYRX,X ;THEN, CHANGE SEC ; X-POS INTO THE SBC #47 ; COLUMN NUMBER LSR A LSR A CLC ;AND ADD IT ON ADC SCRPTR STA SCRPTR BCC GTPA INC SCRPTR+1 GTPA CLC ; ADD SCREEN ADC # <CANYON ; START STA SCRPTR ; ADDRESS LDA SCRPTR+1 ADC # >CANYON STA SCRPTR+1 LDY #0 ;CLEAR INDEX LDA (SCRPTR),Y ; & GET CHAR BEQ GTP1 ;IF IT'S BLANK CMP #4 ; OR ABOVE 4 BCC GOTCHR ; THIS ISN'T IT. GTP1 INY ; TRY AGAIN,ONE LDA (SCRPTR),Y ; RIGHT BEQ GTP2 CMP #4 BCC GOTCHR GTP2 LDY #$28 ;IF WE STILL LDA (SCRPTR),Y ; DON'T GET IT BEQ GTP3 ; TRY 1 DOWN CMP #4 BCC GOTCHR GTP3 INY ;THEN, BOTH AT LDA (SCRPTR),Y ; ONCE BNE GCKRCK JMP LWRBMB ;IF BY THIS GCKRCK CMP #4 ; TIME, WE DONT BCC GOTCHR ; HAVE IT, THEN JMP LWRBMB ; GIVE UP GOTCHR ASL A ;HOLD SCORE= STA HOLDIT ; CHAR * 2 LDA #0 ;ERASE ROCK ON STA (SCRPTR),Y ; SCREEN LDA ROCKS ;LOWER # OF SEC ; ROCKS LEFT SBC #1 STA ROCKS BCS GOT1 DEC ROCKS+1 GOT1 LDA #$FE ;START EXPLOSION STA EXPLODE ; SOUND ; ; ADD ON TO SCORE ; LDY SCRNDX,X ;GET BASE INDEX LDA HOLDIT ; TO SCORES,AND CLC ; ADD TO SCORE ADC SCORE1,Y STA SCORE1,Y LDA #3 ;SET DIGIT # FOR STA HOLDIT ; ROLLOVER PROT. ADDSCR LDA SCORE1,Y ;DONE? BEQ CHKHI ; YES, CHECK HIGH CMP #26 ;DIGIT >10? BCC SCUNDX ; NO, GO RIGHT SEC ;SUB 10 FROM SBC #10 ; THIS DIGIT STA SCORE1,Y DEY ;POINT TO NEXT DEC HOLDIT BMI CHKHI ;ROLLOVER! LEAVE LDA SCORE1,Y ;GET DIGIT BNE SCBRK ;IF BLANK, SET LDA #$10 ; TO ZERO SCBRK CLC ;ADD 1 ADC #1 STA SCORE1,Y ; AND SAVE IT BNE ADDSCR ;CHECK THIS DIGIT SCUNDX INY ;GO RIGHT ONE INC HOLDIT ; DIGIT BNE ADDSCR ; ; CHECK FOR HIGH SCORE ; CHKHI LDA # <SCORE1 STA SCRPTR ;SET POINTER LDA # >SCORE1 ; TO SCORE FOR STA SCRPTR+1 ; PLAYER 1 TXA ;IF IT ISN'T BEQ CHKSCR ; PLAYER 1, THEN LDA #10 ; ADD TO GET CLC ; POINTER FOR ADC SCRPTR ; PLAYER 2 STA SCRPTR BCC CHKSCR INC SCRPTR+1 CHKSCR LDY #0 ;BEGIN AT HI END CHECKSC LDA (SCRPTR),Y CMP HISCOR,Y ;COMPARE 'EM BEQ CKNXDG ;IF SAME,DO NEXT BCS STHISC ;IF PLAYER > SET BCC CHKFRM ;IF HIGH > SKIP CKNXDG INY ;DO NEXT DIGIT CPY #4 ;IF ALL DONE, BNE CHECKSC ; THEN IT'S THE BEQ CHKFRM ; SAME, SKIP ; ; SET HIGH SCORE ; STHISC LDY #3 ;COPY THE SETDIGT LDA (SCRPTR),Y ; NEW HIGH STA HISCOR,Y ; SCORE INTO DEY ; HISCOR BPL SETDIGT ; ; CHECK FOR GETTING EXTRA BOMBS ; CHKFRM LDY SCRNDX,X ;GET SCORE LDA SCORE1-3,Y ; IN THOUSANDS CMP FREMEN,X ;IF NOT FREE BNE STRKHT ; BOMB YET,SKIP. INC BOMBS,X ;ELSE, UP BOMBS LDA BOMBS,X ; BY 1 CMP #4 ;IF BOMBS>=4, BCS UPDTFM ; KEEP IN RESERVE CLC ;IF BOMBS LESS ADC SCRNDX,X ; THAN 4, THEN TAY ; SET EXTRA LDA #$CD ; ON SCREEN STA BOMB1-4,Y UPDTFM INC FREMEN,X ;SET FOR NEXT ; STRKHT INC RCKHIT,X ;IF NEW # OF LDA RCKHIT,X ; ROCKS HIT = CMP RKILL ; MAX,KILL BOMB BNE LWRBMB ; ELSE, LOWER IT KILLBMB TXA ;SET POINTER CLC ; TO BOMB ADC # >PL2 STA SCRPTR+1 LDA BMBDRP,X STA SCRPTR LDY #5 ;AND ERASE IT LDA #0 ERABOMB STA (SCRPTR),Y DEY BPL ERABOMB KILBOMB TXA ;TURN OFF SOUND ASL A ; FOR THIS BOMB TAY LDA #0 STA AUDF1,Y STA AUDC1,Y STA BMBDRP,X ;SET FLAG OFF LDA RCKHIT,X ;IF IT DIDN'T BNE DONXBMB ; HIT ANYTHING, JSR LWRMISS ; LOWER # BOMBS JMP DONXBMB ; & DO NEXT ; ; LOWER THE BOMBS ; LWRBMB TXA CLC ADC # >PL2 ;SET POINTER TO STA SCRPTR+1 ; BOMB LDA BMBDRP,X STA SCRPTR LDA #0 ;ERASE THE BOMB LDY #5 ERBMB STA (SCRPTR),Y DEY BPL ERBMB INC DRPRATE,X ;UP DROP SPEED LDA DRPRATE,X LSR A ;UPDATE POSITION LSR A LSR A LSR A STA HOLDIT CLC ADC BMBDRP,X CMP #196 ;OUT OF RANGE? BCS KILBOMB ; YES, KILL IT STA BMBDRP,X ;ELSE, SET STA SCRPTR ; THE BOMB LDY #5 SETBOMB LDA CHARS+96,Y STA (SCRPTR),Y DEY BPL SETBOMB TXA ;SET Y TO INDEX ASL A ; THE SOUND REGS TAY LDA HOLDIT ;UPDATE SOUND CLC ; OF DROPPING ADC DRPFREQ,X ; BOMB STA DRPFREQ,X STA AUDF1,Y LDA #$A8 SEC SBC HOLDIT STA AUDC1,Y DONXBMB DEX ;RESET INDEX BMI DOPLMV ;IF BOTH NOT JMP BMBNLOP ; DONE, DO NEXT ; ; CHECK & DROP BOMBS ; CHKDRP LDA BOMBS,X ;IF NO BOMBS LEFT BEQ DONXBMB ; THEN DO NEXT TXA ;IF NOT THE CLC ; COMPUTER,CHECK SBC PLAYERS ; TRIGGER BNE CHKTRG ;IT'S PLAYER! LDA DIR ;GOING LEFT? BMI GOINGR ;NO! LDA PLYRX,X ;GET COMPUTER X CMP #$44 ;TOO FAR LEFT? BCC DONXBMB ;YES! BCS TRYDRP ;NO, TRY DROP! GOINGR LDA PLYRX,X ;GET COMP. X CMP #$B8 ;TOO FAR RIGHT? BCS DONXBMB ;YES! TRYDRP LDA RANDOM ;COMPUTER DROPS AND #15 ; A BOMB IF BEQ DROPIT ; RANDOM SAYS TO BNE DONXBMB ;ELSE DO NEXT CHKTRG LDA TRIG0,X ;TRIG PUSHED? BNE DONXBMB ; NO, DO NEXT DROPIT LDA PLYRY,X ;DROP: SET CLC ; BOMB Y TO ADC #8 ; PLAYER Y+8 STA BMBDRP,X LDA #0 ;CLEAR DROP RATE STA DRPRATE,X STA RCKHIT,X ; AND ROCKS HIT INC BRUN,X ;UP BOMBS DROPPED LDA #50 ;SET THE SOUND STA DRPFREQ,X ; FLAG BNE DONXBMB ;AND DO NEXT ; DOPLMV STA HITCLR ;CLEAR HITS JSR MOVEPLR ;MOVE PLAYERS LDA EXPLODE ;EXPLOSION GOING? BEQ CKRSTRT ; NO,SKIP DEC EXPLODE ;UPDATE EXPLOSION DEC EXPLODE ; SOUND EOR #$F0 STA AUDF3 LSR A LSR A LSR A LSR A EOR #$8F STA AUDC3 CKRSTRT LDA CONSOL ;ANY CONSOLE CMP #7 ; BUTTONS PUSHED? BEQ CKNSCR ;IF YES, THEN JMP RESTART ; RE-START CKNSCR LDA ROCKS ;# OF ROCKS LEFT BNE CHKPAUS ; = ZERO? LDA ROCKS+1 ;IF YES, THEN BNE CHKPAUS ; SET UP A JMP NEWSCRN ; NEW SCREEN CHKPAUS LDA CH ;SPACEBAR PRESSED? CMP #33 BNE CKDRRCK ;NO, CONTINUE LDA #0 ;YES, PAUSE GAME STA AUDC1 ;TURN OFF MAIN STA AUDC2 ; SOUNDS STA AUDC3 HLDPTRN LDA PORTA ;WAIT FOR STICK CMP #$FF ; MOVEMENT BEQ HLDPTRN LDA #$FF ;RESET CH FOR STA CH ; ANOTHER PAUSE STA CH1 CKDRRCK LDA CLOCK ;TIME TO DROP AND #15 ; SUSPENDED BEQ DRPROCK ; ROCKS? JMP BMBLOOP ;NO, DO BOMBS DRPROCK LDA #39 ;SET COLUMN TO 39 STA XCOUNT DSTYCNT LDA #8 ;ROW TO 8 STA YCOUNT ;AND SET POINTER LDA # <[CANYON+360] ; TO XCOUNT CLC ; PLUS CANYON ADC XCOUNT ; START STA SCRPTR LDA # >[CANYON+360] ADC #0 STA SCRPTR+1 RK2DRP LDY #0 ;ROCK FALL LOOP: LDA (SCRPTR),Y ;NOTHING THERE BEQ DONXRCK ; THEN TRY NEXT UP TAX ;ELSE HOLD IT LDY #$28 ; & LOOK UNDERNEATH LDA (SCRPTR),Y BNE DONXRCK ;NOT BLANK-DO NEXT TXA ;BLANK, MOVE ROCK STA (SCRPTR),Y ; ABOVE DOWN LDY #0 TYA STA (SCRPTR),Y LDA SCRPTR ; & GO UP ONE SEC ; SO WHOLE COLUMN SBC #$28 ; WON'T FALL AT STA SCRPTR ; ONCE BCS NOVER DEC SCRPTR+1 NOVER DEC YCOUNT ;LAST ROW DONE? BMI DONXCOL ; YES, DO NEXT COL DONXRCK LDA SCRPTR ;GO UP ONE SEC ; ROW SBC #$28 STA SCRPTR BCS NOVER2 DEC SCRPTR+1 NOVER2 DEC YCOUNT ;LAST ROW DONE? BPL RK2DRP ; YES, DO NEXT COL DONXCOL DEC XCOUNT ;LAST COL DONE? BPL DSTYCNT ; NO, DO NEXT JMP BMBLOOP ;DO BOMBS AGAIN ; ; MOVE PLAYER,CHECK FOR LEAVING ; SCREEN, END GAME CHECK, SWITCH ; SHIP TYPES ; MOVEPLR LDA ONSCR ;IF NOT ON BNE ADDCLOK ; SCREEN, SET SOUND LDA MASK ; AND PLAYERS CMP #3 ;BALLOON? BEQ STBLSND ; YES, DO THAT LDA #$96 ;SET PLANE SOUND STA AUDF4 LDA #$24 STA AUDC4 BNE ADDCLOK ; & GOTO CLOCK ADD STBLSND LDA #0 ;SET WIND SOUND STA AUDF4 LDA #2 STA AUDC4 LDX #1 ;SET BALLOON STBLNS LDA PLYRY,X STA SCRPTR TXA CLC ADC # >PL0 STA SCRPTR+1 LDY #15 SETBALN LDA CHARS+80,Y STA (SCRPTR),Y DEY BPL SETBALN DEX BPL STBLNS ADDCLOK INC CLOCK ;ADD TO CLOCK LDA CLOCK ;IF CLOCK AND AND MASK ; MASK<>0 THEN BNE DODELAY ; DON'T MOVE LDA PLYRX ;MOVE THE PLAYERS CLC ;FIRST PLAYER 1 ADC DIR STA PLYRX STA HPOSP0 STA HPOSP2 LDA DIR ;THEN PLAYER 2 EOR #$FE CLC ADC PLYRX+1 STA PLYRX+1 STA HPOSP1 STA HPOSP3 LDA MASK ;IF ON PLANES CMP #1 ; THEN CHECK IF BNE DODELAY ; TIME TO ANIMATE LDA CLOCK ; PROPS AND #2 BEQ DODELAY ;NO, SKIP THIS LDA DIR ;SET TEMP DIR STA TDIR ;(WILL BE KILLED) LDX #1 ANILOOP LDA PLYRY,X ;SET POINTER STA SCRPTR ; TO PLAYER TXA CLC ADC # >PL0 STA SCRPTR+1 LDA CLOCK ;GET IMAGE INDEX AND #4 ; FROM CLOCK ASL A STA HOLDIT ; AND HOLD IT LDA TDIR ;GET DIRECTION AND #$10 ; INDEX FROM CLC ; DIR ADC HOLDIT ;& ADD 'EM TO GET STX HOLDIT ; INDEX. TAX ;SAVE PLAYER # LDY #0 ;SET PLAYER ANISET LDA CHARS+48,X STA (SCRPTR),Y INX INY CPY #8 BNE ANISET LDA TDIR ;REVERSE TDIR EOR #$FE STA TDIR LDX HOLDIT ;GET PLAYER # DEX ; & ANIMATE NEXT BPL ANILOOP DODELAY LDX #15 ;WAIT FOR A DELAY1 LDY DELYVAL ; WHILE TO MAKE DELAY2 DEY ; GAME PLAYABLE BNE DELAY2 DEX BNE DELAY1 LDA #1 ;PLAYERS ARE NOW STA ONSCR ; ON SCREEN LDA PLYRX ;BUT CHECK TO CMP #44 ; SEE IF THEY BEQ OFFSCR ; AREN'T CMP #204 BNE MPGOBAK ;IF ON, RETURN OFFSCR LDA #0 ;ELSE, TURN OFF STA AUDC3 ; EXPLOSIONS AND STA AUDC4 ; BKG SOUND STA EXPLODE STA ONSCR ;SET ONSCR FALSE LDX #1 CHKBR LDA BMBDRP,X ;IF A BOMB IS BEQ CKBRN ; IN THE AIR, AND LDA RCKHIT,X ; IT HASN'T HIT BNE CKBRN ; ANYTHING YET, JSR LWRMISS ; IT'S A MISS CKBRN LDA BRUN,X ;IF NO BOMBS BNE CKNBR ; DROPPED THIS JSR LWRMISS ; PASS,IT'S A MISS CKNBR DEX BPL CHKBR JSR PMCLR ;CLEAR OUT PLAYERS LDX PLAYERS ;IF THE ACTUAL LDA BOMBS ; PLAYERS HAVE CLC ; NO MORE BOMBS, ADC BOMBS,X ; AND WE'RE ON A ADC PLAY ; GAME, END IT BEQ ENDGAME LDA DIR ;REVERSE DIRECTION EOR #$FE STA DIR LDX PLYRY ;CHANGE PLAYER LDY PLYRY+1 ; LANES STX PLYRY+1 STY PLYRY LDA #3 ;RESET CLOCK STA CLOCK LDA ROCKS+1 ;IF HALF OF THE BNE MPGOBAK ; ROCKS ARE GONE LDA ROCKS ; THEN SWITCH CMP #149 ; TO PLANES BCS MPGOBAK ;ELSE RETURN LDA #1 ;SET MOVE RATE STA MASK ; MASK LDA #4 ;PLANE BOMBS GET STA RKILL ; MAX OF 4 ROCKS MPGOBAK RTS ;RETURN ; ENDGAME PLA ;GET RID OF PLA ; RETURN ADDRESS LDA #8 ;DO DELAY SO STA HOLDIT ; THE PLAYERS WAIT0 LDX #$FF ; CAN SEE THE WAIT1 LDY #$FF ; FINAL SCORE WAIT2 LDA CONSOL ; (END DELAY CMP #7 ; EARLY WITH BNE ENDGOBK ; CONSOL KEY) DEY BNE WAIT2 DEX BNE WAIT1 DEC HOLDIT BPL WAIT0 ENDGOBK JMP RESTART ;GO TITLE SCREEN ; ; SET CANYON SCREEN IMAGE ; SETSCRN LDY #0 ;COPY ROCKS & SETSC1 LDA ROCKIMG,Y ; CANYON TO STA CANYON+40,Y ; SCREEN INY BNE SETSC1 LDY #145 SETSC2 LDA ROCKIMG+255,Y STA CANYON+295,Y DEY BNE SETSC2 RTS ;RETURN ; ; LOWER NUMBER OF BOMBS LEFT ; LWRMISS LDA BOMBS,X ;IF ALREADY BEQ LWMGOBK ; ZERO, EXIT DEC BOMBS,X ;LOWER BOMBS LEFT LDA BOMBS,X ;IF AT LEAST 3 CMP #3 ; LEFT, RETURN BCS LWMGOBK CLC ;GET INDEX FOR ADC SCRNDX,X ; SCREEN TO TAY ; ERASE BOMB LDA #0 STA BOMB1-3,Y LWMGOBK RTS ;RETURN ; ; CLEAR PLAYERS,BOMB Y POSITIONS, ; BOMBS DROPPED THIS PASS, AND ; TURN OFF BOMB SOUNDS ; PMCLR LDA #0 TAY PMCLOOP STA PL0,Y ;CLEAR ALL STA PL1,Y ; PLAYERS STA PL2,Y STA PL3,Y DEY BNE PMCLOOP STA BMBDRP ;CLEAR BOMB Y STA BMBDRP+1 ; POSITION STA BRUN ; & BOMBS DROPPED STA BRUN+1 ; THIS PASS STA AUDC1 ;TURN OFF BOMB STA AUDC2 ; FALL SOUNDS RTS ; ; PLAYER 2/COMPUTER MESSAGES ; P2COMPT .SBYTE +$80,"RETUPMOC2 REYALP" ; ; MISC DATA ; SCRNDX .BYTE 3,13 MASKS .BYTE 1,3 ; ; TITLE SCREEN DISPLAY LIST ; DLIST1 .BYTE $70,$70,$70,$46 .WORD GAME .BYTE $70,$70,$70,$70,$70 .BYTE $70,$70,$70,$70,$44 .WORD CANYON+40 .BYTE 4,4,4,4,4,4,4,4,4,$47 .WORD TITLE .BYTE 6,6,$41 .WORD DLIST1 ; ; GAME DISPLAY LIST ; DLIST2 .BYTE $70,$70,$70,$70 .BYTE $70,$70,$70,$70,$70 .BYTE $70,$70,$70,$70,$44 .WORD CANYON+40 .BYTE 4,4,4,4,4,4,4,4,4,$46 .WORD GAME .BYTE $70,6,6,$41 .WORD DLIST2 ; ; TITLES ; TITLE .SBYTE +$80," boulder " .SBYTE +$80," bombers " .SBYTE " by mark price " .SBYTE " PLAYERS: " SCNOPLR .BYTE $11,0,0,0,0,0 ; ; BOTTOM OF GAME SCREEN ; GAME .SBYTE " HIGH: " HISCOR .SBYTE " 0 PLAYER 1 " P2MSG .BYTE 0,0,0,0,0,0,0,0,0,0 SCORE1 .BYTE 0,0,0,0,0 BOMB1 .BYTE 0,0,0,0,0 SCORE2 .BYTE 0,0,0,0,0 BOMB2 .BYTE 0,0,0,0 ; ; DATA FOR CANYON ; ROCKIMG .BYTE 1,1,1,1,1,1,1,1,1,1 .BYTE 1,1,1,1,1,1,1,1,1,1 .BYTE 1,1,1,1,1,1,1,1,1,1 .BYTE 1,1,1,1,1,1,1,1,1,1 .BYTE $85,1,1,1,1,1,1,1,1,1 .BYTE 1,1,1,1,1,1,1,1,1,1 .BYTE 1,1,1,1,1,1,1,1,1,1 .BYTE 1,1,1,1,1,1,1,1,1,$85 .BYTE $84,$85,1,1,1,1,1,1,1,1 .BYTE 1,1,1,1,1,1,1,1,1,1 .BYTE 1,1,1,1,1,1,1,1,1,1 .BYTE 1,1,1,1,1,1,1,1,$84,$85 .BYTE $84,$85,2,2,2,2,2,2,2,2 .BYTE 2,2,2,2,2,2,2,2,2,2 .BYTE 2,2,2,2,2,2,2,2,2,2 .BYTE 2,2,2,2,2,2,2,2,$84,$85 .BYTE $84,$84,$85,2,2,2,2,2,2,2 .BYTE 2,2,2,2,2,2,2,2,2,2 .BYTE 2,2,2,2,2,2,2,2,2,2 .BYTE 2,2,2,2,2,2,2,$84,$84,$85 .BYTE $84,$84,$85,2,2,2,2,2,2,2 .BYTE 2,2,2,2,2,2,2,2,2,2 .BYTE 2,2,2,2,2,2,2,2,2,2 .BYTE 2,2,2,2,2,2,2,$84,$84,$85 .BYTE $84,$84,$84,$85,3 .BYTE 3,3,3,3,3,3,3 .BYTE $85,3,3,3,3,3,3,3,3,3,3,3 .BYTE 3,3,3,$85,3,3,3,3,3,3,3,3 .BYTE $84,$84,$84,$85,$84,$84 .BYTE $84,$85,3,3,3,3 .BYTE 3,3,3,$84,$84,$85 .BYTE 3,$85,3,3,3,3 .BYTE 3,3,3,3,$85,3 .BYTE $84,$84,$85,3,3,3 .BYTE 3,3,3,3,$84,$84 .BYTE $84,$85,$84,$84,$84,$84 .BYTE $85,3,3,3,3,3 .BYTE $84,$84,$84,$84,$84,$84 .BYTE $85,3,3,3,3,3 .BYTE 3,$84,$84,$84,$84,$84 .BYTE $84,$85,3,3,3,3 .BYTE 3,$84,$84,$84,$84,$85 .BYTE $84,$84,$84,$84,$84,$85 .BYTE 3,3,3,$84,$84,$84 .BYTE $84,$84,$84,$84,$84,$85 .BYTE 3,3,3,3,$84,$84 .BYTE $84,$84,$84,$84,$84,$84 .BYTE $85,3,3,3,$84,$84 .BYTE $84,$84,$84,$85 ; ; CHARACTER SET DATA ; MYCHARS .BYTE 0,0,0,0,0,0,0,0 .BYTE 84,84,84,84,84,84,84,0 .BYTE 168,168,168,168,168,168,168,0 .BYTE 252,252,252,252,252,252,252,0 .BYTE 255,255,255,255,255,255,255,255 .BYTE 252,252,252,252,252,252,252,252 .BYTE 0,0,1,3,63,211,254,128 .BYTE 0,0,1,131,191,211,126,0 .BYTE 0,0,128,192,252,203,127,1 .BYTE 0,0,128,193,253,203,126,0 .BYTE 60,126,255,0,255,255,126,60 .BYTE 24,36,36,24,24,0,0,0 .BYTE 160,64,224,224,224,64,0,0 .BYTE 108,124,56,124,124,124,56,16 ; ; ON-SCREEN CANYON ; CANYON = *+$0190 ; *= $02E0 .WORD INIT ;RUN ADDRESS ; .END