A.N.A.L.O.G. ISSUE 39 / FEBRUARY 1986 / PAGE 19

Super Pong

16K Cassette or Disk

by Gary S. Domrow

A couple of weeks ago, as I sat around with several other Atari owners, I realized that — to the best of our knowledge — no version of the once-popular Pong was available for the Atari computers. Apparently, everyone thought that Atari was above Pong, or that players were tired of the home computer’s predecessor. Well, being an assembly language aficionado, I set out to change the situation. A couple weeks later, I impressed my friends with this program.

Super Pong should function on any system with at least 16K of memory. Also, the game requires one pair of paddle controllers and at least one willing friend (or enemy). A one-player “practice” option is available, but I won’t claim that it’s as exciting as the two-player games.

Typing it in.

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 Super Pong. The data statements are listed in hexadecimal (base 16), so the program will fit in 16K cassette systems.

Cassette instructions.

  1. Type Listing 1 into your computer, using the BASIC cartridge and verify your typing with Unicheck (see page 11).
  2. Type RUN and press RETURN. The program will begin and ask:
    MAKE CASSETTE (0), OR DISK (1)? Type 0 and press RETURN. The program will begin checking the data statements, printing the line number of each as it goes. It will alert you if it finds any problems. Fix any incorrect lines and re-RUN the program, if necessary, until all errors are eliminated.
  3. When all of your data lines are correct, the computer will beep twice and prompt you to READY CASSETTE AND PRESS RETURN. Now, insert a blank cassette in your recorder, press the RECORD and PLAY buttons simultaneously and hit RETURN. The message WRITING FILE will appear, and the program will create a machine language boot tape version of Super Pong, printing each data line number as it goes. When the READY prompt appears, the game is recorded and ready to play. CSAVE the BASIC program onto a separate tape before continuing.
  4. To play, rewind the tape created by the BASIC program to the beginning. Turn your computer OFF and remove all cartridges. Press the PLAY button on your recorder and turn ON your computer while holding down the START key. If you have a 600 or 800XL computer, you must hold the START and OPTION keys when you turn on the power. The computer will “beep” once. Hit the RETURN key, and Super Pong will load and run automatically.

Disk instructions.

  1. Type Listing 1 into your computer, using the BASIC cartridge and verify your typing with Unicheck (see page 11).
  2. Type RUN and press RETURN. The program will ask:
    MAKE CASSETTE (0), OR DISK (1)? Type 1 and press RETURN. The program will begin checking the data lines, printing the line number of each statement as it goes. It will alert you if it finds any problems. Fix incorrect lines and re-RUN the program, if necessary, until all errors are eliminated.
  3. When all the data lines are correct, you will be prompted to INSERT DISK WITH DOS, PRESS RETURN. Put a disk containing DOS 2.0S into drive 1 and press RETURN. The message WRITING FILE will appear, and the program will create an AUTORUN.SYS file on the disk, displaying each data line number as it goes. When the READY prompt appears, the game is ready to play. Be sure the BASIC program is SAVEd before continuing.
  4. To play the game, insert the disk containing the AUTORUN.SYS file into drive 1. Turn your computer OFF, remove all cartridges and turn the computer back ON. Super Pong will load and run automatically.

The game.

After Super Pong loads, the title screen will appear, with the credits scrolling across the top. To begin, press either of the paddle buttons. The playfield will appear, and one of the available game types will be printed across the top.

To change the game type, slowly rotate first paddle in either direction. Pressing the button again will select the game type, and the beginning score will appear. From this point on, pressing the button of the paddle that will hit the ball first will serve the ball.

One point is scored each time the ball goes past the other player. The first player to get fifteen points is declared the winner. Super Pong may be paused and resumed by pressing any key, and pressing START will restart the game at any time. In all game versions, the ball will speed up after the eighth and sixteenth hits, and will bounce on an angle if hit by the end of the paddle.

Options.

Four different game options are available: Standard Pong, Hockey Pong, Wall Pong, and Practice. The following paragraphs briefly describe each type of game.

Standard — Each player controls one paddle on the screen. The direction of the serve alternates, beginning with the player on the right.

Hockey — Each player controls two paddles on the screen. The serve alternates as in Standard Pong. However, the ball will pass through the centermost paddles if it’s already moving toward that player’s goal.

Wall Pong — In this game, the two players hit the ball against the wall. The players must alternate hits. The paddle of the player who must hit the ball will be brighter until the ball is hit. Also, the player who misses will receive the next serve.

Practice — This is a one-player version of Wall Pong, and is included for practice. Obviously, neither serve nor hits alternate.

I hope that you enjoy the challenge of a good game of Super Pong as much as I enjoyed the challenge of writing the program.

Gary Domrow is a third-year computer science student at the Fort Wayne, Indiana extension of Purdue University. He has worked with Ataris for over four years, learned assembly Janguage two years ago, and now spends much of his free time learning and experimenting with FORTH.

Listing 1.
BASIC listing.

