*BREAKOUT GAME - BY DAN PINAL
*ZERO PAGE EQUATES
WINDOW	EQU	$F0
MSG	EQU	$F2
LINE2	EQU	$F4
PO	EQU	$F6
*MISC EQUATES
RTCLOC	EQU	$14
ATRACT	EQU	$4D
SDLSTL	EQU	$230
STICKO	EQU	$278
STRIGO	EQU	$284
AUDF1	EQU	$D200		; PITCH I
AUDC1	EQU	$D201		; DISTORTION/VOLUME I
RANDOM	EQU	$D20A
SETVBV	EQU	$E45C		; SET VBLANK ROUTINE
XITVBV	EQU	$E462		; DEFFERED VBLANK EXIT
CONSOL	EQU	$D01F
* EQUATES FOR CIO
CIOV	EQU	$E456		; ENTRY VECTOR
* COMMANDS *
OPEN	EQU	$03		; OPEN FOR INPUT/OUTPUT
GETREC	EQU	$05		; GET RECORD
GETCHR	EQU	$07		; GET CHARACTER(S)
PUTREC	EQU	$09		; PUT RECORD
PUTCHR	EQU	$0B		; PUT CHARACTER(S)
CLOSE	EQU	$0C		; CLOSE DEVICE
STATIS	EQU	$0D		; STATUS REQUEST
SPECIL	EQU	$0E		; BEGINNING OF SPECIAL ENTRY COMMANDS
*
* SPECIAL COMMANDS
*
DRAWLN	EQU	$11		; DRAW LINE
FILLIN	EQU	$12		; DRAW LINE WITH RIGHT FILL
*
* AUX1 VALUES
*
APPEND	EQU	$01		; OPEN FOR WRITE APPEND
OPNIN	EQU	$04		; OPEN FOR INPUT
OPNOT	EQU	$08		; OPEN FOR OUTPUT
OPNINO	EQU	OPNIN+OPNOT	; OPEN FOR INPUT AND OUTPUT
MXDMOD	EQU	$10		; OPEN FOR MIXED MODE (E:,S:)
INSCLR	EQU	$20		; OPEN WITHOUT CLEARING SCREEN (E:,S:)
*
* O.S. RAM EQUATES
*1/0 CONTROL BLOCK EQUATES
ROWCRS	EQU	$54		; CURRENT GRAPHICS CURSOR ROW
COLCRS	EQU	$55		; & $56. LSB MSB OF CURRENT GRAPHICS CURSOR COLUMN
ATACHR	EQU	$2FB		; LAST GRAPHICS CHARACTER READ OR WRITTEN
*
ICHID	EQU	$340		; HANDLER INDEX SET BY O.S.
ICDNO	EQU	$341		; DEVICE # AS IN D1:,D2: ETC
ICCOM	EQU	$342		; COMMAND
ICSTA	EQU	$343		; STATUS RETURNED
ICBAL	EQU	$344		; BUFFER ADDRESS LO
ICBAH	EQU	$345		; BUFFER ADDRESS HI
ICPTL	EQU	$346		; PUT ONE BYTE VECTOR LO
ICPTH	EQU	$347		; PUT ONE BYTE VECTOR HI
ICBLL	EQU	$348		; BUFFER LENGTH LO
ICBLH	EQU	$349		; BUFFER LENGTH HI
ICAUX1	EQU	$34A		; AUXI
ICAUX2	EQU	$34B		; AUX2
;
;
;
	ORG	$4000
*
	JMP START		; SKIP PAST SUBROUTINES
* GRAPHICS CALLS TO O.S.
*
*   GRAPHICS
*   ACC=GR. MODE
GRAPHICS PHA			; SAVE MODE
	LDX	#$60		; IOCB #6 FOR GRAPHICS
	LDA	#CLOSE		; CLOSE #6 FOR SAFETY (CAN'T OPEN AN ALREADY OPEN DEVICE)
	STA	ICCOM,X
	JSR	CIOV
	LDA	#OPEN
	STA	ICCOM,X
	LDA	#>FNAME		; FILENAME IS S:
	STA	ICBAL,X
	LDA	#<FNAME
	STA	ICBAH,X
	PLA			; GR. MODE
	STA	ICAUX2,X
	AND	#$F0		; KEEP UPPER NIBBLE FOR FULLSCREEN
				; & NO SCREEN ERASE FLAGS(+16 & +32)
