	.OPT NO LIST
;BACKGROUND PRINTER
;by
;A. Giambra
;
ADDR	= $2200 	;START ADDRESS
DDEVIC	= $0300 	;DEVICE
DUNIT	= $0301 	;DEVICE
DCOMND	= $0302 	;I/O COMMAND
DSTATS	= $0303 	;DEVICE
DBUFLO	= $0304 	;BUFFER ADDRESS
DTIMLO	= $0306 	;BUFFER ADDRESS
DBYTLO	= $0308 	;BUFFER ADDRESS
DBYTHI	= $0309 	;BUFFER ADDRESS
DAUX1	= $030A 	;SECTOR NUMBER
DSKINV	= $E453 	;OS I/O ROUTINE
CIOV	= $E456 	;OS I/O ROUTINE
NOTE	= $26 	;NOTE SECTOR
READ	= $04 	;OPEN FOR READ
PUTCHAR	= $0B 	;PUT CHARACTERS
READCOM	= $52 	;READ SECTOR CMND
STATUS	= $0D 	;STATUS COMMAND
OPEN	= $03 	;OPEN DEVICE
CLOSE	= $0C 	;CLOSE DEVICE
OPENERROR	= 129 	;CHANNEL OPEN
NOTFOUND	= $AA 	;WORK FLAG
IOCB0	= $00 	;CHANNEL 0
IOCB1	= $10 	;CHANNEL 1
HATABS	= $031A 	;HANDLER TABLE
ICCOM	= $0342 	;I/O COMMAND
ICSTA	= $0343 	;I/O STATUS
ICBAL	= $0344 	;BUFFER ADDRESS
ICBLL	= $0348 	;BUFFER LENGTH
ICAX1	= $034A 	;AUXILIARY BYTE
ICAX3	= $034C 	;AUXILIARY BYTE
DOSVEC	= $0A 	;DUP SYS ADDRESS
DOSINI	= $0C 	;DOS INIT
PBPNT	= $1D
PBUFSZ	= $1E
PRNBUF	= $03C0
PTIMOT	= $1C
LOMEM	= $02E7 	;LOW MEMORY
WARMSTART	= $E474
XITVBV	= $E462 	;VBI EXIT
SETVB	= $E45C 	;SET VBI ROUTINE
VVBLKD	= $0224 	;VBI VECTOR ADDR
CR	= $9B 	;CARRIAGE RETURN
COMMAND	= $CB 	;TEMP STORAGE
SECTOR	= $CC 	;SECTOR COUNT
INDEX	= $CE 	;WORK INDEX
RETRY	= $CF 	;RETRY FLAG
FLAG	= $D0 	;WROK FLAG
BUSY	= $D1 	;BUSY FLAG
;OFFSET TO RESIDENT PRINT HANDLER
;RETRY LOGIC
PRINTOFF	= $EECB-$EEA7
;
;HANDLER TABLE
;
	*= ADDR
	.WORD OPENIT-1
	.WORD CLOSEIT-1
	.WORD RETURN-1
	.WORD WRITE-1
	.WORD RETURN-1
	.WORD RETURN-1
	JMP RETURN
DOS
	*= *+2
DUPSAV
	*= *+2
VBISAV
	*= *+2
TIMER
	*= *+1
;
;THE OPEN ROUTINE SUBSTITUES THE
;PRINT.SPL FILE NAME INTO THE
;IOCB, THEN CALLS THE DISK
;OPEN ROUTINE
;
OPENIT
	LDA SECTOR 	;PRINT.SPL INUSE?
	BEQ OPEN1 	;TEST OTHER BYTE
INUSE
	TXA  	;SAVE X REGISTER
	PHA 
	LDX #IOCB0 	;CHANNEL 0-EDITOR
	LDA #PUTCHAR 	;WRITE CHARS
	STA ICCOM,X
	LDA # <MSG 	;IN USE MESSAGE
	STA ICBAL,X
	LDA # >MSG
	STA ICBAL+1,X
	LDA #17
	STA ICBLL,X 	;MESSAGE LENGTH
	LDA #0
	STA ICBLL+1,X
	JSR CIOV 	;WRITE IT
	PLA 
	TAX  	;RESTORE X REG
	LDY #OPENERROR
	TYA  	;GIVE ERROR MSG
	STA ICSTA,X 	;TO BASIC
	RTS 
OPEN1
	LDA SECTOR+1
	BNE INUSE
	LDA # <DISKNAME
	STA ICBAL,X 	;SUBSTITUTE NAME
	LDA # >DISKNAME
	STA ICBAL+1,X
	LDA #1 	;SET COMMAND TO 1
	STA COMMAND