10 REM *** PONG ***
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:RESTORE 1000:TRAP 120:? "CHECKING DATA"
50 LINE=LINE+10:? "LINE:";LINE:READ DAT$:IF LEN(DAT$)<>90 THEN 220
60 DATLIN=PEEK(183)+PEEK(184)*256:IF DATLIN<>LINE THEN ? "LINE ";LINE;" MISSING!":END 
70 FOR X=1 TO 89 STEP 2:D1=ASC(DAT$(X,X))-48:D2=ASC(DAT$(X+1,X+1))-48:BYTE=HEX(D1)*16+HEX(D2)
80 IF PASS=2 THEN PUT #1,BYTE:NEXT X:READ 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,7:PUT #1,40:CLOSE #1:END 
160 FOR X=1 TO 7:PUT #1,0:NEXT X:CLOSE #1:END 
170 IF  NOT DSK THEN 200
180 ? "INSERT DISK WITH DOS, PRESS RETURN";:DIM IN$(1):INPUT IN$:OPEN #1,8,0,"D:AUTORUN.SYS"
190 PUT #1,255:PUT #1,255:PUT #1,0:PUT #1,40:PUT #1,80:PUT #1,49: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=990:RESTORE 1000:TRAP 120:GOTO 50
220 ? "BAD DATA: LINE ";LINE:END 
230 DATA 0,19,216,39,255,39,169,0,234,234,234,169,60,141,2,211,169,0,141,231,2,133,14,169,56,141,232,2
240 DATA 133,15,169,7,133,10,169,40,133,11,24,96
1000 DATA A514C514F0FC60A91B850CA928850DA9008D4402A901850920B62CA2FF9A20E22BA9008D05D485828583858F8D,979
1010 DATA 08D2A93C8D3002A9318D3102A9038D0FD2200028205B2DA9018584A907A22BA0FA205CE420C92DA208BDE7309D,456
1020 DATA C002CA10F7A900858F8585858620432D20E02820392F20AC28A9008584200429A585CD4830F011A586CD4830F0,168
1030 DATA 0620AC284C7328A20CD002A203A000B9E1309D7431E8C8C006D0F4AD7C022D7D02D0F8F0A820282EAD5930F013,242
1040 DATA A205A585202B2F9D7431E8A58520342F9D7431AD5830F013A20EA586202B2F9D7431E8A58620342F9D743160A9,870
1050 DATA 808D05D0A21AA9048587A005A5871D80219D8021E888D0F4A58749048587E07090E860A900A8B9802129FC9980,484
1060 DATA 21C810F520BB292071298D1ED020002820202A20662B20EA298D1ED0A900854DAD4430C926900AC9DCB00620A2,702
1070 DATA 2B4C1829ADF930F00BADF930C901F009C902F011AD4430300CF818A58669018586D84C6929F818A58569018585,661
1080 DATA D8A5894DF83085896020AC28AD0AD2293F1869288D4530A9008D4930A589100CAD4B3020E4298D46304C9A29AD,147
1090 DATA 4B308D4630AD0AD22903C903F0F78D4730AD0AD23009AD473020E4298D4730A97F8D4430D02FAD5830D004A201,712
1100 DATA D015AD5930D003AAF00DADF930F005AACA4CD929A689E8BD7C02D0FBBD7C02F0FB6049FF1869016018AD453069,490
1110 DATA 08AABD7D2129FC9D7D21CAEC4530D0F2BD802109039D8021BD812109039D8121AD44308D04D060486830CA6048,322
1120 DATA 6810C560A58FF015AD463020162A858B38A58FE58B858F1004A900858FAD00D08D5C30AD08D08D5B30AD5C3029,121
1130 DATA 01F00B20B12AA9308583A90E8582AD5C302902F00B20DA2AA9308583A90E8582AD5C30D042A58FD03EAD5B30F0,94
1140 DATA 39ADF930F01CAD5B302903F007ADF930C901F00EAD5B30290CF01FADF930C902D01820032BA9508583A90E8582,996
1150 DATA ADF930F008ADF93049038DF93060AD4530C91CB00AAD473020162A8D473060C96E900AAD4730201B2A8D473060,457
1160 DATA AD473020E4298D473060AD4430C935B00AAD463020162A8D463060C9C8900AAD4630201B2A8D463060AD463020,502
1170 DATA E4298D463060ADF930D013AD5B302903F007AD46303007100EAD46303009AD463020E4298D4630202D2BA90885,431
1180 DATA 8FD04EAD5B302903F006AD42304C3D2BAD433038ED453020E429A8C818AD4730794C308D4730300AC903900FA9,707
1190 DATA 028D473060C9FEB005A9FE8D47306018AD44306D46308D443018AD45306D47308D453060EE4930AD4930CD4A30,153
1200 DATA D017A9008D4930AD463020162AC903F008AD46303004EE463060CE463060ADFC02C9FFF019A9018584A9FF8DFC,269
1210 DATA 02ADFC02C9FFF0F9A9008584A9FF8DFC0260A9AF8580A9318581A000A22BA9AA918018A580691485809002E681,262
1220 DATA CAD0EE60A9748580A9318581A206A900A89180C8D0FBE681CAD0F660A9088D1FD0AD1FD0C906D0034C74E4A584,684
1230 DATA F0034C62E4AD7002A00020D02C858CAD58308D5A30CE5A30AD5A303017AC423020E52CAC5A30BE3E30A48CAD5A,415
1240 DATA 3020142D4C202CA58C8D4230AD7102A00120D02C858CAD59308D5A30CE5A30AD5A30301D186902AC433020E52C,322
1250 DATA AC5A30BE4030A48C18AD5A30690220142D4C542CA58C8D4330A582F002C682A58209A08D01D2A5838D00D2ADF9,292
1260 DATA 30F01EADF9302902AAA9DA9DC0029DC102ADF93049032902AAA9D69DC0029DC1024C62E4A90AA22A9D4631CA10,507
1270 DATA FAA9418D7131A93C8D7231A9318D7331604A38E9073004C91AB004A91AD006C9669002A9656048848AA9008580,271
1280 DATA A92285816820012DA48AA209A9009180C8CA10FA60A888300E18A5806980858090F4E6814C022D60848A48A88A,388
1290 DATA 9900D0A9008580A92285816820012DA209A903A48A9180C8CA10FA60A955A2139D9C319DF834CA10F760A9208D,665
1300 DATA 07D4A92E8D2F02205B2DA9038D1DD0A9118D6F0260A20CA9009D00D0CA10FAA9208581A9008580A204A89180C8,419
1310 DATA D0FBE681CAD0F66020E22B20002820282EA9008D05D4A5880A0A0A0AAAA000BDFC30997431E8C8C010D0F4205B,700
1320 DATA 2D20352D20E028A588C904F00AA99C8D4431A9318D4531A5880AAABDF030858DE8BDF030858E6C8D00AD3F3109,746
1330 DATA 108D3F3120352DA95D8D4031A9308D4131A26EA9088D04D4858F200028AD7C022D7D02F01EC68FA58F100CA907,881
1340 DATA 858FEE4031D003EE4131A58F8D04D4D0DCCAD0D9F0B9A90F8D04D4A9748D4031A9318D4131AD3F3129EF8D3F31,587
1350 DATA 60A900A2279D7431CA10FA60A9018D58308D5930A92E8D3E30A9C88D4030A9008DF930A9018D4B30A9088D4A30,233
1360 DATA A9FF8DF83060A9018D5830A9008D5930A95A8D3E30A9018D4B30A9088D4A30A9008DF93020C32BA9008DF83060,47
1370 DATA A9028D58308D5930A92C8D3E30A99C8D3F30A9C68D4030A9588D4130A9018D4B30A9088D4A30A9008DF93020DD,679
1380 DATA 2EA9FF8DF83060A9018D58308D59308D4B30A9088D4A30A95A8D3E30A95E8D4030A9018DF93020C32BA9008DF8,573
1390 DATA 3060A9B08580A9318581A209A000A9809180A013A902918018A580691485809002E681CA10E618A58069B88580,850
1400 DATA A58169018581A209A000A9809180A013A902918018A580691485809002E681CA10E6604A4A4A4AF00209D06029,680
1410 DATA 0F09D060AD7C022D7D02F0F8A90085888589207B2DA9158D4830A9008DFB308584200028A9018584AD70028DFA,385
1420 DATA 3018A5146903858F200028AD7C022D7D02F062A58FC514D0EFAD7002CDFA30F0DAB011ADFB3030C5EEFB30ADFB,998
1430 DATA 30C903D0C9F01FCEFB30ADFB3010B1C9FDD0BBC688A5881004A9038588202230200F304CC72FE688A588C904D0,656
1440 DATA 04A900858820E42F20FA2FA203A9D69DC002CA10FA207B2D4C4F2FAD7C022D7D02F0F8A900858F60A5880A0A0A,334
1450 DATA 0AAAA000BDFC30998831E8C8C010D0F460A900858FA58F8D05D4200028E68FA58FC910D0F060A90F858FA58F8D,223
1460 DATA 05D4200028C68FA58F10F260A5880A0A0A0AAAA000B97431998831BDFC30997431E8C8C010D0EE600000000000,863
1470 DATA 000000000000000000FDFEFEFFFF00000101020203000000000000000000000000000000000000000000000000,143
1480 DATA 00000030002F002E0027000000000000000000000000000000000000A2B980A7A1B2B980A4AFADB2AFB780AFA6,134
1490 DATA 80B4A8A580B3B5ADADA9B480B3AFA6B4B7A1B2A580A7B2AFB5B000666F7200616E616C6F6700636F6D70757469,200
1500 DATA 6E6700000000000000000000000000000000000000000037292E2E2532D4D4D4D49494940A00332E812EB52E5A,579
1510 DATA 2E000000000000003334212E2421322400302F2E2700000000282F232B253900302F2E2700000000000037212C,713
1520 DATA 2C00302F2E27000000000000000030322123342923250000707070677431074A9C310000000000000000000000,158
1530 REM * 2385 BYTES

Listing 2.
Assembly listing.

