A.N.A.L.O.G. ISSUE 28 / MARCH 1985 / PAGE 73
All right, you potential Matt Dillons, here’s your chance to walk down the main street of town … into the legends.
TwoGun is a two-player machine language game. It demonstrates two assembly techniques essential on the Atari home computer: color changing and collision detection. VCOUNT ($D40B) is monitored for the majority of the time, to change the color of the players partway down the screen, much like a display list interrupt. Also, the complexity of collision detection becomes apparent, as most of the vertical blank is devoted to this.
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 TwoGun. The data statements are listed in hexadecimal (base 16), so the program will fit in 16K cassette systems.
Listing 2 is the assembly language source code for the game of TwoGun, created with the Atari Macro assembler. You don’t have to type this listing to play the game! It is included for those readers interested in assembly language. Follow the instructions below to make either a cassette or disk version of TwoGun.
In TwoGun, shooting your opponent scores a point…and causes him to fall down dead. Bullets can be obtained by touching the flashing gun that appears at random. This also causes a cactus (in your color) to appear in the gun’s position.
Bullets are indicated at the top of the screen next to the score. Your cacti slow down your opponent, as well as stop his bullets. Rocks, on the other hand, ricochet bullets at random. They appear when you’ve shot your opponent’s cactus.
Watch for the players to change color. Flashing grey means the player cannot move; flashing green means he is low on ammunition.
Little gravestones, acting like rocks, will appear after every death — to the tune of Taps. Home on the Range runs throughout the game. Shoot ’em up!
My first game creation, TwoGun was built with APX’s editor. The source code is in macro assembly form.
Practice your draw. TwoGun should keep you in top gunfighting shape just in case the villains ride into town.
10 REM *** TWOGUN *** 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 97:PUT #1,0:NEXT X:CLOS E #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,246: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,19,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 2065E420E92220DE22A9D38D3002 A9288D3102A92E8D2F02A9388D07D4A9038D1D D0A9008D0CD0A9188D6F02A9,606 1010 DATA 008D08D2A9068DC602A9AA8DC702 A200BD00E09D0030BD00E19D0031E8D0F1A930 8DF402A248BDCB279D0830CA,927 1020 DATA 10F7A900A27F9580CA10FBA2079D 00D0CA10FAA9008583A223A000A906205CE4A2 12BD8C26BC9F26990038CA10,72 1030 DATA F4A20FA058BD832899003A889900 3A88CA10F2A207A058BDD32799803A99813A99 823A99833ABDDB2799003B99,285 1040 DATA 013B99023B99033B88888888CA10 DBA9038D08D08D09D08D0AD0A9368DC002A9C2 8DC102A9068DC202A9788D00,200 1050 DATA D0A9A88D01D0A9488D02D0A94A8D 2327A9018D6D27A9018589A220ADC40248ADC5 028DC402688DC502A9108585,287 1060 DATA A585D0FCCAD0E720E922A9078581 A9008583A2079D00D2CA10FAAD0AD20901858E A9008D08D08D09D085908594,980 1070 DATA 8D1527858B858A85918592A9028D 00D2A9AA8D03D2A9FF858685878588A213BD78 269DDC38CA10F7A681A51409,639 1080 DATA 079DC002E002B00729F0090A9DC4 02AD1FD02901D0E720E92220DE22AD1FD02901 F0F9A9F28DC802A9BA8DC702,935 1090 DATA A201A91A9DC002BDC72709049DC4 02BDC92795AA95AEA93095AC95B0A90095A495 9A95A295BE95A695A8A90395,761 1100 DATA 9CCA10D18D1ED0A9018583A90085 84858AA580F0FCA584F0034C1C21A9008580A2 01B5AC18691E9596BDC72709,164 1110 DATA 069598A590F012B5A4F004A90495 98B59CC902B004A9CA9598CA10D9A201AD0BD4 8D0AD4D596D00748B5989D12,8 1120 DATA D068CA10F2C97090E6A201BD04D0 3DC02648D5A0F0129010B59AD00CB5A2D008A9 2D95A4A91085886895A0BD04,886 1130 DATA D02908F022A9108588A482BDB826 9914388D1ED0AD0AD22903090118759C959CAD 0AD20940858EA58ED00EAD0A,686 1140 DATA D2D02EA482A900991438F0E7C68E D02120B022F011293FC902F00BC982F0F1A900 991438F0EA8482A9C1991438,488 1150 DATA A9108588CA30034C27224CD321AD 0AD2C9C8B0F9A8B91438600A0A858D0A0A1865 8D601875B84A4A4A20BC2285,18 1160 DATA 8DB5B61869014A4A4A18658DA860 A2F0A9009DFF37CAD0FA60A27FA9009D80399D 003A9D803A9D003B9D803BCA,318 1170 DATA 10EE60A9018580C685A589F03CCE 6D27AD6D27D01AEE2327AD2327C94A9005A901 8D2327AABD6D278D6D27A90A,284 1180 DATA 858CAE2327BD23278D06D2A58529 01D00BC68CA58C300509A08D07D2A583D0034C 7526C6911033A91F8591A592,144 1190 DATA 49108592A59049018590AD0AD209 06CDC702F0F68DC702A5861012A5A425A5D00C A690BDE6268D00D2A908858B,465 1200 DATA A58BF00FC68BA58610F6A58B0980 8D01D2300BA5863007C686290F8D01D2A58730 10C687A687BDF4268D03D2BD,880 1210 DATA E8268D02D2A5883010C688A6888A 09408D05D2BDFD268D04D2AC1527D00AA58A10 22A9018589D02BA9008589CE,45 1220 DATA 1C271013B91C278D1C27B915278D 06D2A910858ACE1527A5852901D009C68AA58A 09A08D07D2A201B59AF012A9,579 1230 DATA 019D08D0D69AD009A94095A2A900 9D08D0B5A2F002D6A2B5A4F008D6A4D004A920 95A2BCBC26A905858FB59C95,630 1240 DATA 9EB59EC904B00C186984990038A9 00959EF00CA988990038B59E38E904959EC8C6 8FD0DDBD0CD03DC026F00BB5,273 1250 DATA AE95AAB5B095AC4C7724B5AA95AE B5AC95B0BC7802B9C62695B21875AAC998B00C 858DB5A815A4D004A58D95AA,582 1260 DATA B9D62695B41875ACC940B00C858D B5A815A4D004A58D95ACB5A8F042BD8402F03D B5B215B4D006854D95A8F031,630 1270 DATA B59CF0F6B59A15A4D027D69CA901 95A6A90095A8A9188586B5AA18690395B6B5AC 95B8B5B20A0A95BAB5B40A95,755 1280 DATA BC4CFD24BD8402D008B5A6D004A9 0195A8BD08D03DC026F06BA90095A6A90F20C6 22A989990038BCBE26B99A00,138 1290 DATA F006A9A095A4D04FA9008D1C27A9 068D1527A9B0999A00A9A899A400F8B5BE1869 01D895BE48BCBA26290F1DB6,427 1300 DATA 26990038684A4A4A4A1DB62699FF 37290FC90190158681BCBE26A90099C002A900 8583A90185844C6726B5AA18,864 1310 DATA 69309D00D08A48BDB2268595BDB4 268594A9B08593B5A4D01BA5928593B5A8F013 BD7802C90FF00CB59CF008BC,923 1320 DATA 7802B9B7278593B5AC186928A8B5 9AF004A9A08593A59318690FAABD1328919488 CAE49310F568AAB5A6D017B5,784 1330 DATA B818691FA8B980393DC426998039 A9009D04D04C6126BD00D03DC026F011A90720 C622A983991438A91085884C,492 1340 DATA 5B26BD00D02904F01DA90A8587AD 0AD2290FA8B9C62619D626F0F2B9C6260A95BA B9D62695BCB5B61875BAC99E,165 1350 DATA B03295B61869309D04D0B5B81869 1FA8B980393DC426998039B5B81875BCC950B0 1295B818691FA8B980391DC2,387 1360 DATA 269980394C6126A90095A695A8CA 30034C06248D1ED0AD1FD02901D004A9018584 4CD1E7B0B2A5B3B300F3F4E1,731 1370 DATA F2F400B4AF00A2A5A7A9AE34772F 67356E6279636F6E7261647461746765293D51 65798D3F4042434445464749,433 1380 DATA 4A4B4C4D3A3A0080105002420113 020D01000201030CFCF3000000000001010100 FFFFFF000000000000000000,460 1390 DATA 01FF000001FF000001FF000A1028 18100C0A09080A0F161040ACADAEAFADAAA6A2 A00A0B0A090B0A0807090C0D,135 1400 DATA 0A0605080A0F100F0A06070A0A00 51607960797900400810400810006C6C514840 5155603C3C3C3C3C35515151,366 1410 DATA 5551486C6C5148405155603C3C3C 3C3C40485155514851353C4048404851515151 5551486C6C5148405155603C,837 1420 DATA 3C3C3C3C40485155514851001010 10102008081808102008081808101010104010 101010200808180810200808,189 1430 DATA 1808101808104030180810301018 08101010104010101010200808180810200808 180810101010800000000000,101 1440 DATA 2030400050607000809000703010 880041CF7FF0F8E000181B1BDBDFD8F8180000 307C72FEFF1F000000FF00FF,572 1450 DATA 0000008080FF80FF800000A0A0FF A0FFA00000A8A8FFA8FFA80000AAAAFFAAFFAA 0000183C18183C7E7E00287C,724 1460 DATA 547C387CBABABA792828680C0000 143E2A3E1C3E5D5D5D9E141416300004147C68 743878BCBAB9782828282C60,293 1470 DATA 04147C69763C78B8B8B878282828 2C6004147C6874387FB8B8B8782828282C6020 283E162E1C1E3D5D9D1E1414,900 1480 DATA 14340620283E966E3C1E1D1D1D1E 141414340620283E162E1CFE1D1D1D1E141414 340604147C6874387EBABABA,524 1490 DATA 7A2828282C6020287E566E5C7E1D 1D1D1E14141434060000000000000000000010 3BBBFF000000143E2A3E1C3E,546 1500 DATA 5D5D5D5D14141436007070704700 38070707070707070707070741D32800000000 000000000000000000000000,888
TITLE 'TWOGUN - A Shootout' SUBTTL 'By Conrad Tatge 84' CONSOL EQU $D01F ;Console switch RANDOM EQU $D20A ;random byte HPOSP0 EQU $D000 ;horizontal M0PF EQU $D000 ;collisions M0PL EQU $D008 P0PF EQU $D004 ORG $80 ;Page zero VBIDO DS 1 ;vertical blank shake WINNER DS 1 ;starts glow LOOT DS 1 ;where loot is ENABLE DS 1 ;VBI allowance DOCPU DS 1 ;game over flag TIMER DS 1 ;inc'ed every VBI SND1 DS 1 ;firing sound SND2 DS 1 ;ricochet SND3 DS 1 ;fwooop DOHOME DS 1 ;flag for little music VOLUME DS 1 ;taps note volume VOL2 DS 1 ;footstep volume SUSTAI DS 1 ;tune volume TEMP DS 1 ;work NOLOOT DS 1 ;countdown COUNT DS 1 ;counter ONOFF DS 1 ;foot switch STEPTM DS 1 ;time for next step STEP DS 1 ;step pointer PICTUR DS 1 ;frame PIC DS 2 ;Page zero PM point CHANGE DS 2 ;where to change color NEWCOL DS 2 ;what color to change DEAD DS 2 ;dead flag AMMOS DS 2 ;bullets AMMOS2 DS 2 ;for displaying PLPF2 DS 2 NOCOL DS 2 ;after a collision NOMOVE DS 2 ;after a shot MISSLF DS 2 ;1 = shooting PRESSF DS 2 ;1 = aiming HORIZ DS 2 ;cowboy position VERT DS 2 HORIZ2 DS 2 ;previously VERT2 DS 2 DIRX DS 2 ;aim direction DIRY DS 2 SHORIZ DS 2 ;shot position SHVERT DS 2 SHDIRX DS 2 ;shot direction SHDIRY DS 2 SCORE DS 2 ;BCD player score ASSERT * < $100 ;page zero! PMHORZ = $30 ;For screen PMVERT = $28 ;offsets PMTITL = PMVERT+$30 ;for title page AMMO = 1 ;character codes CACTUS = 2 ROCK = 3 CHAMMO = 4 ;bullets character GRAVE = 9 ;gravestone HOMES = 74 ;length of song CHRSET EQU $3000 ;memory space PMAREA EQU $3800 DISP EQU PMAREA ;screen memory MIS EQU PMAREA+$180 PL0 EQU PMAREA+$200 PL1 EQU PMAREA+$280 PL2 EQU PMAREA+$300 PL3 EQU PMAREA+$380 PLAREA EQU DISP+20 ;play area ORG $2000 INIT JSR $E465 ;init sound JSR PMCLR ;clear buffer JSR CLDISP ;clear screen LDA #LOW DLIST STA $230 LDA #HIGH DLIST STA $231 LDA #$2E STA $22F ;P/M LDA #HIGH PMAREA STA $D407 LDA #3 STA $D01D ;GRACTL LDA #0 STA $D00C ;SIZEM LDA #$18 STA $26F ;PRIOR LDA #0 STA $D208 ;init LDA #$06 ;light grey STA $2C6 ;rocks LDA #$AA STA $2C7 ;bullets LDX #0 MOVEIT LDA $E000,X ;move ROM set STA CHRSET,X LDA $E100,X STA CHRSET+$100,X INX BNE MOVEIT LDA #HIGH CHRSET STA 756 ;point to new one LDX #$48 ;move 9 characters NEWCHR LDA NEWSET,X ;and copy new STA CHRSET+8,X DEX BPL NEWCHR LDA #0 LDX #$7F CLPZER STA $80,X ;zero variables DEX BPL CLPZER LDX #7 ZHORIZ STA HPOSP0,X ;horizontals DEX BPL ZHORIZ LDA #0 STA ENABLE ;Not yet LDX #HIGH VBLANK ;Set up LDY #LOW VBLANK ;NMI LDA #6 JSR $E45C LDX #18 ;19 characters PRINT LDA CHRS,X LDY CHRPOS,X STA DISP,Y ;put to screen DEX BPL PRINT LDX #$F LDY #PMTITL DOMAN LDA THEMAN,X STA PL0,Y DEY STA PL0,Y DEY DEX BPL DOMAN LDX #$7 LDY #PMTITL DOCAC LDA NEWSET+8,X ;display dudes STA PL1,Y STA PL1+1,Y STA PL1+2,Y STA PL1+3,Y LDA NEWSET+$10,X STA PL2,Y STA PL2+1,Y STA PL2+2,Y STA PL2+3,Y DEY DEY DEY DEY DEX BPL DOCAC LDA #3 STA $D008 ;x4 width STA $D009 STA $D00A LDA #$36 ;red cowboy STA $2C0 LDA #$C2 ;green cactus STA $2C1 LDA #$06 ;grey rocks STA $2C2 LDA #$78 ;horizontals STA $D000 LDA #$A8 STA $D001 LDA #$48 STA $D002 LDA #HOMES ;set it up... STA HOMEON LDA #1 ;and STA DURAT2 LDA #1 ;start the tune... STA DOHOME LDX #32 AGAIN LDA $2C4 ;switch $2C4 & $2C5 PHA LDA $2C5 STA $2C4 PLA STA $2C5 LDA #16 ;quarter of a second STA TIMER TWAITA LDA TIMER BNE TWAITA DEX BNE AGAIN JSR PMCLR ;clear PM title LDA #7 ;glow title STA WINNER START LDA #0 STA ENABLE LDX #7 NOSNDS STA $D200,X DEX BPL NOSNDS LDA RANDOM ORA #1 ;at least one STA NOLOOT ;set up timer LDA #0 STA $D008 STA $D009 sta ONOFF STA PIC STA TAPS STA VOL2 STA VOLUME STA STEPTM STA STEP LDA #2 ;Sound freq' STA $D200 ;AUDF1 LDA #$AA STA $D203 ;sound ctrl 2 LDA #$FF STA SND1 STA SND2 STA SND3 LDX #19 PRESS LDA PRESSM,X ;write message STA DISP+220,X DEX BPL PRESS LDX WINNER DOWN LDA $14 ;Glow ORA #7 STA $2C0,X CPX #2 BCS DOGAME AND #$F0 ORA #$A STA $2C4,X DOGAME LDA CONSOL AND #1 ;START? BNE DOWN JSR PMCLR JSR CLDISP UP LDA CONSOL AND #1 ;Let go yet? BEQ UP LDA #$F2 ;brown STA $2C8 LDA #$BA ;color of loot STA $2C7 LDX #1 ;Set up game SETUP LDA #$1A ;fleshy STA $2C0,X ;COLPM0 LDA TCOLOR,X ORA #4 STA $2C4,X ;COLPF0 LDA THORIZ,X STA HORIZ,X STA HORIZ2,x ;old LDA #$30 STA VERT,X STA VERT2,X ;old LDA #0 STA NOMOVE,X STA DEAD,X STA NOCOL,X STA SCORE,X STA MISSLF,X STA PRESSF,X ;etc... LDA #3 ;give him some! STA AMMOS,X DEX BPL SETUP STA $D01E ;HITCLR LDA #1 ;Now it can STA ENABLE LDA #0 STA DOCPU STA VOLUME ;quiet! * CPU moves the random gun, checks * for it's collision, and does color CPU PROC LDA VBIDO ;wait for VBI BEQ CPU LDA DOCPU ;end game? BEQ :CPU.2 JMP START ;do it again! :CPU.2 LDA #0 STA VBIDO LDX #1 setvp LDA VERT,X CLC ADC #30 ;where to change STA CHANGE,X LDA TCOLOR,X ORA #6 STA NEWCOL,X LDA ONOFF ;alternate BEQ SETVP3 ;natural color LDA NOMOVE,X BEQ SETVP2 LDA #4 STA NEWCOL,X ;darken him! SETVP2 LDA AMMOS,X CMP #2 BCS SETVP3 LDA #$CA ;embarassment STA NEWCOL,X SETVP3 DEX BPL SETVP KERNEL LDX #1 LDA $D40B STA $D40A ;WSYNC CKVP CMP CHANGE,X ;time to change? BNE nochan PHA LDA NEWCOL,X ;get new color STA $D012,X PLA nochan DEX BPL CKVP CMP #$70 BCC KERNEL LDX #1 :CPU1 LDA P0PF,X ;have we run into AND MISHIT,X ;a cactus? PHA ;hold on to CMP PLPF2,X BEQ :CPU1.2 BCC :CPU1.2 LDA DEAD,X ;O.K. if dead... BNE :CPU1.2 LDA NOCOL,X ;or already hit BNE :CPU1.2 LDA #45 ;.75 seconds STA NOMOVE,X ;stop there LDA #$10 ;start boing STA SND3 :CPU1.2 PLA STA PLPF2,X ;remember it LDA P0PF,X AND #8 ;got the loot? BEQ :CPU3 LDA #$10 STA SND3 ;boing LDY LOOT LDA GOTIT,X ;make a cactus STA PLAREA,Y STA $D01E ;HITCLR LDA RANDOM AND #3 ORA #1 CLC ADC AMMOS,X STA AMMOS,X loottm LDA RANDOM ;wait a little ORA #$40 ;not zero STA NOLOOT :CPU3 LDA NOLOOT ;waiting? BNE lootdn LDA RANDOM ;chance it BNE :CPU3.1 LDY LOOT ;erase old one LDA #0 STA DISP+20,y BEQ LOOTTM LOOTDN DEC NOLOOT BNE :CPU3.1 :CPU2 JSR RANDY ;hide loot BEQ DOLOOT AND #$3F ;remove color CMP #CACTUS BEQ DOLOOT CMP #LOOT ;the loot? BEQ :CPU2 LDA #0 ;erase it STA PLAREA,Y BEQ :CPU2 ;now try again DOLOOT STY LOOT ;use this value LDA #AMMO OR $C0 ;PF3 STA PLAREA,Y LDA #$10 STA SND3 ;boing :CPU3.1 DEX BMI RECPU JMP :CPU1 RECPU JMP CPU SUBTTL 'Subroutines' RANDY LDA RANDOM ;find a random CMP #200 ;byte on screen BCS RANDY TAY ;and get its contents LDA PLAREA,Y RTS * Multiply by 20 for screen plotting MULT20 ASL A ;*2 ASL A ;*4 STA TEMP ASL A ;*8 ASL A ;*16 CLC ADC TEMP ;*20 RTS * Finds screen location from a missle PMDISP CLC ;offset is on A ADC SHVERT,X ;get horizontal LSR A LSR A LSR A ;/8 JSR MULT20 ;times 20 STA TEMP ;hold LDA SHORIZ,X CLC ADC #1 LSR A LSR A LSR A ;/8 CLC ADC TEMP ;add on to TAY ;and put in Y RTS CLDISP LDX #240 ;Clear screen LDA #0 CLEAR STA DISP-1,X DEX BNE CLEAR RTS PMCLR LDX #$7F ;clear out P/M LDA #0 ZPLYR STA MIS,X STA PL0,X STA PL1,X STA PL2,X STA PL3,X DEX BPL ZPLYR RTS SUBTTL 'The Vertical Blank' * Vertical BLANK does everything else VBLANK PROC LDA #1 ;VBI call flag STA VBIDO DEC TIMER LDA DOHOME ;Home on the range BEQ CKENAB DEC DURAT2 ;count it down LDA DURAT2 BNE DONOTE INC HOMEON ;next note LDA HOMEON CMP #HOMES ;done yet? BCC NEWDUR LDA #1 ;yes, start again STA HOMEON NEWDUR TAX ;note getter LDA DURAT2,X STA DURAT2 LDA #$A ;start volume STA SUSTAI DONOTE LDX HOMEON LDA HOMEON,X ;play the note STA $D206 LDA TIMER ;decrease volume? AND #1 BNE CKENAB DEC SUSTAI ;a little softer LDA SUSTAI BMI CKENAB ;not too much! ORA #$A0 ;adjust sound STA $D207 CKENAB LDA ENABLE ;should we? BNE :L1 JMP LOOP6 :L1 DEC STEPTM BPL DOSNDS LDA #$1F ;wait for next STA STEPTM LDA STEP ;take a step! EOR #$10 STA STEP LDA ONOFF EOR #1 STA ONOFF NEWAMO LDA RANDOM ORA #6 CMP $2C7 BEQ NEWAMO STA $2C7 ;new ammo color LDA SND1 ;not during a shot! BPL DOSNDS LDA NOMOVE ;if not moving... AND NOMOVE+1 BNE DOSNDS LDX ONOFF LDA FEET,X ;make footsteps STA $D200 LDA #8 STA VOL2 DOSNDS LDA VOL2 BEQ DOSND1 DEC VOL2 LDA SND1 BPL DOSNDS LDA VOL2 ORA #$80 ;decrease volume STA $D201 BMI CKSND2 DOSND1 LDA SND1 ;gunshot BMI CKSND2 DEC SND1 AND #$F STA $D201 CKSND2 LDA SND2 BMI CKSND3 DEC SND2 LDX SND2 LDA CONT2,X STA $D203 LDA FREQ2,X STA $D202 CKSND3 LDA SND3 ;boing BMI CKTAPS DEC SND3 LDX SND3 TXA ;use pointer as volume ORA #$40 STA $D205 ;AUDC3 LDA FREQ3,X STA $D204 ;AUDF3 CKTAPS LDY TAPS BNE DOTAPS LDA VOLUME ;of last note? BPL TAPS2 LDA #1 ;we're done! STA DOHOME BNE LOOP DOTAPS LDA #0 ;reset flag STA DOHOME DEC DURAT ;note length BPL TAPS2 LDA DURAT,Y STA DURAT LDA TAPS,Y ;new note STA $D206 ;AUDF4 LDA #$10 ;new volume STA VOLUME DEC TAPS ;next note TAPS2 LDA TIMER AND #1 BNE LOOP DEC VOLUME LDA VOLUME ORA #$A0 STA $D207 LOOP LDX #1 LOOP1 LDA DEAD,X ;6 feet under? BEQ ALIVE1 LDA #1 ;elongate him STA $D008,X DEC DEAD,X ;and decrement BNE ALIVE1 LDA #$40 STA NOCOL,X LDA #0 ;back to normal STA $D008,X ALIVE1 LDA NOCOL,X BEQ DECMOV DEC NOCOL,X DECMOV LDA NOMOVE,X ;movement? BEQ SHOAMM DEC NOMOVE,X BNE SHOAMM LDA #$20 STA NOCOL,X SHOAMM LDY WHERE2,X ;get posit' LDA #5 STA COUNT LDA AMMOS,X ;replicate STA AMMOS2,X SHOAM1 LDA AMMOS2,X ;ammo left CMP #4 BCS SHOAM2 ;full four? CLC ;partial ADC #CHAMMO OR $80 STA DISP,Y LDA #0 ;no more STA AMMOS2,X BEQ SHOAM3 SHOAM2 LDA #CHAMMO+4 OR $80 STA DISP,Y LDA AMMOS2,X SEC SBC #4 STA AMMOS2,X SHOAM3 INY ;go right one DEC COUNT BNE SHOAM1 LDA $D00C,X AND MISHIT,X ;other guy? BEQ safety LDA HORIZ2,X ;move back! STA HORIZ,X LDA VERT2,X STA VERT,X JMP GETSTK safety LDA HORIZ,X ;safe place! STA HORIZ2,X LDA VERT,X STA VERT2,X GETSTK LDY $278,X ;Y is STICK LDA TDIRX,Y STA DIRX,X ;hold direction CLC ADC HORIZ,X ;new HORIZ CMP #$98 ;off of screen? BCS CKVERT STA TEMP ;no...could use LDA PRESSF,X ;unless aiming ORA NOMOVE,X BNE CKVERT LDA TEMP STA HORIZ,X ;update it CKVERT LDA TDIRY,Y ;same for VERT STA DIRY,X CLC ADC VERT,X CMP #$40 BCS CKPRES STA TEMP LDA PRESSF,X ORA NOMOVE,X BNE CKPRES LDA TEMP STA VERT,X * Joystick fire button code: * test for ammos then * if not strig then set PRESSF * if strig and PRESSF then fire CKPRES LDA PRESSF,X ;already? BEQ CKBUTT LDA $284,X ;letting go? BEQ CKBUTT LDA DIRX,X ORA DIRY,X BNE FIRE ;any direction? NOFLIP STA 77 ;stop attract STA PRESSF,X ;not pressing BEQ CKBUTT FIRE LDA AMMOS,X ;any bullets? BEQ NOFLIP LDA DEAD,X ;if dead ORA NOMOVE,X ;or immobile... BNE CKBUTT ;don't shoot! DEC AMMOS,X ;use a bullet LDA #1 ;he's shooting STA MISSLF,X LDA #0 STA PRESSF,X LDA #$18 ;fire sound STA SND1 LDA HORIZ,X ;make a bullet CLC ADC #3 ;center it STA SHORIZ,X LDA VERT,X STA SHVERT,X LDA DIRX,X ASL A ;4 times as fast ASL A STA SHDIRX,X LDA DIRY,X ASL A ;twice as fast STA SHDIRY,X JMP LOOP2 CKBUTT LDA $284,X ;now button? BNE LOOP2 LDA MISSLF,X ;or shoot? BNE LOOP2 LDA #1 STA PRESSF,X ;pressed... LOOP2 LDA M0PL,X AND MISHIT,X ;player hit? BEQ MOVEM LDA #0 ;stop shooting STA MISSLF,X LDA #$F ;offset JSR PMDISP ;find where LDA #GRAVE OR $80 STA DISP,Y ;put on screen LDY OPPON,X LDA DEAD,Y ;already dead? BEQ KILLEM LDA #$A0 ;slow shooter STA NOMOVE,x BNE MOVEM ;JMP killem LDA #0 ;play taps STA DURAT LDA #6 STA TAPS LDA #$B0 ;kill him STA DEAD,Y LDA #$A8 STA NOMOVE,Y SED LDA SCORE,X CLC ADC #1 ;Give him 1 point CLD STA SCORE,X PHA ;And display his score LDY WHERE,X AND #$F ORA COLSCO,X STA DISP,Y PLA LSR A LSR A LSR A LSR A ORA COLSCO,X STA DISP-1,Y AND #$F CMP #1 ;20 points wins BCC MOVEM STX WINNER LDY OPPON,X LDA #0 ;darken loser STA $2C0,Y LDA #0 STA ENABLE LDA #1 STA DOCPU JMP LOOP4 ;Remember who MOVEM LDA HORIZ,X CLC ADC #PMHORZ ;Small adjust STA HPOSP0,X ;horizontal TXA PHA LDA PLOFF1,X ;Set up PM STA PIC+1 ;pointers for LDA PLOFF2,X ;players STA PIC LDA #$B0 ;hold him still STA PICTUR LDA NOMOVE,X BNE :L2 LDA STEP ;now animate STA PICTUR LDA PRESSF,X ;aiming? BEQ :L2 LDA $278,X CMP #15 ;stick centered? BEQ :L2 LDA AMMOS,X ;or out? BEQ :L2 LDY $278,X LDA PICOFF,Y ;According STA PICTUR ;to STICK0 :L2 LDA VERT,X CLC ADC #PMVERT TAY ;No more Y! LDA DEAD,X BEQ ALIVE LDA #$A0 ;draw dead guy STA PICTUR ALIVE LDA PICTUR CLC ADC #$F ;16 bytes TAX ;X is saved on stack DRAW LDA SHAPE,X ;draw him! STA (PIC),Y DEY DEX CPX PICTUR ;done yet? BPL DRAW PLA TAX ;restore player X LDA MISSLF,X ;Should we BNE MVHORZ ;kill missle? LDA SHVERT,X ;Y not stick CLC ADC #PMVERT-9 TAY LDA MIS,Y AND BITSOF,X ;Out bits STA MIS,Y LDA #0 STA $D004,X ;Zero HPOSM0 JMP LOOP3 MVHORZ LDA M0PF,X ;have we hit AND MISHIT,X ;a cactus? BEQ HORZ1 ;no collision LDA #7 ;offset JSR PMDISP ;figure out where LDA #ROCK OR $80 STA DISP+20,Y ;make rock LDA #$10 ;make boing STA SND3 JMP KILMSL ;kill missle HORZ1: LDA M0PF,X ;have we hit a AND #4 ;PF2 rock? BEQ HORZ3 LDA #10 ;ricochet STA SND2 HORZ2: LDA RANDOM ;new direc' AND #$F TAY LDA TDIRX,Y ORA TDIRY,Y BEQ HORZ2 ;some delta LDA TDIRX,Y ASL A ;a little slower STA SHDIRX,X LDA TDIRY,Y STA SHDIRY,X HORZ3: LDA SHORIZ,X ;update CLC ADC SHDIRX,X CMP #$9E ;off screen? BCS KILMSL STA SHORIZ,X CLC ADC #PMHORZ ;Compensate STA $D004,X LDA SHVERT,X ;Remove old CLC ADC #PMVERT-9 TAY LDA MIS,Y AND BITSOF,X STA MIS,Y LDA SHVERT,X ;Now update CLC ADC SHDIRY,X CMP #$50 ;off screen? BCS KILMSL STA SHVERT,X CLC ADC #PMVERT-9 ;Compensate TAY LDA MIS,Y ORA BITSON,X ;Turn on bit STA MIS,Y JMP LOOP3 KILMSL LDA #0 ;kill this missle STA MISSLF,X STA PRESSF,X LOOP3 DEX ;Next player BMI LOOP4 ;end part of VBI JMP LOOP1 LOOP4 STA $D01E LDA CONSOL AND #1 BNE LOOP6 LDA #1 STA DOCPU LOOP6 JMP $E7D1 ;Exit VBI SUBTTL 'Data Tables' * Various tables PRESSM DB $B0,$B2,$A5,$B3,$B3,0 DB $F3,$F4,$E1,$F2,$F4,0 DB $B4,$AF,0,$A2,$A5,$A7 DB $A9,$AE ;press start... CHRS DB $34,$77,$2f,$67,$35,$6E DB 'byconradtatge' CHRPOS DB 41,61,81,101,121,141 DB 63,64,66,67,68,69,70,71 DB 73,74,75,76,77 ;position PLOFF1 DB HIGH PL0 ;PM pointers DB HIGH PL1 PLOFF2 DB LOW PL0 DB LOW PL1 COLSCO DB $10,$50 ;masks GOTIT DB CACTUS OR $00 ;PF0 DB CACTUS OR $40 ;PF1 WHERE DB 1,19 ;score posit' WHERE2 DB 2,13 ;ammo position OPPON DB 1,0 ;opponent MISHIT DB 2,1 ;collision checks BITSON DB 3,$C ;ORA turn ons BITSOF DB $FC,$F3 ;AND turn offs TDIRX DB 0,0,0,0,0,1,1,1 ;stick DB 0,$FF,$FF,$FF,0 ;deltas DB 0,0,0 TDIRY DB 0,0,0,0,0,1,$FF DB 0,0,1,$FF,0,0 DB 1,$FF,0 FEET DB 10,16 ;footsteps FREQ2 DB 40,24,16,12,10,9,8,10 DB 15,22,16,64 ;ricochet CONT2 DB $AC,$AD,$AE,$AF,$AD,$AA DB $A6,$A2,$A0 FREQ3 DB 10,11,10,9,11,10,8 ;boing DB 7,9,12,13,10,6,5,8,10 DB 15,16,15,10,6,7,10,10 TAPS DB 0 DB $51,$60,$79 ;notes DB $60,$79,$79 DURAT DB 0 DB 64,8,16,64,8,16 ;durations HOMEON DB 0 ;Home, home on the... DB 108,108,81,72,64 ;Oh give DB 81,85,96,60,60,60 DB 60,60,53,81,81,81,85,81,72 DB 108,108,81,72,64 ;where DB 81,85,96,60,60,60 DB 60,60,64,72,81,85,81,72,81 DB 53,60,64,72,64 ;Home, home DB 72,81,81,81,81,85,81,72 DB 108,108,81,72,64 ;where DB 81,85,96,60,60,60 DB 60,60,64,72,81,85,81,72,81 DURAT2 DB 0 DB 16,16,16,16,32 DB 8,8,24,8,16,32 DB 8,8,24,8,16,16,16,16,64 DB 16,16,16,16,32 DB 8,8,24,8,16,32 DB 8,8,24,8,16,24,8,16,64 DB 48,24,8,16,48 DB 16,24,8,16,16,16,16,64 DB 16,16,16,16,32 DB 8,8,24,8,16,32 DB 8,8,24,8,16,16,16,16,128 PICOFF DB 0,0,0,0,0,$20,$30,$40 DB 0,$50,$60,$70,0,$80 DB $90,0 TCOLOR DB $70,$30 ;player colors THORIZ DB $10,$88 ;and positions * Alternate character set NEWSET DB 0,$41,$CF,$7F ;ammo dump DB $F0,$F8,$E0,0 DB $18,$1B,$1B ;cactus DB $DB,$DF,$D8,$F8,$18 DB 0,0,$30,$7C,$72 DB $FE,$FF,$1F ;rock DB 0,0,0,$FF ;empty DB 0,$FF,0,0 DB 0,$80,$80,$FF ;1 DB $80,$FF,$80,0 DB 0,$A0,$A0,$FF ;2 DB $A0,$FF,$A0,0 DB 0,$A8,$A8,$FF ;3 DB $A8,$FF,$A8,0 DB 0,$AA,$AA,$FF ;4 DB $AA,$FF,$AA,0 DB 0,$18,$3C,$18 ;a grave DB $18,$3C,$7E,$7E * Cowboy shape table SHAPE DB $00,$28,$7C,$54 ;+1 DB $7C,$38,$7C,$BA DB $BA,$BA,$79,$28 DB $28,$68,$0C,$00 DB $00,$14,$3E,$2A ;+2 DB $3E,$1C,$3E,$5D DB $5D,$5D,$9E,$14 DB $14,$16,$30,$00 DB $04,$14,$7C,$68 ; DB $74,$38,$78,$BC DB $BA,$B9,$78,$28 DB $28,$28,$2C,$60 DB $04,$14,$7C,$69 ; DB $76,$3C,$78,$B8 DB $B8,$B8,$78,$28 DB $28,$28,$2C,$60 DB $04,$14,$7C,$68 ; DB $74,$38,$7F,$B8 DB $B8,$B8,$78,$28 DB $28,$28,$2C,$60 DB $20,$28,$3E,$16 ; DB $2E,$1C,$1E,$3D DB $5D,$9D,$1E,$14 DB $14,$14,$34,$06 DB $20,$28,$3E,$96 ; DB $6E,$3C,$1E,$1D DB $1D,$1D,$1E,$14 DB $14,$14,$34,$06 THEMAN DB $20,$28,$3E,$16 ; DB $2E,$1C,$FE,$1D DB $1D,$1D,$1E,$14 DB $14,$14,$34,$06 DB $04,$14,$7C,$68 ; DB $74,$38,$7E,$BA DB $BA,$BA,$7A,$28 DB $28,$28,$2C,$60 DB $20,$28,$7E,$56 ; DB $6E,$5C,$7E,$1D DB $1D,$1D,$1E,$14 DB $14,$14,$34,$06 DB 0,0,0,0,0,0,0,0,0,0 ;DEAD DB $10,$3B,$BB,$FF,0,0 DB $00,$14,$3E,$2A ;NOMOVE DB $3E,$1C,$3E,$5D DB $5D,$5D,$5D,$14 DB $14,$14,$36,$00 * The display list is 12 graphic 2's DLIST DB $70,$70,$70 DB $47 DW DISP DB 7,7,7,7,7,7,7,7,7,7,7 DB $41 DW DLIST ;and that's all she wrote! END INIT