LOOKUP
	LDY #0
LOOK
	LDA HATABS,Y 	;FIND DISK HNDLR
	CMP #'D 	;IS IT A 'D'?
	BEQ FOUND 	;YES
	INY  	;NO, SKIP 2 BYTES
	INY 
	INY 
	BPL LOOK 	;LOOK AGAIN
FOUND
	INY 
	LDA HATABS,Y 	;VECT TABLE ADDR
	STA INDEX 	;STORE IN INDEX
	INY 
	LDA HATABS,Y
	STA INDEX+1
	LDY COMMAND 	;OFFSET TO OPEN
;ROUTLINE
	LDA (INDEX),Y 	;TRANSFER CNTRL
	PHA  	;WITH INDIRECT JP
	DEY 
	LDA (INDEX),Y
	PHA  	;TARGET ADDRESS
;             IS NOW ON THE STACK
	LDA FLAG 	;RESTORE THE CHAR
;                SENT BY CIO
RETURN
	RTS  	;DO INDIRECT JUMP
WRITE
	STA FLAG 	;SAVE CHAR SENT
;                BY CIO
	LDA #7 	;USED AS OFFSET
;                TO WRITE ROUTINE
	STA COMMAND
	BNE LOOKUP
;
;THE CLOSE ROUTINE CLOSES THE
;PRINT.SPL FILE,REOPENS IT AND
;NOTES THE FIRST SECTOR. FINALLY
;IT CLOSES THE FILE AND FIRES UP
;THE VBI SERVICE ROUTINE
;
CLOSEIT
	LDA COMMAND 	;LAST CIO OP?
	CMP #7 	;A WRITE?
	BNE RETURN 	;NO, SO EXIT
	LDA #3 	;STORE OFFSET TO
;                TO CLOSE ROUTINE
	STA COMMAND
	JSR LOOKUP 	;CALL DISK CLOSE
;                ROUTINE
	LDX #IOCB1 	;CHANNEL 1
	LDA #OPEN 	;LOAD OPEN CMND
	STA ICCOM,X 	;STORE IN IOCB
	LDA # <DISKNAME
	STA ICBAL,X 	;STORE FILE NAME
	LDA # >DISKNAME
	STA ICBAL+1,X
	LDA #READ 	;OPEN INPUT
	STA ICAX1,X
	JSR CIOV 	;CALL OS I/O
	LDA #NOTE 	;NOTE SECTOR CMND
	STA ICCOM,X
	JSR CIOV 	;CALL I/O ROUTINE
	LDA ICAX3,X 	;GET THE SECTOR #
	STA SECTOR
	LDA ICAX3+1,X
	STA SECTOR+1
	LDA #CLOSE 	;CLOSE COMMAND
	STA ICCOM,X
	JSR CIOV 	;CLOSE THE FILE
	LDA #0 	;INIT WORK AREAS
	STA INDEX
	STA FLAG
	STA RETRY
	STA BUSY
	LDA # <WARMSTART
	STA DOSVEC 	;MAKE SURE CAN'T
	LDA # >WARMSTART 	;USE DOS CMD
	STA DOSVEC+1
	LDA #7 	;CALL AN IND VBI
	LDY # <VB 	;ADDR VBI ROUTINE
	LDX # >VB
	JSR SETVB 	;SET VBI
	RTS 
OUT
	JMP XITVBV
VB
	LDA BUSY 	;DON'T LET VBI
	BNE OUT 	;INTERRUPT ITSELF
	LDA FLAG 	;TIME TO PRINT?
	BNE PRINTER 	;YES
	STA COMMAND 	;INIT WORK AREA
	STA TIMER 	;INITIALIZE TIMER
	LDA #1
	STA DUNIT 	;DRIVE 1
	LDA #READCOM 	;READ COMMAND
	STA DCOMND
	LDA # <DATA 	;DATA BUFFER ADDR
	STA DBUFLO
	LDA # >DATA
	STA DBUFLO+1
	LDA SECTOR 	;LOAD SECTOR NO.
	STA DAUX1
	LDA SECTOR+1
	STA DAUX1+1
	JSR DSKINV 	;READ A SECTOR
	TYA  	;GET I/O STATUS
	BMI OUT 	;WAS IT BAD I/O?
	INC FLAG 	;SET FLAG
	BNE OUT 	;EXIT