;*****************************
;*         P O N G           *
;*     by GARY S. DOMROW     *
;* (c) 1986 ANALOG Computing *
;*****************************
;
;O.S. RAM Z-PAGE
;
BOOT?	=	$09	;O.S. BOOT FLAG
DOSVEC	=	$0C	;INIT. VECTOR
RTCLOK	=	$14	;REAL TIME CLOCK
ATRACT	=	$4D	;ATTRACT FLAG
;
;O.S. RAM
;
COLDST	=	$0244	;COLD START FLAG
SDLSTL	=	$0230	;DISP LIST PTR
PADDL0	=	$0270	;PADDLES
SDMCTL	=	$022F	;DIRECT MEMORY ACCESS CONTROL
GPRIOR	=	$026F	;PRIORITY REGISTER
PCOLR0	=	$02C0	;PLAYER 0 COLOR
PTRIG0	=	$027C	;PADDLE TRIGGER 0
CH	=	$02FC	;CHARACTER PRESSED
;
;O.S. ENTRY POINTS
;
SETVBV	=	$E45C	;SET VERTICAL BLANK VECTOR
XITVBV	=	$E462	;EXIT VERTICAL BLANK
WRMVEC	=	$E474	;WARM START VECTOR
;
;O.S. REGISTER
;
GRACTL	=	$D01D	;PM GRAPHICS CONTROL
PMBASE	=	$D407	;PM BASE REGISTER
RANDOM	=	$D20A	;RANDOM NUMBER GENERATOR
HITCLR	=	$D01E	;COLLISION CLEAR REGISTER
AUDF1	=	$D200	;AUDIO FREQ. 1
AUDC1	=	$D201	;AUDIO CONTROL 1
AUDCTL	=	$D208	;AUDIO CONTROL
SKCTL	=	$D20F	;SERIAL CONTROL
CONSOL	=	$D01F	;CONSOLE SWITCHES
HPOSP0	=	$D000	;HORIZ POSITION PLAYER 0
HPOSM0	=	$D004	;HORIZ POSITION MISSLE 0
M0PL	=	$D008	;MISSILE-PLAYER COLLISIONS
M0PF	=	$D000	;MISSILE-PLAYFIELD COLLISIONA
HSCROL	=	$D404	;HORIZ SCROLL REGISTER
VSCROL	=	$D405	;VERT SCROLL REG
;
;MY Z-PAGE
;
	*=	$80
;
GPNTR	.DS	2	;GENERAL POINTER
VOL	.DS	1	;VOLUME
NOTE	.DS	1	;NOTE
LOCK	.DS	1	;PADDLE MOVE FLG
SCORE1	.DS	1	;PLAYER 1 SCORE
SCORE2	.DS	1	;PLAYER 2 SCORE
COLR	.DS	1	;COLOR
TYPE	.DS	1	;GAME TYPE
SRVDR	.DS	1	;SERVE DIRECTION
TEMP2	.DS	1
TEMPX	.DS	1
TEMPY	.DS	1
JMPVEC	.DS	2	;JUMP VECTOR
COUNT	.DS	1	;COUNTER
;
;EQUATES
;
PMB	=	$20	;PM BASE (HI BYTE)
P1SC	=	5	;PLYR 1 SCORE POSITION
P2SC	=	14	;PLYR 2 SCORE POSITION
MISL	=	PMB*256+384	;MISSILE MEMORY
PLR0	=	MISL+128	;PLAYER 0 MEMORY
PLR1	=	PLR0+128	;PLAYER 1
PLR2	=	PLR1+128	;PLAYER 2
PADCLR	=	$D6	;PADDLE COLOR
MINY	=	$FE	;MINIMUM Y CHANGE
MAXY	=	2	;MAXIMUM Y CHANGE
;
;START OF CODE 
;
	*=	$2800
;
WAIT60	LDA	RTCLOK
MWAIT	CMP	RTCLOK
	BEQ	MWAIT
	RTS
;
START	LDA	# <WRMSTRT	;SET UP THE
	STA	DOSVEC	;RESET VECTOR
	LDA	# >WRMSTRT
	STA	DOSVEC+1
	LDA	#0
	STA	COLDST
	LDA	#1
	STA	BOOT?
	JSR	DLBUILD	;BUILD D LIST
;
;ENTRY FOR RESET
;
WRMSTRT	LDX	#$FF	;RESET STACK
	TXS
	JSR	CLEARALL
	LDA	#0
	STA	VSCROL
	STA	VOL
	STA	NOTE
	STA	COUNT
	STA	AUDCTL
	LDA	# <DLIST	;SET D LIST
	STA	SDLSTL
	LDA	# >DLIST
	STA	SDLSTL+1
	LDA	#3
	STA	SKCTL
	JSR	WAIT60
	JSR	ZPMS
	LDA	#1
	STA	LOCK
	LDA	#7	;INITIALIZE VBI
	LDX	# >VBI
	LDY	# <VBI
	JSR	SETVBV
	JSR	PTITLE	;PRINT TITLE SCREEN
;
;ENTRY POINT FOR NEW GAME
;
STARTGAME	LDX	#8
COLLP	LDA	COLORS,X	;SET PLAYER AND
	STA	PCOLR0,X	;PLAYFIELD COLORS
	DEX
	BPL	COLLP
;
	LDA	#0	;INITIALIZE STUFF:
	STA	COUNT
	STA	SCORE1	; - SCORES
	STA	SCORE2
	JSR	PMINIT	; - P/M GRAPHICS
	JSR	MIDLINE	; - MIDDLE LINE
	JSR	SETUP	; - GAME TYPE
	JSR	NEWSCORE
;
;ENTRY FOR PLAYING ONE GAME
;
GAMELOOP	LDA	#0	;UNLOCK PADDLES
	STA	LOCK
	JSR	PLAYONE	;PLAY ONE BALL
	LDA	SCORE1	;AND CHECK
	CMP	TOPSCR	;FOR A WINNER
	BEQ	TWOLOST
	LDA	SCORE2
	CMP	TOPSCR
	BEQ	ONELOST
	JSR	NEWSCORE	;PRINT NEW SCORE
	JMP	GAMELOOP	;AND JUMP
;
ONELOST	LDX	#12
	BNE	PRINTWIN
;
TWOLOST	LDX	#3
PRINTWIN	LDY	#0	;PRINT 'WINNER'
WINNERLP	LDA	WINNER,Y
	STA	SCORELINE,X
	INX
	INY
	CPY	#6
	BNE	WINNERLP
WAITTRIG	LDA	PTRIG0	;WAIT FOR EITHER
	AND	PTRIG0+1	;TRIGGER BEFORE
	BNE	WAITTRIG	;RESTARTING
	BEQ	STARTGAME
;
;SUBROUTINES OF ALL SHAPES AND SIZES
;
;REPRINT THE SCORE LINE
;
NEWSCORE	JSR	CLNSCRLN	;CLEAN UP
	LDA	NUMPD2
	BEQ	PRSCR2
	LDX	#P1SC
	LDA	SCORE1	;PRINT PLAYER ONE'S SCORE
	JSR	TOPHALF
	STA	SCORELINE,X
	INX
	LDA	SCORE1
	JSR	BOTHALF
	STA	SCORELINE,X
PRSCR2	LDA	NUMPD1
	BEQ	NOMORESCR
	LDX	#P2SC	;AND NOW PLAYER TWO'S
	LDA	SCORE2
	JSR	TOPHALF
	STA	SCORELINE,X
	INX
	LDA	SCORE2
	JSR	BOTHALF
	STA	SCORELINE,X
NOMORESCR	RTS
;
;DRAW MIDDLE LINE, ACTUALLY A MISSILE
;
MIDLINE	LDA	#128	;X-POSITION
	STA	HPOSM0+1
	LDX	#26
	LDA	#4
	STA	COLR