*O.S. FULL SCREEN FLAG IS THE OPPOSITE OF THE WAY BASIC USES IT.
*i.e. +16 = SPLIT SCREEN NOT FULL SCREEN
	EOR	#$10		; FLIP-FLOP IT LIKE BASIC
	ORA	#OPNINO		; OPEN S: FOR READING & WRITING
	STA	ICAUX1,X
	JMP	CIOV		; GO DO IT IT WILL RTS FROM THERE
;
*   POSITION
*   EVEN THOUGH THIS IS SIMPLE IT IS HERE AS A SUBROUTINE
*   BECAUSE IT IS USED OFTEN BY OTHER ROUTINES
*   ACC. = VERT.
*   X = HORIZ. HI : Y HORIZ. LO
POSITION
	STY	COLCRS		; CURSOR COLUMN LO
	STX	COLCRS+1	; CURSOR COLUMN HI
	STA	ROWCRS		; CURSOR ROW
	RTS
;
*   PLOT
*   ENTRY REG. ARE SAME AS POSITION
*   WILL PLOT A POINT USING VALUE IN COLOR
PLOT	JSR	POSITION
	LDX	#$60		; IOCB #6
	LDA	#PUTCHR
	STA	ICCOM,X
	LDA	#$0		; 0 BUFFER LENGTH
	STA	ICBLL,X
	STA	ICBLH,X
	LDA	COLOR		; CIO WILL DEFAULT TO VALUE IN ACC
	JMP	Ciov		; & SEND IT TO SCREEN (IT WILL RTS To PROGRAM FROM CIO
*DRAWTO
*   ENTRY SETUP SAME AS POSITION
DRAWTO	JSR	POSITION
	LDA	COLOR
	STA	ATACHR		; TELL O.S.
	LDX	#$60		; IOCB #6
	LDA	#DRAWLN		; DRAWTO HAS ITS OWN SPECIAL COMMAND
	STA	ICCOM,X
	LDA	#OPNINO
	STA	ICAUX1,X	; MAKE SURE O.S. KNOWS WHAT IT IS SUPPOSED TO DO
	LDA	#$0
	STA	ICAUX2,X
	JMP	CIOV		; GO DO IT & RTS TO PROGRAM FROM THERE
*LOCATE
*   SETUP SAME AS POSITION
*   ACC. & COLOR HAVE VALUE LOCATED
LOCATE	JSR	POSITION
	LDX	#$60		; IOCB #6
	LDA	#GETCHR
	STA	ICCOM,X
	LDA	#$0		; 0 OUT BUFFER LENGTH
	STA	ICBLL,X
	STA	ICBLH,X
	JSR	CIOV		; THIS WORKS EXACTLY THE OPPOSITE OF PLOT
	STA	COLOR
	RTS
*   MISC. ROUTINES
*   8 BIT DIVISION
*   X= NUM TO DIVIDE BY
*   A= LOBYTE OF NUM TO DIVIDE INTO
*   Y= HIBYTE OF NUM TO DIVIDE INTO
*   RESULT & REMAIN HAVE ANSWER ON EXIT
*    A=REMAINDER
DIVIDE	STA	RESULT
	STX	DIVISOR
	TYA
	LDX	#$08
DIV1	ASL	RESULT
	ROL	A
	CMP	DIVISOR
	BCC	DIV2
	SBC	DIVISOR
	INC	RESULT
DIV2	DEX
	BNE	DIV1
	STA	REMAIN
	RTS
;
*   8 BIT MULTIPLY
*   MULTIPLIES ACC BY X REG.
*   STORES RESULT (L,H) IN RESULT & RESULT+1
MULTIPLY STA	M1		z; MULTIPLIER
	STX	M2		; MULTIPLICAND
	LDA	#$0
	STA	RESULT
	STA	RESULT+1
	LDX	#$08
MUL1	ASL	RESULT
	ROL	RESULT+1
	ASL	M2
	BCC	MUL2
	CLC
	LDA	RESULT
	ADC	M1
	STA	RESULT
	BCC	MUL2
	INC	RESULT+1
MUL2	DEX
	BNE	MUL1
	RTS
;
NEWBALL	LDA	#$01		; BALL COLOR
	STA	COLOR
	CLC
	LDA	RANDOM
	AND	#$7F		; 0-128
	ADC	#$10		; 16-144
	STA	BALLX		; BALL HORIZ. POS. IS DOUBLED SO IT CAN BE MOVED IN HALF INC
	LSR	A		; /2 FOR ACTUAL BALL POSITION
	STA	OLDX
	TAY
	LDX	#$00
	LDA	#$11		; 17
	STA	BALLY
	STA	OLDY
	JSR	PLOT		; PUT NEW BALL STARTING POS. ON SCREEN
	LDA	#$01
	STA	DY		; SET FOR DOWN
	LDA	RANDOM
	AND	#$03		; 0-3
	TAX
	LDA	VX,X		; PICK RANDOM HORIZ. VECTOR
	STA	DX		; SAVE IT
	LDA	#$26		; 38
	STA	PADDLE		; REPOSITION TO MIDDLE OF SCREEN
NB1	JSR	DOPADDLE
	LDA	STICKO
	CMP	#$0F		; STICK CENTER?
	BNE	NB1		; WAIT TILL IT IS.
	LDA	STRIGO		; BUTTON PRESSSED?
	BNE	NB1		; WAIT TILL TRIGGER PRESSED
	RTS
DOPADDLE LDX	STICKO		; GET STICK VALUE
	LDA	STRIGO		; BUTTON PRESSED
	BNE	DP1		; USE NORMAL SPEED PADDLE MOVEMENT
	LDA	FHOFFS,X	; TRIPLE SPEED TABLE
	JMP	DP2
DP1	LDA	HOFFS,X		; NORMAL SPEED TABLE
DP2	LDX	#$00		; PADDLE MINIMUM
	LDY	#$4C		; 76 PADDLE MAXIMUM
	CLC
	ADC	PADDLE
	BPL	DP3
	TXA			; PADDLE H. CAN'T GO LESS THAN 0 SO SET IT TO 0
DP3	CMP	#$4D		; 77 GONE PAST UPPER LIMIT
	BCC	DP4		; OK IF <
	TYA
DP4	STA	PADDLE
*   NOW ERASE OLD PADDLE & DRAW NEW
	LDA	#$00
	STA	COLOR
	JSR	DRPADDLE
	LDA	PADDLE
	STA	PX
	LDA	#$01
	STA	COLOR
	JSR	DRPADDLE
	RTS
*   DRAW PADDLE
DRPADDLE LDA	#$24		; 36TH ROW
	LDY	PX		; PADDLE H.
	LDX	#$00		; HI BYTE OF PADDLE H. ALWAYS 0 UNLESS GR. 8
	JSR	PLOT
	CLC
	LDA	PX
	ADC	#$03		; END OF PADDLE IS PADDLE H. + 3
	TAY			; SET UP FOR DRAWTO CALL
	LDX	#$00
	LDA	#$24
	JSR	DRAWTO
	RTS
*EBRICK
* ERASES BRICK ONE LINE AT A TIME
EBRICK	LDX	#$00
	STX	COLOR
	LDA	BRICKY
	LDY	BRICKX
	JSR	PLOT
	CLC
	LDA	BRICKX
	ADC	#$04
	TAY
	LDX	#$00
	LDA	BRICKY
	JSR	DRAWTO
	RTS
*
JDELAY	LDA	RTCLOC
JD1	CMP	RTCLOC
	BEQ	JD1
	DEX
	BNE	JDELAY
	RTS
*
* VBI ROUTINE IS USED SO SOUND DOES NOT INTERFERE WITH PLAY
*
VBI	CLD
	LDA	TIMER		; SOUND TO DO
	BEQ	XVBI		; NO. LEAVE
	DEC	TIMER		; COUNTDOWN
	LDA	TIMER		; USE TIMER AS VOLUME
	ORA	#$A0		; DISTORTION 10
	STA	AUDC1		; TELL POKEY
	LDA	#$20
	STA	AUDF1
XVBI
	JMP	XITVBV
*
*   PROGRAM DATA
*
*FNAME	AS	"S:"
*	HS	9B
FNAME	DB	$53,$3A
	DB	$9B
;
;
;
*MSG0	AT	"GAME OVER"
MSG0	DB	$27,$21,$2D
	DB	$25,$00,$2F
	DB	$36,$25,$32
;
;
;
*MSG1	AT	" PERFECT!"
MSG1	DB	$00,$30,$25
	DB	$32,$26,$25
	DB	$23,$34,$01
;
;
;
*MSGTAB	DA	MSG0,MSG1
MSGTAB	DW	MSG0
	DW	MSG1
;
;
;
*TOPLINE	AT	BALL: 0
*	AT	SCORE: 0000
TOPLINE	DB	$00,$00,$22
	DB	$21,$2C,$2C
	DB	$1A,$00,$10
	DB	$00,$00,$00
	DB	$00,$00,$00
	DB	$00,$00,$00
	DB	$00,$00
	DB	$00,$00,$00
	DB	$00,$00,$00
	DB	$00,$00,$33
	DB	$23,$2F,$32
	DB	$25,$1A,$00
	DB	$10,$10,$10
	DB	$10,$00
;
;
;
*HOFFS	HS	0000000000010101
*	HS	00FFFFFF00000000
HOFFS	DB	$00,$00,$00,$00,$00,$01,$01,$01
	DB	$00,$FF,$FF,$FF,$00,$00,$00,$00
;
;
;
*FHOFFS	HS	0000000000030303
*	HS	00FDFDFD00000000
FHOFFS	DB	$00,$00,$00,$00,$00,$03,$03,$03
	DB	$00,$FD,$FD,$FD,$00,$00,$00,$00
;
;
;
*VX	HS	FEFF0102
VX	DB	$FE,$FF,$01,$02
;
;
;
*POINTS	HS	00100503
POINTS	DB	$00,$10,$05,$03
;
;
;
COLOR	DS	1
RESULT	DS	1		; RESULT & REMAIN MUST STAY
REMAIN	DS	1		; NEXT TO EACH OTHER
DIVISOR	DS	1
M1	DS	1
M2	DS	1
TEMPI	DS	1
TEMP2	DS	1
TEMP3	DS	1
TEMP4	DS	1
ROW	DS	1
BALLX	DS	1		; BALL'S X POSITION (DOUBLED)
BALLY	DS	1		; BALL'S Y POSITION
DX	DS	1		; DOUBLED HORIZONTAL DIRECTION VALUE
DY	DS	1		; VERTICAL DIRECTION VALUE
TX	DS	1		; TRUE HORIZONTAL DIRECTION VALUE
OLDX	DS	1		; BALL'S OLD HORIZ POSITION
OLDY	DS	1		; BALL'S OLD VERTICAL POSITION
PADDLE	DS	1		; HORIZ PADDLE POSITION
PX	DS	1		; NEW HORIZ PADDLE POSITION
BALLS	DS	1
BRICKS	DS	1
BRICKX	DS	1		; HORIZ POSITION OF BRICK TO BE REMOVED
BRICKY	DS	1		; VERTICAL POSITION
SCORE	DS	2
TIMER	DS	1
;
*BEGINNING OF MAIN PROGRAM
START	LDA	#$07		; DEFFERED
	LDY	#>VBI
	LDX	#<VBI
	JSR	SETVBV		; ENABLE SOUND ROUTINE
	LDA	#$05		; START WITH GRAPHICS 5
	JSR	GRAPHICS
	LDA	SDLSTL		; FIND DISPLAY LIST
	STA	PO
	LDA	SDLSTL+1
	STA	PO+1
	LDY	#$2F
	LDA	(PO),Y		; FIND OUT WHERE IT PUT TEXT WINDOW
	STA	WINDOW+1
	STA	LINE2+1
	DEY
	LDA	(PO),Y
	STA	WINDOW
	CLC
	ADC	#$38		; 56 ALMOST HALFWAY INTO 2ND LINE OF TEXT WINDOW
	STA	LINE2
	BL	ST1
	INC	LINE2+1
ST1	LDY	#$27	; 39
ST2	LDA	TOPLINE,Y	; BLOCK MOVE THE TOPLINE INTO TEXT WINDOW
	STA	(WINDOW),Y
	DEY
	BPL	ST2
* NOW DRAW BRICKS
DOBRICKS LDA	#$03
	STA	TEMPI
DB1	LDA	TEMPI
	STA	COLOR
	LDA	#$02
	STA	TEMP2
DB2	LDA	TEMPI
	ASL	A		; X 2
	ASL	A		; X 4
	CLC
	ADC	TEMP2
	STA	ROW
	LDA	#$02
	STA	TEMP3
DB3	LDA	ROW
	LDX	#$00
	LDY	#$00
	JSR	PLOT		; PLOT O,ROW
	LDA	ROW
	LDX	#$0
	LDY	#$4F		; 79
	JSR	DRAWTO		; DRAWTO 79,ROW
	INC	ROW
	DEC	TEMP3
	BNE	DB3		; TWO ROWS PER BRICK
	DEC	TEMP2
	DEC	TEMP2
	BPL	DB2		; TWO ROWS OF BRICKS PER COLOR
	DEC	TEMPI
	BNE	DB1		; 3 COLORS OF BRICKS
	LDA	#$01
	STA	BALLS
	ORA	#$10		; MAKE INTERNERNAL CHR
	LDY	#$08
	STA	(WINDOW),Y
	LDA	#$60		; 96 6 ROWS OF 16 BRICKS
	STA	BRICKS
	LDA	#$00
	STA	SCORE
	STA	SCORE+1
* MAIN GAME LOOP BEGINS HERE
*
GAME	JSR	NEWBALL		; INITIALIZE NEW BALL DATA WAIT FOR BUTTON PRESS
GAMELOOP	LDX	#$08
	STX	ATRACT
	JSR	JDELAY
	JSR	DOPADDLE	; UPDATE PADDLE POS.
* GET NEW BALL POS.
DOBALL	CLC
	LDA	BALLX
	ADC	DX		; HORIZONTAL CHANCE. -2 TO +2
	CMP	#$F0
	BCC	AA0
	LDA	#$00
AA0	CMP	#$A0
	BCC	AA10
	LDA	#$9F
AA10	STA	BALLX
	LSR	A		; TRUE H. POS.
	STA	TX
	BEQ	AA1
	CMP	#$4F		; 79 AT RIGHT EDGE?
	BL	AA2		; OK IF
AA1	DEC	DX
	LDA	DX
	EOR	#$FF		; REVERSE HORIZONTAL
	STA	DX
	LDA	#$10
	STA	TIMER		; PING!
AA2	CLC
	LDA	BALLY
	ADC	DY
	STA	BALLY
	CMP	#$02
	BGE	AA3
	LDA	#$01		; AT TOP
	STA	DY		; SET VERTICAL DIRECTION TO DOWN
	LDA	#$10
	STA	TIMER		; PING!
	BNE	HITCK		; BRANCH ALWAYS
AA3	CMP	#$27		; PAST PADDLE?
	BL	HITCK		; OK IF <
	JMP	ENDBALL
; ACC HAS V.
HITCK	LDX	#$00
	LDY	TX
	JSR	LOCATE		; ACC. HAS COLOR VALUE OF PIXEL
	CMP	#$00
	BNE	AB1
	JMP	XHITCK
AB1	LDY	#$10
	STY	TIMER		; PING!
	LDY	BALLY
	CPY	#$20		; HAS IT HIT PADDLE OR BRICKS?
	BCC	AB2		; BRICKS
	LDA	TX		; COMPARE PADDLE H. TO BALL H.
	SBC	PX		; DIFFERENCE IS 0-3
	TAX			; AND WILL DECIDE NEW HORIZ. VELOCITY
	LDA	VX,X
	STA	DX		; STORE NEW HORIZ VELOCITY
	LDA	#$FF
	STA	DY		; SET VERTICAL DIRECTION TO UP
	JMP	XHITCK		; LEAVE
*ACC. STILL HAS COLOR		; VALUE HIT. USE IT TO GET BRICK VALUE
AB2	TAX
	SED
	LDA	SCORE+1		; LOAD TWO LOW DIGITS
	ADC	POINTS,X	; ADD POINT VALUE OF BRICK
	STA	SCORE+1
	LDA	#$00		; WILL ALSO ADD CARRY BIT IF NECESSARY
	ADC	SCORE
	STA	SCORE
	CLD
* NOW PRINT NEW SCORE ON SCREEN
DOSCORE
	LDX	#$00
	LDY	#$23
AC1	LDA	SCORE,X
	LSR	A		; EACH BYTE HOLDS 2 NUMBERS
	LSR	A		; SHIFT UPPER NIBBLE OVER
	LSR	A		; AND DO IT
	LSR	A		; FIRST.
	ORA	#$10		; TRANSLATE NUMBER INTO INTERNAL CHARACTER
	STA	(WINDOW),Y	; STORE HIGHER DIGIT OF PAIR IN TEXT AREA
	INY			; NEXT
	LDA	SCORE,X
	AND	#$0F		; NOW DO LOWER NIBBLE
	ORA	#$10		; MAKE A CHR
	STA	(WINDOW),Y	; STORE LOWER DIGIT OF PAIR IN TEXT AREA
	INY
	INX
	CPX	#2		; DONE BOTH BYTES? (ALL 4 SCORE DIGITS)
	BNE	AC1
*NOW CALCULATE BRICK POSITION
*   BRICK HORIZONTAL IS THE INTEGER OF TX/5
	LDA	TX
	LDY	#$00		; TX HAS NO HIBYTE SO Y=O
	LDX	#$05		; TO DIVIDE BY
	JSR	DIVIDE
	LDA	RESULT
	LDX	#$05
	JSR	MULTIPLY
	LDA	RESULT
	STA	BRICKX
	LDA	BALLY		; BALL VERT.
	LSR	A		; /2
	ASL	A		; X2 THIS INSURES AN EVEN NUMBER
	STA	BRICKY		; THE 'FOP OF ANY BRICK IS AN EVEN ROW.
	JSR	EBRICK		; ERASE TOP 1,INE OF BRICK
	INC	BRICKY		; BRICKS ARE 2 [,INES HIGH
	JSR	EBRICK		; ERASE SECOND LINE
*   BRICK IS GONE
*   FLIP FLOP VERTICAL DIRECTION
	DEC	DY
	LDA	DY
	EOR	#$FF
	STA	DY
	DEC	BRICKS		; ONE LESS BRICK
	BEQ	ENDGAME		; IF ALL ARE GONE END GAME
XHITCK	LDA	#$0
	STA	COLOR
	LDA	OLDY
	LDX	#$00
	LDY	OLDX
	JSR	PLOT		; ERASE OLD BALL
	LDA	#$01
	STA	COLOR
	LDA	BALLY
	STA	OLDY
	LDX	#$00
	LDY	TX
	STY	OLDX
	JSR	PLOT		; PUT BALL ON IN NEW POSITION
	JMP	GAMELOOP	; DO IT AGAIN
ENDBALL	LDX	#$00
	STX	COLOR
	LDY	OLDX
	LDA	OLDY
	JSR	PLOT		; ERASE BALL
	INC	BALLS
	LDA	BALLS		; 2-6
	CMP	#$06
	BCS	ENDGAME
	ORA	#$10		; MAKE INTO CHR.
	LDY	#$08
	STA	(WINDOW),Y
	JMP	GAME		; GO BACK TO NEWBALL ROUTINE
ENDGAME
	LDX	#$00
	LDA	BRICKS
	BNE	AD1
	INX			; THEN 2ND MESSAGE
AD1	TXA
	ASL
	TAX
	LDA	MSGTAB,X
	STA	MSG
	LDA	MSGTAB+1,X
	STA	MSG+1
	LDY	#$08
AD2	LDA	(MSG),Y
	STA	(LINE2),Y
	DEY
	BPL	AD2
AD3	LDA	CONSOL
	CMP	#$06
	BNE	AD3
	JMP	START
