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