MLLPOUT	LDY	#5	;5 ON, 5 OFF
MLLP1	LDA	COLR
	ORA	MISL,X
	STA	MISL,X
	INX
	DEY
	BNE	MLLP1
	LDA	COLR	;SWITCH ON TO OFF, OFF TO ON
	EOR	#$04
	STA	COLR
	CPX	#112	;END OF SCREEN?
	BCC	MLLPOUT
	RTS
;
;PLAY ONE BALL
;
PLAYONE	LDA	#0	;ERASE LAST BALL
	TAY
CLRBALL	LDA	MISL,Y
	AND	#$FC
	STA	MISL,Y
	INY
	BPL	CLRBALL
	JSR	WAITBUTTON	;WAIT FOR A TRIGGER
	JSR	SERVE	;SERVE THE BALL
POLOOP	STA	HITCLR
	JSR	WAIT60	;PAUSE
	JSR	CHECKCOL	;CHECK COLLISIONS
	JSR	MOVE	;MOVE BALL
	JSR	DRAWBALL	;RE-DRAW BALL
	STA	HITCLR	;CLR COLLISIONS
	LDA	#0	;RESET ATTRACT MODE
	STA	ATRACT
	LDA	BALLX	;CHECK IF BALL IS
	CMP	#38	;OFF THE SCREEN
	BCC	OFFSCREEN
	CMP	#220
	BCS	OFFSCREEN
	JSR	PAUSE	;CHECK FOR KEYPRESS
	JMP	POLOOP	;END LOOP
;
OFFSCREEN	LDA	ALTFL	;ALTERNATING HITS??
	BEQ	CHCKSIDES	;NO
	LDA	ALTFL	;YES, PENALIZE
	CMP	#1	;PLAYER WHO SHOULD
	BEQ	OUTPL1	;HAVE HIT IT
	CMP	#2
	BEQ	OUTPL2
CHCKSIDES	LDA	BALLX	;CHECK WHICH SIDE
	BMI	OUTPL2
OUTPL1	SED		;OUT PLAYER ONE'S SIDE
	CLC		;SO ADD TO SCORE 2
	LDA	SCORE2
	ADC	#1
	STA	SCORE2
	CLD
	JMP	POOUT
;
OUTPL2	SED		;OUT PLAYER TWO'S SIDE
	CLC		;SO ADD TO SCORE 1
	LDA	SCORE1
	ADC	#1
	STA	SCORE1
	CLD
POOUT	LDA	SRVDR	;CHANGE SERVE DIRECTION
	EOR	SRVFL	;ACCORDING TO SRVFL
	STA	SRVDR
	RTS
;
;PUT ONE BALL IN PLAY
;
SERVE	JSR	NEWSCORE	;PRINT NEW SCORE
	LDA	RANDOM	;GET Y POSITION
	AND	#$3F	;BETWEEN 40 & 104
	CLC
	ADC	#40
	STA	BALLY
	LDA	#0	;RESET NUMBER OF HITS
	STA	HITS
	LDA	SRVDR	;SERVE IN RIGHT DIRECTION
	BPL	POS
	LDA	STRSPD
	JSR	NEGATE
	STA	CHNGX
	JMP	FIGCHNGY
;
POS	LDA	STRSPD
	STA	CHNGX
FIGCHNGY	LDA	RANDOM	;GET Y CHANGE
	AND	#$03	;BETWEEN 2 & -2
	CMP	#3
	BEQ	FIGCHNGY
	STA	CHNGY
	LDA	RANDOM	;UP OR DOWN??
	BMI	POSY	;DOWN
	LDA	CHNGY
	JSR	NEGATE	;UP
	STA	CHNGY
POSY	LDA	#127	;STARTING X POSITION
	STA	BALLX
	BNE	DRAWBALL	;DRAW FIRST BALL
;
;WAIT FOR RECEIVER TO PRESS BUTTON
;
WAITBUTTON	LDA	NUMPD1	;IF NO PADDLE 1,
	BNE	PADTHERE1	;WAIT FOR 2
	LDX	#1
	BNE	WAITPRESS
;
PADTHERE1	LDA	NUMPD2	;IF NO PADDLE 2
	BNE	PADTHERE2	;WAIT FOR 1
	TAX
	BEQ	WAITPRESS
;
PADTHERE2	LDA	ALTFL	;IF ALTERNATING,
	BEQ	CHECKDR
	TAX		;WAIT FOR NEXT ONE
	DEX
	JMP	WAITPRESS
;
CHECKDR	LDX	SRVDR	;ELSE, USE SERVE DIRECTION
	INX
WAITPRESS	LDA	PTRIG0,X	;WAIT FOR PRESS
	BNE	WAITPRESS
WAITUPTRG	LDA	PTRIG0,X	;AND RELEASE
	BEQ	WAITUPTRG
	RTS
;
;MAKE ACCUMULATOR NEGATIVE
;
NEGATE	EOR	#$FF
	CLC
	ADC	#1
	RTS
;
;DRAW THE BALL, ACTUALLY A MISSLE
;
DRAWBALL	CLC
	LDA	BALLY
	ADC	#8
	TAX
ERBALL	LDA	MISL-3,X	;ERASE OLD BALL
	AND	#$FC
	STA	MISL-3,X
	DEX
	CPX	BALLY
	BNE	ERBALL
	LDA	MISL,X	;AND DRAW THE
	ORA	#$03	;NEW ONE
	STA	MISL,X
	LDA	MISL+1,X
	ORA	#$03
	STA	MISL+1,X
	LDA	BALLX
	STA	HPOSM0
	RTS
;
;MAKE ACCUMULATOR POSITIVE
;
MAKEPOS	PHA
	PLA
	BMI	NEGATE
	RTS
;
;MAKE ACCUMULATOR NEGATIVE
;
MAKENEG	PHA
	PLA
	BPL	NEGATE
	RTS
;
;CHECK FOR COLLISIONS
;
CHECKCOL	LDA	COUNT	;UNLESS COUNTER NOT ZERO
	BEQ	CONTCC
	LDA	CHNGX
	JSR	MAKEPOS
	STA	TEMPX
	SEC
	LDA	COUNT
	SBC	TEMPX
	STA	COUNT
	BPL	CONTCC
	LDA	#0
	STA	COUNT
CONTCC	LDA	M0PF	;BALL & WALLS
	STA	MISPF
	LDA	M0PL	;BALL & PADDLES
	STA	MISPL
	LDA	MISPF	;CHECK COLOR 1
	AND	#$01
	BEQ	NOHORIZ
	JSR	HORIZCOL	;DO HORIZ COLLISION
	LDA	#$30	;AND PLAY NOTE
	STA	NOTE
	LDA	#14
	STA	VOL
NOHORIZ	LDA	MISPF	;CHECK COLOR 2
	AND	#$02
	BEQ	NOVERT
	JSR	VERTCOL	;DO VERTICAL COLLISON
	LDA	#$30	;AND PLAY NOTE
	STA	NOTE
	LDA	#14
	STA	VOL
NOVERT	LDA	MISPF	;CHECK PLAYER ONLY IF
	BNE	NOPLAYER	;NO WALL COLLISION
	LDA	COUNT	;ONLY IF COUNT OK
	BNE	NOPLAYER
	LDA	MISPL
	BEQ	NOPLAYER
	LDA	ALTFL	;IF ALTERNATING,
	BEQ	CONTPLCOL
	LDA	MISPL	;MAKE SURE IT IS
	AND	#$03	;THE RIGHT PLAYER
	BEQ	PL2COL
	LDA	ALTFL	;PLAYER 1
	CMP	#1
	BEQ	CONTPLCOL