PRINTER
	INC TIMER 	;INCREMENT TIMER
	LDA TIMER
	CMP #2 	;SLOW DOWN OUTPUT
	BNE OUT
	LDA #0 	;RESET TIMER
	STA TIMER
	LDA RETRY 	;LAST I/O BAD?
	BNE TRYAGAIN 	;YES,TRY AGAIN
	INC BUSY 	;SET BUSY FLAG
	LDY INDEX 	;CHARACTER INDEX
	LDA DATA,Y 	;LOAD A CHARACTER
;
;THE FOLLOWING ROUTINE EMULATES
;THE OPERATING SYSTEM PRINT
;HANDLER WRITE ROUTINE
;
PRINT
	PHA  	;SAVE CHARACTER
	LDY #$57 	;WRITE COMMAND
	LDX #$28 	;BUFFER SIZE
	LDA #$4E 	;NORMAL MODE
	STA DAUX1
	STY DCOMND
	STX PBUFSZ
	LDX PBPNT
	PLA  	;GET CHARACTER
	STA PRNBUF,X 	;PUT IN BUFFER
	INX  	;INC BUFF POINTER
	CPX PBUFSZ 	;= BUFFER SIZE?
	BEQ BUFFUL
	STX PBPNT 	;SAVE POINTER
	CMP #$9B 	;EOL?
	BEQ BLFILL 	;YES, BLANK FILL
	LDY #1 	;GOOD STATUS
	JMP IN
BLFILL
	LDA #$20 	;LOAD A SPACE
FILLBF	STA PRNBUF,X
	INX 
	CPX PBUFSZ 	;BUFFER FULL?
	BNE FILLBF
BUFFUL
	LDA #0 	;CLEAR BUFFER
	STA PBPNT 	;POINTER
	LDX #$C0 	;SET BUFF POINTER
	LDY #$03
	STX DBUFLO
	STY DBUFLO+1
	LDA #$40 	;STORE DEVICE
	STA DDEVIC
	LDA #1
	STA DUNIT
	LDA #$80 	;DIRECTION=OUTPUT
	STA DSTATS
	LDA PBUFSZ 	;STORE BUFF SIZE
	STA DBYTLO
	LDA #0
	STA DBYTHI
	LDA PTIMOT 	;TIMEOUT VALUE
	STA DTIMLO
	JSR $E459
IN
	DEC BUSY 	;BUST FLAG OFF
	TYA  	;GET STATUS
	BPL AHEAD 	;GOOD I/O
	INC RETRY 	;SET RETRY FLAG
	BNE JP
AHEAD
	LDY INDEX
	INY  	;INC CHAR INDEX
	CPY DATA+127 	;END OF SECTOR?
	BCS NEXTSECTOR 	;YES
	STY INDEX 	;NO, SAVE IT
JP
	JMP OUT
TRYAGAIN
	DEC RETRY 	;RETRY FLAG OFF
	INC BUSY 	;SET BUSY FLAG
;
RETADDR
	JMP BUFFUL 	;RETRY WRITING
;                THE BUFFER
EXITVB
	JSR $00 	;PRINT HANDLER
;                CLOSE ROUTINE
	LDA VBISAV 	;RESTORE VBI VECT
	STA VVBLKD
	LDA VBISAV+1
	STA VVBLKD+1
	LDA # <DUPEXIT 	;RESTORE
;                   DOSVEC
	STA DOSVEC
	LDA # >DUPEXIT
	STA DOSVEC+1
	BNE JP
NEXTSECTOR
	LDA #0 	;RESET WORK AREAS
	STA INDEX
	STA FLAG
	LDA DATA+125 	;GET NEXT SECTOR
	AND #$03 	;GET HIGH BYTE
	STA SECTOR+1
	BEQ NEXT1
	INC COMMAND 	;THERE IS MORE
NEXT1
	LDA DATA+126 	;GET LOW BYTE
	STA SECTOR
	BEQ NEXT2
	INC COMMAND 	;THERE IS MORE
NEXT2
	LDA COMMAND 	;MORE SECTORS?
	BEQ EXITVB 	;NO, END VBI
	JMP OUT 	;EXIT VBI
DISKNAME	.BYTE "D:PRINT.SPL"
MEMSAV
	.BYTE "D:MEM.SAV"
MSG
	.BYTE "PRINT.SPL IN USE",CR	;!!!!!!!! INVERSE CHARS !!!!!!!!
DATA	;  	DISK DATA BUFFER
	*= *+128
