; *****************************
; *         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  DB 0,0     ;GENERAL POINTER
VOL    DB  1       ;VOLUME
NOTE   DB   1      ;NOTE
LOCK   DB   1      ;PADDLE MOVE FLG
SCORE1 DB    1    ;PLAYER 1 SCORE
SCORE2 DB    1    ;PLAYER 2 SCORE
COLR   DB  1      ;COLOR
TYPE   DB  1      ;GAME TYPE
SRVDR  DB   1     ;SERVE DIRECTION
TEMP2  DB   1
TEMPX  DB   1
TEMPY  DB   1
JMPVEC DB   0,0    ;JUMP VECTOR
COUNT  DB   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 '
      .SBYTE '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     46
SCORELINE     40
SCRNMEM     880
;
;  *=  $02E0
;  .WORD START
End START