PL2COL	LDA	MISPL	;PLAYER 2
	AND	#$0C
	BEQ	NOPLAYER
	LDA	ALTFL
	CMP	#2
	BNE	NOPLAYER
CONTPLCOL	JSR	PLAYERCOL	;OK TO DO PLAYER COLLISION
	LDA	#$50	;PLAY A NOTE
	STA	NOTE
	LDA	#14
	STA	VOL
	LDA	ALTFL
	BEQ	NOPLAYER
	LDA	ALTFL	;CHANGE ALTERNATION FLAG
	EOR	#$03	;IF IT IS NOT ZERO
	STA	ALTFL
NOPLAYER	RTS
;
;HANDLE HORIZONTAL WALL & BALL COLLISIONS
;
HORIZCOL	LDA	BALLY	;IF AT TOP,
	CMP	#28	;MAKE Y CHANGE
	BCS	NOTSMALL	;POSITIVE
	LDA	CHNGY
	JSR	MAKEPOS
	STA	CHNGY
	RTS
;
NOTSMALL	CMP	#110	;IF AT BOTTOM,
	BCC	NOTBIG	;MAKE Y CHANGE
	LDA	CHNGY	;NEGATIVE
	JSR	MAKENEG
	STA	CHNGY
	RTS
;
NOTBIG	LDA	CHNGY	;OTHERWISE, JUST
	JSR	NEGATE	;NEGATE IT
	STA	CHNGY
	RTS
;
VERTCOL	LDA	BALLX	;IF OFF LEFT SIDE,
	CMP	#53	;MAKE X CHANGE
	BCS	NOTSMALLV	;POSITIVE
	LDA	CHNGX
	JSR	MAKEPOS
	STA	CHNGX
	RTS
;
NOTSMALLV	CMP	#200	;IF OFF RIGHT SIDE,
	BCC	NOTBIGV	;MAKE X CHANGE
	LDA	CHNGX	;NEGATIVE
	JSR	MAKENEG
	STA	CHNGX
	RTS
;
NOTBIGV	LDA	CHNGX	;OTHERWISE, JUST
	JSR	NEGATE	;NEGATE IT
	STA	CHNGX
	RTS
;
;DO PLAYER-BALL COLLISIONS
;
PLAYERCOL	LDA	ALTFL	;IF NOT ALTERNATING
	BNE	NEGATEIT	;SKIP
	LDA	MISPL	;OTHERWISE, NEGATE
	AND	#$03	;ONLY IF IT HIT
	BEQ	PL2	;THE RIGHT PLAYER,
	LDA	CHNGX	;GOING THE RIGHT
	BMI	NEGATEIT	;DIRECTION
	BPL	NONEGATE
;
PL2	LDA	CHNGX
	BMI	NONEGATE
NEGATEIT	LDA	CHNGX	;NEGATE X CHANGE
	JSR	NEGATE	;IF WE GOT HERE
	STA	CHNGX
NONEGATE	JSR	ADJUSTCY	;FIND PADDLE CHANGE
	LDA	#8	;AND SET COUNTER
	STA	COUNT
	BNE	INCHITS
;
;ADJUST Y CHANGE IF BALL HIT EDGE OF PADDLE
;
ADJUSTCY	LDA	MISPL	;FIND WHICH PADDLE
	AND	#$03	;TO COMPARE
	BEQ	NOTPL1
	LDA	YP1
	JMP	ACYCONT
;
NOTPL1	LDA	YP2
ACYCONT	SEC		;SUBTRACT BALL Y
	SBC	BALLY	;POSITION
	JSR	NEGATE	;AND ADJUST
	TAY
	INY
	CLC		;LOOK AT TABLE
	LDA	CHNGY	;TO FIND ADJUSTMENT
	ADC	CHNGTAB,Y	;TO Y CHANGE
	STA	CHNGY
	BMI	CHNGYNEG
	CMP	#MAXY+1	;NOW, MAKE SURE Y CHANGE
	BCC	OUTACY	;IS WITHIN BOUNDS
	LDA	#MAXY	;TOO BIG???
	STA	CHNGY
	RTS
;
CHNGYNEG	CMP	#MINY	;TOO SMALL???
	BCS	OUTACY
	LDA	#MINY
	STA	CHNGY
OUTACY	RTS
;
;ADD CHANGES TO BALL POSITION
;
MOVE	CLC
	LDA	BALLX
	ADC	CHNGX
	STA	BALLX
	CLC
	LDA	BALLY
	ADC	CHNGY
	STA	BALLY
	RTS
;
;ADD TO HIT COUNTER AND SEE IF ABOVE MAXIMUM
;
INCHITS	INC	HITS
	LDA	HITS	;NUMBER OF HITS
	CMP	MAXHIT	;ABOVE MAXIMUM
	BNE	OUTIH	;NO
	LDA	#0	;RESET COUNTER
	STA	HITS
	LDA	CHNGX	;IS X SPEED AT
	JSR	MAKEPOS	;MAXIMUM???
	CMP	#3
	BEQ	OUTIH	;YES
	LDA	CHNGX	;INC IF POSITIVE
	BMI	XCNEG
	INC	CHNGX
OUTIH	RTS
;
XCNEG	DEC	CHNGX	;DEC IF NEGATIVE
	RTS
;
;PAUSE IF KEY HAS BEEN PRESSED
;
PAUSE	LDA	CH	;PRESSED??
	CMP	#$FF
	BEQ	NOPAUSE	;NO, GET OUT
	LDA	#1	;YES. LOCK PADDLES
	STA	LOCK
	LDA	#$FF	;RESET CH, AND
	STA	CH	;WAIT FOR ANOTHER
KEYWAIT	LDA	CH	;WAIT FOR ANOTHER
	CMP	#$FF	;KEY TO BE PRESSED
	BEQ	KEYWAIT
	LDA	#0	;UNLOCK PADDLES
	STA	LOCK
	LDA	#$FF	;AND RESET AGAIN
	STA	CH
NOPAUSE	RTS
;
;DRAW WALL FOR PRACTICE & WALL BALL
;
WALL	LDA	# <SCRNMEM+19
	STA	GPNTR	;POINT TO SCREEN
	LDA	# >SCRNMEM+19	;MEMORY
	STA	GPNTR+1
	LDY	#0
	LDX	#43
WLP	LDA	#$AA	;COLOR 2 FOR VERTICAL
	STA	(GPNTR),Y
	CLC		;ADD TO POINTER
	LDA	GPNTR
	ADC	#20
	STA	GPNTR
	BCC	WLP2
	INC	GPNTR+1
WLP2	DEX		;DO IT 43 TIMES
	BNE	WLP
	RTS
;
;CLEAR ALL SCREEN MEMORY
;
CLEARALL	LDA	# <SCORELINE
	STA	GPNTR	;SET POINTER
	LDA	# >SCORELINE
	STA	GPNTR+1
	LDX	#6	;AND DO 6 PAGES
	LDA	#0
	TAY
CLRLP	STA	(GPNTR),Y
	INY
	BNE	CLRLP
	INC	GPNTR+1
	DEX
	BNE	CLRLP
	RTS
;
;
;VERTICAL BLANK ROUTINE TO MOVE
;PADDLES AND DO SOUNDS
;
VBI	LDA	#8	;IS START PRESSED??
	STA	CONSOL
	LDA	CONSOL
	CMP	#6
	BNE	CHKLOCK	;NO.
	JMP	WRMVEC	;YES. DO A WARM START
;
CHKLOCK	LDA	LOCK	;ARE PADDLES LOCKED??
	BEQ	VBICONT	;NO.
	JMP	XITVBV	;YES, GET OUT