DUPEXIT
	LDX #IOCB1 	;CHANNEL 1
	LDA #STATUS 	;GET STATUS OF
	STA ICCOM,X 	;MEM.SAV FILE
	LDA # <MEMSAV
	STA ICBAL,X
	LDA # >MEMSAV
	STA ICBAL+1,X
	JSR CIOV
	CPY #NOTFOUND 	;IS IT THERE?
	BNE JUMPDUP 	;YES, GET OUT
	LDY #0
FINDB
	LDA HATABS,Y 	;FIND B DEVICE
	CMP #'B
	BEQ FOUNDB 	;FOUND IT
	INY 
	INY 
	INY 
	BPL FINDB
FOUNDB
	LDA #0 	;TAKE OUT OF TABL
	STA HATABS,Y
	LDA # <ADDR 	;RESTORE LOMEM
	STA LOMEM 	;TO ORIGINAL VAL
	LDA # >ADDR
	STA LOMEM+1
	LDA DOS 	;RESTORE DOSINI
	STA DOSINI 	;TO ORIGINAL VAL
	LDA DOS+1
	STA DOSINI+1
	LDA DUPSAV 	;RESTORE DOSVEC
	STA DOSVEC 	;TO ORIGINAL VAL
	LDA DUPSAV+1
	STA DOSVEC+1
	JMP (DOSVEC) 	;JUMP TO DUP.SYS
JUMPDUP
	LDA DUPSAV
	STA $00
	LDA DUPSAV+1
	STA $01
	JMP ($00)
RESET
	LDA #0 	;RESET SECTOR NUM
	STA SECTOR
	STA SECTOR+1
	LDA DOS 	;GET DOSINI VECT
	STA DOSADDR+1 	;CREATE JSR ADR
	LDA DOS+1
	STA DOSADDR+2
DOSADDR
	JSR $00 	;DOS INIT
	JMP INITMORE 	;REINIT HANDLER
;                 TABLE
INIT
	LDA DOSINI 	;GET DOSINI VECT
	STA DOS 	;AND SAVE IT
	LDA DOSINI+1
	STA DOS+1
	LDA # <RESET 	;POINT DOSINI TO
	STA DOSINI 	;OUR RESET LOGIC
	LDA # >RESET
	STA DOSINI+1
INITMORE
	LDA DOSVEC 	;SAVE DOSVEC
	STA DUPSAV 	;IN DUPSAV
	LDA DOSVEC+1
	STA DUPSAV+1
	LDA # <DUPEXIT 	;POINT DOSVEC
	STA DOSVEC 	;TO DUPEXIT
	LDA # >DUPEXIT
	STA DOSVEC+1
	LDA VVBLKD 	;SAVE ORIG VBI
	STA VBISAV 	;VECTOR
	LDA VVBLKD+1
	STA VBISAV+1
	LDA # <FINI 	;SET LOMEM TO
	STA LOMEM 	;POINT PAST END
	LDA # >FINI 	;OF THIS PROGRAM
	STA LOMEM+1
	LDY #0
SEEK
	LDA HATABS,Y 	;LOOK IN HANDLER
;                 TABLE
	BEQ PUTIT 	;FOR A FREE SPACE
	CMP #'P 	;IS IT THE
;                PRINTER HANDLER?
	BNE PUT1
	JSR GETIT 	;YES, PROCESS IT
PUT1
	INY  	;SKIP 2 BYTES
	INY 
	INY 
	BPL SEEK
PUTIT
	LDA #'B 	;HANDLER NAME
	STA HATABS,Y 	;IN TABLE
	INY 
	LDA # <ADDR 	;STORE ADDRESS OF
	STA HATABS,Y 	;OUR VECT TABLE
	INY 
	LDA # >ADDR
	STA HATABS,Y
	RTS  	;EXIT
GETIT
	TYA  	;SAVE THE Y REG
	PHA  	;ON THE STACK
	INY 
	LDA HATABS,Y 	;GET VECT TABLE
	STA INDEX 	;ADDRESS
	INY 
	LDA HATABS,Y
	STA INDEX+1
	LDY #2 	;OFFSET TO CLOSE
;                ROUTINE
	CLC 
	LDA (INDEX),Y 	;LOAD CLOSE ADR
	ADC #1 	;ADD 1 TO IT
	STA EXITVB+1 	;MODIFY JSR CODE
	INY 
	LDA (INDEX),Y
	ADC #0
	STA EXITVB+2
	PLA  	;RESTORE Y INDEX
	TAY 
	RTS 
FINI
	*= $02E0
	.WORD INIT