;
VBICONT	LDA	PADDL0	;G
	LDY	#0
	JSR	SCALEPAD	;SCALE IT PROPERLY
	STA	TEMPY	;AND SAVE
	LDA	NUMPD1	;NUMBER OF PADDLES FOR PLAYER 1
	STA	NPDTMP
PD1DR	DEC	NPDTMP
	LDA	NPDTMP	;MORE PADDLES??
	BMI	NOPD1	;NO
	LDY	YP1	;YES
	JSR	ERAPAD	;ERASE PADDLE 1
	LDY	NPDTMP	;FIND X POSITION
	LDX	XP1,Y
	LDY	TEMPY	;Y POSITION
	LDA	NPDTMP
	JSR	DRAWPAD	;AND DRAW IT
	JMP	PD1DR	;DO MORE
;
NOPD1	LDA	TEMPY	;PUT Y IN PLACE
	STA	YP1
	LDA	PADDL0+1	;AND DO PLAYER 2
	LDY	#1
	JSR	SCALEPAD	;SCALE IT
	STA	TEMPY
	LDA	NUMPD2	;SAME LOGIC
	STA	NPDTMP	;AS BEFORE
PD2DR	DEC	NPDTMP
	LDA	NPDTMP
	BMI	NOPD2
	CLC		;EXCEPT, WE MUST
	ADC	#2	;LET IT KNOW WHO'S
	LDY	YP2	;PADDLE TO ERASE
	JSR	ERAPAD
	LDY	NPDTMP
	LDX	XP2,Y
	LDY	TEMPY
	CLC
	LDA	NPDTMP
	ADC	#2	;AND TO DRAW
	JSR	DRAWPAD
	JMP	PD2DR
;
NOPD2	LDA	TEMPY
	STA	YP2
	LDA	VOL	;AND SOUNDS??
	BEQ	NOVOLDEC	;NO
	DEC	VOL	;YES, DEC IT
NOVOLDEC	LDA	VOL	;GET VOLUME
	ORA	#$A0	;WITH NO DISTORTION
	STA	AUDC1	;AND STORE
	LDA	NOTE	;GET NOTE
	STA	AUDF1	;AND STORE
	LDA	ALTFL	;IF ALTERNATING,
	BEQ	OUTVBI	;MAKE ONE
	LDA	ALTFL	;PLAYER BRIGHTER
	AND	#$02	;THAN THE OTHER
	TAX
	LDA	#PADCLR+4
	STA	PCOLR0,X
	STA	PCOLR0+1,X
	LDA	ALTFL	;LOOKS TRICKIER
	EOR	#$03	;THAN IT IS HERE
	AND	#$02	;I'M JUST
	TAX		;FINDING PLAYER TO
	LDA	#PADCLR	;MAKE DARKER
	STA	PCOLR0,X
	STA	PCOLR0+1,X
OUTVBI	JMP	XITVBV	;END OF VBI
;
;BUILD A DISPLAY LIST
;
DLBUILD	LDA	#10	;GRAPHICS 5 IN BASIC
	LDX	#42	;42 MODE LINES
DLLP	STA	DLMAIN,X
	DEX
	BPL	DLLP
	LDA	#$41	;JVB INST
	STA	DLMAIN+43
	LDA	# <DLIST
	STA	DLMAIN+44
	LDA	# >DLIST
	STA	DLMAIN+45
	RTS
;
;SCALE PADDLE INPUT TO PM LOC
;
SCALEPAD	LSR	A	;DIVIDE BY TWO
	SEC		;AND TAKE AWAY 7
	SBC	#7	;TO CENTER.
	BMI	LO
	CMP	#26	;NOW CHECK LOWER
	BCS	CHECKHI
LO	LDA	#26
	BNE	AOK
;
CHECKHI	CMP	#102	;TOO BIG?
	BCC	AOK	;NO.
	LDA	#101	;YES. USE 101
AOK	RTS
;
;ERASE A PADDLE
;
ERAPAD	PHA
	STY	TEMP2	;SAVE Y
	LDA	# <PLR0	;GET LOW MEMORY
	STA	GPNTR	;FOR PLAYERS
	LDA	# >PLR0
	STA	GPNTR+1
	PLA		;GET PLAYER NUMBER
	JSR	PLPNTR	;AND ADD TO POINTER
	LDY	TEMP2	GET Y BACK
	LDX	#9
	LDA	#0
ERALP	STA	(GPNTR),Y	;AND STICK SOME
	INY		;ZEROES IN
	DEX		;SOMEWHERE
	BPL	ERALP
	RTS
;
;ADJUST POINTER ACCORDING TO PLAYER NUMBER
;
PLPNTR	TAY
ADDLP	DEY		;GET OUT WHEN WE
	BMI	OUTPLP	;GET TO ZERO
	CLC		;ADD 128 FOR EACH
	LDA	GPNTR	;PLAYER
	ADC	#$80
	STA	GPNTR
	BCC	ADDLP
	INC	GPNTR+1
	JMP	ADDLP
OUTPLP	RTS
;
;DRAW PADDLE
;
DRAWPAD	STY	TEMP2	;DO SAME STUFF
	PHA		;AS IN ERASE,
	TAY
	TXA
	STA	HPOSP0,Y
	LDA	# <PLR0
	STA	GPNTR
	LDA	# >PLR0
	STA	GPNTR+1
	PLA
	JSR	PLPNTR
	LDX	#9
	LDA	#3
	LDY	TEMP2	;(INSTEAD OF 0)
DRLP	STA	(GPNTR),Y
	INY
	DEX
	BPL	DRLP
	RTS
;
;DRAW TOP AND BOTTOM
;
SETSCRN	LDA	#$55	;USE COLOR 1
	LDX	#19	;20 BYTES (0-19)
SETLP1	STA	SCRNMEM,X	;PUT ON SCREEN
	STA	SCRNMEM+860,X
	DEX
	BPL	SETLP1
	RTS
;
;INITIALIZE PLAYER-MISSILE GRAPHICS
;
PMINIT	LDA	#PMB	;TELL IT WHAT
	STA	PMBASE	;MEMORY TO USE
	LDA	#46	;AND DOUBLE-LINE
	STA	SDMCTL	;RESOLUTION
	JSR	ZPMS
	LDA	#3	;PLAYERS AND MISSILES
	STA	GRACTL
	LDA	#$11	;SET PRIORITY
	STA	GPRIOR
	RTS
;
;ZERO PLAYERS, MISSILES, AND X LOCATIONS
;
ZPMS	LDX	#12	;SET X LOCATIONS
	LDA	#0	;AND WIDTHS TO
ZPMLP	STA	HPOSP0,X	;ZERO.
	DEX
	BPL	ZPMLP
	LDA	#PMB
	STA	GPNTR+1
	LDA	#0	;POINT TO PM
	STA	GPNTR	;MEMORY
	LDX	#4	;AND FOUR PAGES
	TAY
ZPMEMLP	STA	(GPNTR),Y	;AND ZERO
	INY		;IT OUT
	BNE	ZPMEMLP
	INC	GPNTR+1
	DEX
	BNE	ZPMEMLP
	RTS
;
;DRAW PLAYING FIELD ACCORDING TO TYPE
;
TYPEOK	JSR	CLEARALL	;CLEAR WHAT WAS THERE
	JSR	WAIT60
	JSR	CLNSCRLN	;AND SCORELINE
	LDA	#0
	STA	VSCROL
	LDA	TYPE	;GET TYPE
	ASL	A
	ASL	A
	ASL	A
	ASL	A	;*16
	TAX		;AS OFFSET TO TABLE
	LDY	#0
PRTYPELP	LDA	STNDRD,X	;PRINT GAME TYPE
	STA	SCORELINE,Y
	INX
	INY
	CPY	#$10
	BNE	PRTYPELP
	JSR	ZPMS	;ZERO P/M AREA
	JSR	SETSCRN	;DO TOP & BOTTOM
	JSR	MIDLINE	;AND MIDDLE LINE
	LDA	TYPE
	CMP	#4
	BEQ	TYPE4
	LDA	# <SCRNMEM
	STA	MAINWORD
	LDA	# >SCRNMEM
	STA	MAINWORD+1
TYPE4	LDA	TYPE	;TYPE * 2 FOR
	ASL	A	;JUMP TABLE
	TAX
	LDA	JMPTAB,X	;GET JUMP TABLE
	STA	JMPVEC	;ENTRIES
	INX
	LDA	JMPTAB,X
	STA	JMPVEC+1
	JMP	(JMPVEC)	;AND OFF WE GO
;
;PRINT TITLE SCREEN
;
PTITLE	LDA	DLIST+3
	ORA	#$10	;SET HSCROL BIT
	STA	DLIST+3
	JSR	SETSCRN	;SET TOP AND BOTTOM
	LDA	# <TITLE	;POINT TO TITLE
	STA	GR2WORD
	LDA	# >TITLE
	STA	GR2WORD+1
	LDX	#110	;FOR 110 CHARACTERS
	LDA	#8
	STA	HSCROL	;INITIALIZE SCROLL
	STA	COUNT	;AND COUNTER
TBGLP	JSR	WAIT60	;SIT AROUND FOR A WHILE
	LDA	PTRIG0	;CHECK FOR TRIGGER
	AND	PTRIG0+1	;PRESSED EITHER
	BEQ	OUTPTITLE	;PADDLE
	DEC	COUNT	;COUNTDOWN
	LDA	COUNT	;WHEN BELOW ZERO,
	BPL	OKCOUNT
	LDA	#7	;SET BACK TO 7
	STA	COUNT
	INC	GR2WORD	;AND INCREMENT
	BNE	OKCOUNT	;LMS IN D LIST
	INC	GR2WORD+1
OKCOUNT	LDA	COUNT	;SET SCROLL
	STA	HSCROL	;REGISTER
	BNE	TBGLP	;IF ZERO,
	DEX		;DEC CHARACTER COUNT
	BNE	TBGLP
	BEQ	PTITLE	;AND REPEAT
;
OUTPTITLE	LDA	#15	;RESET SCROLL
	STA	HSCROL	;RESET POINTER
	LDA	# <SCORELINE
	STA	GR2WORD
	LDA	# >SCORELINE
	STA	GR2WORD+1
	LDA	DLIST+3
	AND	#$EF	;RESET HSCROL BIT
	STA	DLIST+3
	RTS		;AND LEAVE
;
;CLEAN SCORE LINE OF ALL GARBAGE
;
CLNSCRLN	LDA	#0
	LDX	#39	;20 BYTES WIDE *2
CLNSCR	STA	SCORELINE,X
	DEX
	BPL	CLNSCR
	RTS
;
;NEXT ROUTINES SET UP INITIAL
;CONDITIONS FOR GAME PLAY
;
;STANDARD GAME
;
STANDARDSU	LDA	#1	;EACH GET ONE
	STA	NUMPD1	;PADDLE TO MOVE
	STA	NUMPD2
	LDA	#46	;PUT THEM ON
	STA	XP1	;OPPOSITE SIDES
	LDA	#200	;OF THE SCREEN
	STA	XP2
	LDA	#0	;NO ALTERNATION
	STA	ALTFL
	LDA	#1	;START AT SPEED 1
	STA	STRSPD
	LDA	#8	;8 HITS BEFORE SPEED INCREASES
	STA	MAXHIT
	LDA	#$FF	;ALTERNATE SERVES
	STA	SRVFL
	RTS
;
;PRACTICE SET UP
;
PRACTICESU	LDA	#1	;ONLY ONE PADDLE
	STA	NUMPD1
	LDA	#0
	STA	NUMPD2
	LDA	#90	;NEAR MIDDLE
	STA	XP1
	LDA	#1	;START AT ONE
	STA	STRSPD
	LDA	#8	;8 HITS
	STA	MAXHIT
	LDA	#0	;NO ALTERNATION
	STA	ALTFL
	JSR	WALL	;DRAW A WALL
	LDA	#0	;NO SERVE ALTERNATION
	STA	SRVFL
	RTS
;
;HOCKEY PONG SET UP
;
HOCKEYSU	LDA	#2	;TWO PADDLES EACH
	STA	NUMPD1
	STA	NUMPD2
	LDA	#44	;ON END
	STA	XP1
	LDA	#156	;AND NEAR MIDDLE
	STA	XP1+1
	LDA	#198	;ON END
	STA	XP2
	LDA	#88	;AND NEAR MIDDLE
	STA	XP2+1
	LDA	#1	;START AT ONE
	STA	STRSPD
	LDA	#8	;8 HITS
	STA	MAXHIT
	LDA	#0	;NO ALTERNATION
	STA	ALTFL
	JSR	HOCKSIDES	;DRAW SIDES
	LDA	#$FF	;ALTERNATE SERVES
	STA	SRVFL
	RTS
;
;WALL PONG SET UP
;
WALLBALLSU	LDA	#1	;ONE PADDLE EACH
	STA	NUMPD1
	STA	NUMPD2
	STA	STRSPD	;START AT ONE
	LDA	#8	;8 HITS
	STA	MAXHIT
	LDA	#90	;BOTH PADDLES
	STA	XP1	;NEAR MIDDLE
	LDA	#94
	STA	XP2
	LDA	#1	;ALTERNATE HITS
	STA	ALTFL
	JSR	WALL	;DRAW WALL
	LDA	#0	;NO ALTERNATING SERVE
	STA	SRVFL
	RTS
;
;DRAW PARTIAL SIDES FOR HOCKEY
;
HOCKSIDES	LDA	# <SCRNMEM+20
	STA	GPNTR	;POINT TO SCREEN
	LDA	# >SCRNMEM+20
	STA	GPNTR+1
	LDX	#9	;NINE MODE LINES
TOPLP	LDY	#0
	LDA	#$80	;IN COLOR 1
	STA	(GPNTR),Y
	LDY	#19	;ON BOTH ENDS
	LDA	#2	;OF SCREEN
	STA	(GPNTR),Y
	CLC
	LDA	GPNTR	;ADD SIZE OF
	ADC	#20	;ONE LINE
	STA	GPNTR
	BCC	TOPLP1
	INC	GPNTR+1
TOPLP1	DEX
	BPL	TOPLP	;DONE WITH TOP HALF
	CLC
	LDA	GPNTR
	ADC	#$B8	;SKIP A BUNCH OF
	STA	GPNTR	;MODE LINES
	LDA	GPNTR+1
	ADC	#1
	STA	GPNTR+1
	LDX	#9
BOTLP	LDY	#0	;AND DO SIDES
	LDA	#$80	;ON BOTTOM HALF
	STA	(GPNTR),Y
	LDY	#19
	LDA	#2
	STA	(GPNTR),Y
	CLC
	LDA	GPNTR
	ADC	#20
	STA	GPNTR
	BCC	BOTLP1
	INC	GPNTR+1
BOTLP1	DEX
	BPL	BOTLP
	RTS
;
;GET TOP HALF OF BCD NUMBER
;
TOPHALF	LSR	A	;DIVIDE BY 16
	LSR	A
	LSR	A
	LSR	A
	BEQ	TOPZERO	;IF ZERO, LEAVE BLANK
	ORA	#$D0	;IF NOT, MAKE IT NUMERIC
TOPZERO	RTS
;
;GET BOTTOM HALF OF BCD NUMBER
;
BOTHALF	AND	#$0F
	ORA	#$D0
	RTS
;
;LET PLAYER CHOSE GAME
;
SETUP	LDA	PTRIG0	;IF EITHER TRIG
	AND	PTRIG0+1	;IS PRESSED, WAIT
	BEQ	SETUP
	LDA	#0	;INITIALIZE
	STA	TYPE
	STA	SRVDR
	JSR	TYPEOK
	LDA	#$15	;SET ENDING SCORE
	STA	TOPSCR
STARTOVER	LDA	#0	;WAIT FOR THE
	STA	JIFCNT	;PADDLE TO GO
	STA	LOCK	;IN 1 DIRECTION
	JSR	WAIT60
	LDA	#1	;FOR A WHILE
	STA	LOCK
CHECKMORE	LDA	PADDL0
	STA	LASTPAD
	CLC
	LDA	RTCLOK	;CHECK PADDLE
	ADC	#3	;EVERY THIRD
	STA	COUNT	;JIFFY
WAIT03	JSR	WAIT60
	LDA	PTRIG0	;BUT CONSTANTLY
	AND	PTRIG0+1	;CHECK PADDLE
	BEQ	TYPECHOSEN	;BUTTONS
	LDA	COUNT
	CMP	RTCLOK
	BNE	WAIT03
	LDA	PADDL0
	CMP	LASTPAD
	BEQ	CHECKMORE
	BCS	CNTDN
	LDA	JIFCNT	;IF DIRECTION CHANGED,
	BMI	STARTOVER	;TRY AGAIN
	INC	JIFCNT	;ADD TO COUNTER
	LDA	JIFCNT
	CMP	#3	;IS IT 3?
	BNE	CHECKMORE	;NO. WAIT
	BEQ	INCTYPE	;CHANGE GAME TYPE
;
CNTDN	DEC	JIFCNT	;DECR. COUNTER
	LDA	JIFCNT
	BPL	STARTOVER
	CMP	#$FD	;IS IT -3?
	BNE	CHECKMORE	;NO. WAIT.
	DEC	TYPE	;CHANGE GAME TYPE
	LDA	TYPE
	BPL	TYPECONT01
	LDA	#3
	STA	TYPE
TYPECONT01	JSR	LASTTYPE	;SET UP TYPES
	JSR	SCROLLDN	;SCROLL DOWN
	JMP	TYPECONT	;GO BACK FOR MORE
;
INCTYPE	INC	TYPE	;INCR GAME TYPE
	LDA	TYPE
	CMP	#4
	BNE	TYPECONT02
	LDA	#0
	STA	TYPE
TYPECONT02	JSR	NEXTTYPE	;SET UP TYPES
	JSR	SCROLLUP	;AND SCROLL UP
TYPECONT	LDX	#3	;RESET PADDLE
	LDA	#PADCLR	;COLORS
PDCOLRLP	STA	PCOLR0,X
	DEX
	BPL	PDCOLRLP
	JSR	TYPEOK	;SET UP GAME SCREEN
	JMP	STARTOVER	;AND GO BACKE
;
TYPECHOSEN	LDA	PTRIG0	;WAIT FOR
	AND	PTRIG0+1	;TRIG RELEASE
	BEQ	TYPECHOSEN
	LDA	#0
	STA	COUNT
	RTS
;
NEXTTYPE	LDA	TYPE	;PUT NEXT TYPE
	ASL	A	;TITLE IN
	ASL	A	;SECOND LINE OF
	ASL	A	;MEMORY
	ASL	A
	TAX
	LDY	#0
PRTYPELP2	LDA	STNDRD,X
	STA	SCORELINE+20,Y
	INX
	INY
	CPY	#$10
	BNE	PRTYPELP2
	RTS
;
;SCROLL TWO MEMORY LINES UP
;
SCROLLUP	LDA	#0
	STA	COUNT
SCRLUPLP	LDA	COUNT
	STA	VSCROL
	JSR	WAIT60
	INC	COUNT
	LDA	COUNT
	CMP	#$10	;16 TIMES
	BNE	SCRLUPLP
	RTS
;
;SCROLL TWO MEMORY LINES DOWN
;
SCROLLDN	LDA	#15
	STA	COUNT
SCRLDNLP	LDA	COUNT
	STA	VSCROL
	JSR	WAIT60
	DEC	COUNT
	LDA	COUNT
	BPL	SCRLDNLP
	RTS
;
;MOVE CURRENT TYPE TO SECOND
;LINE, AND NEW TYPE TO FIRST
;
LASTTYPE	LDA	TYPE
	ASL	A
	ASL	A
	ASL	A
	ASL	A
	TAX
	LDY	#0
LASTTYPELP	LDA	SCORELINE,Y	;1ST TO 2ND
	STA	SCORELINE+20,Y
	LDA	STNDRD,X	;NEW TO 1ST
	STA	SCORELINE,Y
	INX
	INY
	CPY	#$10
	BNE	LASTTYPELP
	RTS
;
;STORAGE
;
XP1	.BYTE	0,0	;PADDLE X POSITIONS
XP2	.BYTE	0,0
YP1	.BYTE	0	;PADDLE Y POSITIONS
YP2	.BYTE	0
BALLX	.BYTE	0	;BALL X POS
BALLY	.BYTE	0	;BALL Y POS
CHNGX	.BYTE	0	;BALL X CHANGE
CHNGY	.BYTE	0	;BALL Y CHANGE
TOPSCR	.BYTE	0	;ENDING SCORE
HITS	.BYTE	0	;NUMBER OF HITS
MAXHIT	.BYTE	0	;# OF HITS BEFORE SPEED CHANGE
STRSPD	.BYTE	0	;STARTING SPEED
CHNGTAB	.BYTE	-3,-2,-2,-1,-1,0,0,1,1,2,2,3
NUMPD1	.BYTE	0	;NUMBER OF PADDLES
NUMPD2	.BYTE	0	;ON EACH SIDE
NPDTMP	.BYTE	0	;TEMP # OF PADDLES
MISPL	.BYTE	0	;COLLISION REG
MISPF	.BYTE	0	;HOLDERS
TITLE	.SBYTE	"                      P O N G                  BY GARY DOMROW OF THE SUMMIT SOFTWARE GROUP"
	.SBYTE	" for analog computing                     "
WINNER	.SBYTE	"WINNER"
COLORS	.BYTE	$D4,$D4,$D4,$D4,$94,$94,$94,$0A,$00
JMPTAB	.WORD	STANDARDSU,HOCKEYSU,WALLBALLSU,PRACTICESU
SRVFL	.BYTE	0	;SERVE FLAG
ALTFL	.BYTE	0	;ALTERNATE HITS
LASTPAD	.BYTE	0	;PADDLE VALUE
JIFCNT	.BYTE	0	;JIFFY COUNTER
STNDRD	.SBYTE	"   STANDARD PONG"
	.SBYTE	"    HOCKEY PONG "
	.SBYTE	"     WALL PONG  "
	.SBYTE	"      PRACTICE  "
;
;DISPLAY LIST & STORAGE
;
DLIST	.BYTE	$70,$70,$70,$67
GR2WORD	.WORD	SCORELINE
	.BYTE	$07,$4A
MAINWORD	.WORD	SCRNMEM
DLMAIN	.DS	46
SCORELINE	.DS	40
SCRNMEM	.DS	880
;
	*=	$02E0
	.WORD	START
	.END