		* * * * * * * * * * * * *
 ;
 ;
 ;
 ;
 ;  DISK ROUTINES MAY BE MODIFIED AS FOLLOWS:
 ;
 ;  FOR 40-TRACK DRIVES CHANGE TWO BYTES TO
 ;	INCREASE THE STEPPER MOTOR SPEED FOR FASTER I/O
 ;	(SKTYPE) FROM 1BH TO 11H
 ;	(RSTYPE) FROM 0BH TO 01H
 ;  THIS WILL INCREASE STEPPER MOTOR FROM 40MS TO 12MS
 ;  35-TRACK DRIVES WILL NOT OPERATE WITH FAST STEPPER
 ;  TO WRITE A FULL TRACK INSTEAD OF SECTORS,
 ;	(USE ONLY TO RE-FORMAT A TRACK)
 ;  CHANGE (WRTYPE) FROM 0A9H TO 0F4H
 ;  TO READ ONLY THE ID ADDRESS MARKS ON THE DISK,
 ;  CHANGE (WRTYEP) FROM 0A9H TO 0C4H
 ;	WILL READ 6 BYTES FROM DISK:
 ;	TRACK #, HEAD #, SECTOR #, SECTOR LENGTH, 
 ;	AND 2 CRC CHARACTERS
 ;  TO CHANGE THE WRITE SECTOR ROUTINE TO:
 ;	WRITE READ PROTECTED SECTORS (WRTYPE) = 0A9H
 ;	WRITE REGULAR SECTORS (WRTYPE) = 0A8H
 ;  TO WRITE IN NON-STANDARD ID'S:
 ;	(WRTYPE) = 0AAH  OR  0ABH
 ;  FOR STEP COMMAND INSTEAD OF SEEK:
 ;	CHANGE (SKTYPE) FROM 1BH TO 3BH
 ;  HEAD MOTION WILL BE THE SAME AS THE LAST MOVEMENT
 ;  FOR STEP-IN COMMAND INSTEAD OF SEEK:
 ;	CHANGE (SKTYPE) FROM 1BH TO 5BH
 ;  HEAD WILL MOVE ONE TRACK TOWARDS CENTER. (TOWARD 35)
 ;  FOR STEP-OUT COMMAND INSTEAD OF SEEK:
 ;	CHANGE (SKTYPE) FROM 1BH TO 7BH
 ;  HEAD WILL MOVE ONE TRACK TOWARDS TRACK 0.
 ;  TO CHANGE READ SECTOR TO READ TRACK
 ;	CHANGE (RDTYPE) FROM 88H TO 0E5H
 ;  FOR NON-STANDARD IBM READ CHANGE (RDTYPE) TO 80H
 ;  FOR NON-STANDARD IBM WRITE CHANGE (WRTYPE) TO 0A3H
 ; 	BOTH THE ABOVE ARE SECTOR OPERATIONS
 	ORG	4400H		;USE VERY LOW MEMORY
 ENTRY	JP	402DH		;BACK TO DOS
 ;  ROUTINE TO READ MULTIPLE SECTORS INTO RAM
 ;	 L = # OF SECTORS TO READ
 ;	DE = START TRACK/SECTOR
 ;	BC = LOAD ADDRESS
 ;	ZERO FLAG SET IF READ IS SUCCESSFUL
 READ	PUSH	HL		;SAVE LOOP COUNT
 	CALL	STATCK		;CHECK DISK STATUS
 ;  WILL NOT RETURN IF ERROR DETECTED
 READLP	CALL	READ2		;2 TRIES FOR SUCCESS
 	POP	HL		;RESTORE COUNT
 	JP	NZ,DERROR	;BAD AFTER 2 TRIES
 	DEC	L		;REDUCE
 	RET	Z		;DONE WITH READ
 	PUSH	HL		;SAVE AGAIN
 	INC	E		;NEXT SECTOR
 	LD	A,E		;PASS TO ACCUM.
 	SUB	0AH		;10 SECTORS ?
 	JR	NZ,READLP	;MORE SECTORS
 	LD	E,A		;0 TO E
 	INC	D		;NEXT TRACK
 	JR	READLP		;GO SOME MORE
 READ2	PUSH	BC		;SAVE LOAD ADDRESS
 	CALL	READ1		;READ IT ONE TIME
 	POP	HL		;LOAD ADDRESS INTO HL
 	RET	Z		;SUCCESSFUL AFTER 1 TRY
 	LD	B,H		;RESET LOAD ADDRESS
 	LD	C,L		;	INTO BC
 READ1	LD	(37EEH),DE	;TRACK/SECTOR
 	CALL	SELECT		;SELECT DRIVE & TEST
 ;  IF DRIVE IS NOT READY, PROGRAM WILL NOT RETURN
 	LD	HL,37ECH	;COMMAND REGISTER
 	LD	A,(SKTYPE)	;GET SEEK TYPE BYTE
 	LD	(HL),A		;PASS TO CONTROLLER
 	PUSH	AF		;8 MS DELAY
 	POP	AF
 	PUSH	AF
 	POP	AF
 READBZ	LD	A,(HL)		;GET STATUS BYTE
 	RRCA			;SHIFT BUSY BIT
 	JR	C,READBZ	;NOT FOUND YET
 	DEFB	3EH		;LOAD ACCUMULATOR WITH
 RDTYPE	DEFB	88H		;READ SECTOR BYTE
 	LD	(HL),A		;PASS TO CONTROLLER
 	PUSH	DE		;SAVE TRACK/SECTOR
 	LD	DE,37EFH	;DATA TRANSFER ADDRESS
 	PUSH	BC		;4 MORE MS DELAY
 	POP	BC
 	JR	RDTEST		;READ TEST
 RDDONE	RRCA			;SHIFT COMMAND DONE BIT
 	JR	NC,READOK	;NOT SET = DONE
 RDTEST	LD	A,(HL)		;GET STATUS
 	BIT	1,A		;VALID DATA PRESENT ?
 	JR	Z,RDDONE	;IS READ DONE ?
 	LD	A,(DE)		;GET THE VALID BYTE
 	LD	(BC),A		;PUT INTO LOAD BUFFER
 	INC	BC		;POINT TO NEXT
 	JR	RDTEST		;ANY MORE DATA ?
 READOK	LD	A,(HL)		;GET STATUS/RESET LATCH
 	BIT	2,A		;DATA LOST DURING XFER ?
 	POP	DE		;RESTORE TRK/SEC
 	RET	Z		;SUCCESSFUL READ
 	LD	(HL),0D0H	;FORCED INTERRUPT
 	RET			;Z FLAG IS RESET/ERROR
 TRACKS	DEFB	35		;# OF TRACKS ON DISK
 ;  ROUTINE TO WRITE DISK SECTORS
 ;	 L = # OF SECTORS TO WRITE
 ;	DE = START TRACK/SECTOR
 ;	BC = DATA ADDRESS
 ;	ZERO FLAG SET IF WRITE IS SUCCESSFUL
 WRITE	PUSH	HL		;SAVE LOOP COUNT
 ;  SEE SIMILAR REMARKS FOR READ SECTORS
 	CALL	STATCK		;CHECK DISK STATUS
 WRITEL	CALL	WRITE2
 	POP	HL
 	JP	NZ,DERROR	;DISK ERROR ROUTINE
 	DEC	L
 	RET	Z
 	PUSH	HL
 	INC	E
 	LD	A,E
 	SUB	0AH
 	JR	NZ,WRITEL
 	LD	E,A
 	INC	D
 	JR	WRITEL
 WRITE2	PUSH	BC
 	CALL	WRITE1
 	POP	HL
 	RET	Z
 	LD	B,H
 	LD	C,L
 WRITE1	LD	(37EEH),DE
 	CALL	SELECT		;SELECT DRIVE
 	LD	HL,37ECH
 	DEFB	3EH		;LOAD ACCUMULATOR
 SKTYPE	DEFB	1BH		;SLOW SEEK BYTE
 	LD	(HL),A		;PASS TO CONTROLLER
 	PUSH	AF
 	POP	AF
 	PUSH	AF
 	POP	AF
 WRITEZ	LD	A,(HL)
 	RRCA
 	JR	C,WRITEZ
 	DEFB	3EH		;LOAD ACCUMULATOR
 ;  ALL WRITING IS READ PROTECTED UNLESS MODIFIED
 WRTYPE	DEFB	0A9H		;WRITE SECTOR BYTE
 	LD	(HL),A		;PASS TO CONTROLLER
 	PUSH	DE
 	LD	DE,37EFH
 	PUSH	BC
 	POP	BC
 	JR	WRITET
 WRITED	RRCA
 	JR	NC,WRITEO
 WRITET	LD	A,(HL)
 	BIT	1,A
 	JR	Z,WRITED
 	LD	A,(BC)
 	LD	(DE),A
 	INC	BC
 	JR	WRITET
 WRITEO	LD	A,(HL)
 	BIT	2,A
 	POP	DE
 	RET	Z
 	LD	(HL),0D0H
 	RET			;FLAGS ARE SET
 ;  THIS ROUTINE WILL CATCH ALL DISK ERRORS
 ;	A WILL CONTAIN LAST STATUS BYTE
 DERROR	BIT	2,A		;DATA LOST FLAG
 	LD	HL,ERMSG1	;ERROR MESSAGE
 	JR	NZ,ERSHOW	;SHOW IS THAT'S IT
 	BIT	4,A		;TRACK/SECTOR NOT FOUND
 	LD	HL,ERMSG2
 	JR	NZ,ERSHOW
 	BIT	3,A		;ERROR IN DATA FIELD
 	LD	HL,ERMSG3
 	JR	NZ,ERSHOW
 	LD	HL,ERMSG4
 ERSHOW	CALL	SHOW
 	JP	STOP		;TERMINATE PROGRAM
 SHOW	LD	A,(HL)		;GET A CHARACTER
 	INC	HL		;POINT TO NEXT
 	CP	3		;TERMINATOR ?
 	RET	Z		;DONE IF YES
 	CALL	33H		;DISPLAY THE BYTE
 	JR	SHOW		;BACK FOR MORE
 ERMSG1	DEFB	0DH
 	DEFM	'DATA LOST DURING DISK I/O OPERATION.'
 	DEFB	0DH
 	DEFM	'DAMAGE TO DATA MAY HAVE OCCURED.'
 	DEFB	3
 ERMSG2	DEFB	0DH
 	DEFM	'TRACK/SECTOR NOT FOUND DURING DISK'
 	DEFM	' I/O OPERATION.'
 	DEFB	3
 ERMSG3	DEFB	0DH
 	DEFM	'ERROR IN DATA ID FIELD ON DISKETTE.'
 	DEFB	3
 ERMSG4	DEFB	0DH
 	DEFM	'UNIDENTIFIED ERROR HAS BEEN DETECTED.'
 	DEFB	3
 SELECT	DEFB	3EH		;LOAD ACCUMULATOR
 DRIVE	DEFB	1		;WITH THIS BYTE
 	LD	(37E1H),A	;PASS TO CONTROLLER
 	RET			;DONE WITH SELECT
 STATCK	PUSH	BC		;SAVE ALL THE POINTERS
 	PUSH	DE
 	PUSH	HL
 	CALL	SELECT		;SELECT THE DRIVE
 	LD	BC,0		;1 SECOND DELAY LOOP
 	CALL	60H		;TO WAIT FOR MOTOR SPEED
 	LD	A,(37ECH)	;GET STATUS BYTE
 	LD	HL,ERMSG5	;DRIVE NOT READY
 	BIT	7,A
 	JP	NZ,ERSHOW	;SHOW THE ERROR
 	LD	HL,ERMSG6	;DRIVE NOT IN SYSTEM
 	BIT	2,A
 	JP	Z,ERSHOW
 	LD	HL,ERMSG7	;WRITE PROTECTED
 	BIT	6,A
 	JP	NZ,ERSHOW
 	LD	HL,ERMSG8	;NO SYSTEM IN DRIVE
 	LD	BC,00CDH	;LOOP COUNTER
 LP1	DEC	BC
 	LD	A,B		;GET MSB
 	OR	C		;ANY BITS SET ?
 	JP	Z,ERSHOW
 	LD	(37ECH),A	;READY YET ?
 	AND	2
 	JR	NZ,LP1		;WAIT SOME MORE
 	LD	HL,ERMSG9	;DOOR NOT CLOSED
 	LD	BC,199DH	;LOOP COUNT
 LP2	DEC	BC
 	LD	A,B
 	OR	C
 	JP	Z,ERSHOW
 	LD	A,(37ECH)
 	AND	2
 	JR	Z,LP2
 	LD	DE,0
 	LD	BC,00BAH
 	LD	HL,ERMSG0	;NO DISKETTE IN DRIVE
 LP3	DEC	BC
 	LD	A,B
 	OR	C
 	JP	Z,ERSHOW
 	INC	DE
 	LD	A,(37ECH)
 	AND	2
 	JR	NZ,LP3
 	LD	BC,1720H
 	LD	HL,ERMSG9	;DOOR NOT CLOSED
 LP4	DEC	BC
 	LD	A,B
 	OR	C
 	JP	Z,ERSHOW
 	INC	DE
 	LD	A,(37ECH)
 	AND	2
 	JR	Z,LP4
 	LD	HL,0EACBH
 	ADD	HL,DE
 	LD	HL,ERMSGU	;DISKETTE HARD SECTORED
 	JP	NC,ERSHOW
 	POP	HL		;RESTORE ALL POINTERS
 	POP	DE
 	POP	BC
 	RET			;DONE WITH DIAGNOSTICS
 ERMSG5	DEFB	0DH
 	DEFM	'DRIVE IS NOT READY FOR DATA TRANSFER.'
 	DEFB	3
 ERMSG6	DEFB	0DH
 	DEFM	'DRIVE IS NOT IN THE SYSTEM.'
 	DEFB	3
 ERMSG7	DEFB	0DH
 	DEFM	'DISKETTE IS WRITE PROTECTED.'
 	DEFB	3
 ERMSG8	DEFB	0DH
 	DEFM	'NO SYSTEM IN THE DRIVE.'
 	DEFB	3
 ERMSG9	DEFB	0DH
 	DEFM	'DOOR NOT CLOSED ON DRIVE.'
 	DEFB	3
 ERMSG0	DEFB	0DH
 	DEFM	'NO DISKETTE IN DRIVE.'
 	DEFB	3
 ERMSGU	DEFB	0DH
 	DEFM	'DISKETTE IS HARD SECTORED AND'
 	DEFM	' IS UNUSABLE.'
 	DEFB	3
 STOP	CALL	DISPLY		;DISPLAY FOLLOWING
 	DEFW	0D0DH
 	DEFM	'PROGRAM CANNOT CONTINUE '
 	DEFM	'BECAUSE OF DETECTED ERROR.'
 	DEFB	0DH
 	DEFM	'PRESS <RESET> BUTTON TO RESTART.'
 	DEFB	0
 STAY	JP	STAY		;ENDLESS LOOP
 ;  THE ABOVE LOOP MAY BE INTERCEPTED ELSEWHERE
 ;  DATA MUST IMMEDIATELY FOLLOW THE CALL INSTRUCTION
 ;	AND MUST BE TERMINATED WITH 0
 ;  THE CURSOR POSITION IS TAKEN FROM 4020H AND IS
 ;	MAINTAINED BY CALLS AT 33H.
 ;  LOWER CASE CHARACTERS WILL BE DISPLAYED IF THE
 ;	LOWER CASE MOD IS INSTALLED.
 DISPLY	POP	DE		;POINT TO DATA
 DISPLP	LD	HL,(4020H)	;GET CURSOR POSTION
 	LD	A,(DE)		;GET DATA BYTE
 	INC	DE		;BUMP POINTER
 	OR	A		;SET FLAGS
 	JR	Z,DISDN		;TERMINATOR
 	CP	20H		;DISPLAYABLE ?
 ;  USE ROM TO DISPLAY CONTROL CHARACTERS
 	JR	C,CARRET	;DO DOS ROUTINE
 	LD	(HL),A		;PUT INTO VIDEO
 	CP	(HL)		;IS IT STILL THERE
 ;  IF LOWER CASE MOD NOT INSTALLED, ADJUST TO UPPER CASE
 	JR	Z,DISOK		;Z=LOWERCASE INSTALLED
 	SUB	20H		;MAKE IT UPPER CASE
 	LD	(HL),A		;RE-DISPLAY IT
 DISOK	INC	HL		;POINT TO NEXT
 	LD	(4020H),HL	;UPDATE CURSOR
 	JR	DISPLP		;GO TO LOOP
 CARRET	PUSH	AF		;SAVE INPUT CHAR
 	EXX			;SAVE POINTERS
 	POP	AF		;GET CHARACTER
 	CALL	33H		;DISPLAY A REG
 	EXX			;RESTORE POINTERS
 	JR	DISPLP		;GET ANOTHER CHARACTER
 ;  THE FOLLOWING ROUTINE WILL CONVERT A NUMBER TO ASCII
 ;	A = VALUE TO BE CONVERTED
 ;	EXIT WITH HL = 2 ASCII VALUES, HIGH AND LOW
 ASCII	LD	C,A		;SAVE NUMBER
 	SRL	A		;ALIGN TO HIGH DIGIT
 	SRL	A
 	SRL	A
 	SRL	A
 	CALL	ASCTS		;CONVERT TO ASCII
 	LD	H,A		;SAVE IN H
 	LD	A,C		;RESTORE ORIGINAL
 	AND	0FH		;MASK HIGH NIBBLE
 	CALL	ASCTS		;CONVERT THAT TOO
 	LD	L,A		;PASS TO L
 	RET
 ASCTS	ADD	A,30H		;CONVERT
 	CP	3AH		;TEST FOR 0-9
 	JP	M,ASCTSD	;GO IF 0-9
 	ADD	A,7		;ADJUST FOR LETTER
 ASCTSD	RET			;DONE
 ;  THE FOLLOWING ROUTINE WILL RETURN THE INTEGER
 ;	VALUE OF A STRING
 ;	HL => STRING TEXT OF UP TO 2 ASCII CHARACTERS
 ;	C WILL RETURN WITH THE VALUE OF THE STRING
 ;	A WILL RETURN WITH TERMINATOR ( , - ENTER )
 ;	HL WILL RETURN => CHARACTER AFTER TERMINATOR
 ;  USEFUL FOR MULTIPLE INPUT SUCH AS:    3,5-9,12,14 <EN>
 TEMPST	DEFW	0H		;TEMPORARY STORAGE
 VALUE	LD	A,(HL)		;GET 1'ST CHAR.
 	INC	HL		;POINT TO NEXT
 	CP	0DH		;NO INPUT ?
 	JP	Z,BADINP	;NO GOOD
 	SUB	30H		;REMOVE ASCII
 	JP	C,BADINP	;NO GOOD
 	CP	0AH		;BIGGER THAN 9 ?
 	JP	C,NOADJ		;DON'T ADJUST
 	SUB	7		;ADJUST FOR LETTER
 NOADJ	CP	10H		;BIGGER THAN 1 HEX DIGIT?
 	JP	NC,BADINP	;NO GOOD
 	LD	C,A		;SAVE IN CASE OF ONE CHAR
 	SLA	A		;SHIFT TO UPPER NIBBLE
 	SLA	A
 	SLA	A
 	SLA	A
 	LD	(TEMPST),A	;SAVE FOR A MINUTE
 	LD	A,(HL)		;GET IT
 	INC	HL		;POINT TO NEXT
 	CP	0DH		;ONE DIGIT SUPPLIED ?
 	RET	Z		;	YES IF ZERO
 	CP	2CH		;COMMA ?
 	RET	Z		;	YES IF ZERO
 	CP	2DH		;DASH ?
 	RET	Z		;	YES IF ZERO
 	SUB	30H		;REMOVE ASCII
 	JP	C,BADINP	;NO GOOD
 	CP	0AH		;BIGGER THAN 9 ?
 	JP	C,NOADJ2	;DON'T ADJUST
 	SUB	7		;ADJUST FOR LETTER
 NOADJ2	CP	10H		;BIGGER THAN 1 HEX DIGIT?
 	JP	NC,BADINP	;NO GOOD
 	LD	C,A		;PASS TO C REG.
 	LD	A,(TEMPST)	;GET LAST CHAR.
 	ADD	A,C		;ADD 'EM
 	LD	C,A		;GIVE IT BACK
 	LD	A,(HL)		;PASS BACK TERMINATOR
 	INC	HL		;POINT TO NEXT BYTE
 	RET			;DONE WITH IT
 BADINP	LD	C,0		;NO VALUE
 	DEC	HL		;POINT TO BAD POINT
 	RET			;DONE
 ;  FLASHING CURSOR ROUTINE
 ;  B = LENGTH OF INPUT ( 1-255 )
 ;  CURSOR POSITION AT (4020H), MAINTAINED BY ROM
 ;	RETURN
 ;	A = 1'ST CHARACTER INPUT IN ASCII
 ;	B = LENGTH OF INPUT
 ;	HL => FIRST CHARACTER OF STRING
 ;	DE => LAST CHARACTER+1 ON VIDEO MEMORY
 ;	CALL	GETSTR
 STRING	DEFS	100H		;256 BYTE BUFFER
 LENGTH	DEFB	0		;LENGTH OF INPUT STRING
 REQLEN	DEFB	0		;REQUESTED LENGTH
 CHAR	DEFB	0		;LAST INPUT CHARACTER
 GETSTR	LD	A,B		;GET REQUESTED LENGTH
 	LD	(REQLEN),A	;SAVE IT
 NEWST	LD	HL,(4020H)	;GET CURSOR POSIT
 	LD	DE,STRING	;POINT TO BUFFER
 	LD	A,20H		;ASCII SPACE
 LOOP15	LD	(HL),A		;INTO VIDEO
 	LD	(DE),A		;INTO BUFFER
 	INC	DE		;	NEXT
 	INC	HL		;    TYPED INTO
 	DJNZ	LOOP15		;NEXT SPACE
 	XOR	A		;ZERO THE ACCUMULATOR
 	LD	(LENGTH),A	;INITIALIZE LENGTH
 	LD	HL,STRING	;SET POINTER TO BEGINNING
 ;					OF BUFFER AREA
 	LD	DE,(4020H)	;GET CURSOR POSITION
 SCAN	LD	A,8FH		;CURSOR CHARACTER
 	LD	(DE),A		;CURSOR ON
 	LD	BC,500H		;DELAY COUNT
 LOOP1	DEC	BC		;START COUNT
 	PUSH	BC		;SAVE COUNT
 	PUSH	DE		;MUST SAVE
 	PUSH	IY		;   <DE> AND <IY>
 	CALL	2BH		;ROM KEYBOARD SCAN
 	POP	IY		;RESTORE
 	POP	DE		;   <DE> AND <IY>
 	POP	BC		;RESTORE COUNT
 	OR	A		;SET FLAGS
 	JP	NZ,GOTONE	;IF KEY WAS PRESSED
 	LD	A,B		;TEST <BC> REG. FOR
 	OR	C		;   ZERO VALUE
 	JR	NZ,LOOP1	;GO BACK IF NOT DONE
 	LD	A,20H		;CURSOR CHARACTER
 	LD	(DE),A		;CURSOR OFF
 	LD	BC,500H		;DELAY COUNT
 LOOP2	DEC	BC		;START COUNT
 	PUSH	BC		;SAVE COUNT
 	PUSH	DE		;MUST SAVE
 	PUSH	IY		;   <DE> AND <IY>
 	CALL	2BH		;ROM KEYBOARD SCAN
 	POP	IY		;RESTORE
 	POP	DE		;   <DE> AND <IY>
 	POP	BC		;RESTORE COUNT
 	OR	A		;SET FLAGS
 	JP	NZ,GOTONE	;NEW KEY IF <ACC> >< 0
 	LD	A,B		;GET VALUE OF B
 	OR	C		;ANY BITS ON ?
 	JR	NZ,LOOP2	;NEXT LOOP
 	JR	SCAN		;DO IT AGAIN
 ;  KEY PRESSED IS IN <A> REG.
 GOTONE	LD	(CHAR),A	;SAVE INPUT CHARACTER
 	CP	0DH		;IS IT A CARRIAGE RETURN
 	JP	Z,DONE		;GO IF IT IS
 	CP	8		;IS IT A BACKSPACE
 	JR	Z,BCKSPA	;SEE IF IT'S OK
 	CP	18H		;SHIFT LEFT ARROW
 	JR	Z,NEWST		;INITIALIZE IF YES
 	CP	20H		;SEE IF A NON-ALPHA KEY
 	JP	C,SCAN		;   WAS PRESSED
 	LD	A,(REQLEN)	;GET REQUESTED LENGTH
 	LD	B,A		;GIVE VALUE TO <B> REG.
 	LD	A,(LENGTH)	;GET CURRENT LENGTH
 	CP	B		;COMPARE VALUES
 	JR	NC,SCAN		;TOO MANY CHARACTERS
 ;  HERE THE NEW KEY IS DISPLAYED AND STORED IN <STRING>
 	LD	A,(CHAR)	;RESTORE INPUT CHARACTER
 	LD	(DE),A		;PUT IT ON VIDEO
 	LD	(HL),A		;PUT IT IN BUFFER
 	INC	DE		;INCREMENT <HL> AND <DE>
 	INC	HL		;    TABLE POINTERS
 	LD	A,(LENGTH)	;GET LENGTH
 	INC	A		;ADD 1
 	LD	(LENGTH),A	;SAVE VALUE
 	JR	SCAN		;GET NEXT KEY
 BCKSPA	LD	A,(LENGTH)	;GET CURRENT LENGTH
 	OR	A		;SET FLAGS
 	JR	Z,SCAN		;NO CHARACTERS IN BUFFER
 	DEC	A		;SUBTRACT 1
 	LD	(LENGTH),A	;NEW LENGTH
 	LD	A,20H		;CURSOR OFF CHAR.
 	LD	(DE),A		;CURSOR OFF
 	LD	(HL),A		;PUT SPACE IN BUFFER
 	DEC	HL		;DECREMENT BOTH
 	DEC	DE		;    TABLE POINTERS
 	JR	SCAN		;GET ANOTHER KEY
 DONE	LD	A,20H		;ASCII - SPACE
 	LD	(DE),A		;CURSOR OFF
 	LD	(HL),0DH	;CARRIAGE RETURN
 	LD	A,(LENGTH)	;GET LENGTH
 	LD	B,A		;GIVE TO B REG.
 	LD	A,(STRING)	;GET FIRST INPUT CHAR.
 	LD	HL,STRING	;POINT TO BUFFER
 	LD	(4020H),DE	;UPDATE CURSOR
 	RET			;ALL DONE
 ;  THE FOLLOWING IS A STROBE ROUTINE FOR THE KEYBOARD
 STROBE	CALL	2BH		;SCAN KEYBOARD
 	OR	A		;SET FLAGS
 	JR	Z,STROBE	;WAIT TILL ONE PRESSED
 	RET			;DONE
 ;  THE FOLLOWING WILL SIMULATE SET, RESET, AND POINT
 ;	DE = Y,X COORDINATES
 ;		X = 0 TO 127  /  Y = 0 TO 47
 ;	Z FLAG SET IF TEST
 SET	LD	A,0C6H		;SET INSTRUCTION
 	JR	SETTST		;STORE IT
 RESET	LD	A,86H		;RESET INSTRUCTION
 	JR	SETTST		;SAVE IT
 POINT	LD	A,46H		;BIT INSTRUCTION
 SETTST	LD	(INST+1),A	;SAVE THE INSTRUCTION
 GETY	LD	A,D		;GET Y VECTOR
 	LD	B,0FFH		; -1
 SIMLP	INC	B		;SUBS FOR DIVISION
 	SUB	3		;	BY THREE
 	JP	P,SIMLP		;GO IF NOT MINUS
 	ADD	A,3		;YQ IN B, YR IN A
 	SLA	A		;YR * 2
 	LD	C,A		;SAVE THAT
 	LD	L,B		;YQ IN L
 	LD	H,0		;YQ IN HL
 	LD	B,6		;COUNTER FOR MULT
 SIMLP1	ADD	HL,HL		;YQ*2
 	DJNZ	SIMLP1		;GO IF NOT YQ*64
 	LD	D,0		;DE NOW HAS X
 	SRL	E		;XQ
 	JR	NC,SIMLP2	;GO IN XR NE 1
 	INC	C		;C HAS YR*2+XR
 SIMLP2	ADD	HL,DE		;HL HAS YQ*2+XQ
 	LD	DE,3C00H	;START OF VIDEO
 	ADD	HL,DE		;HL HAS DISPLACEMENT
 	SLA	C		;ALIGN TO FIELD
 	SLA	C
 	SLA	C
 	LD	A,(INST+1)	;GET THE INSTRUCTION
 	ADD	A,C		;SET THE FIELD
 	LD	(INST+1),A	;STORE IT
 INST	DEFB	0CBH		;BIT, SET, RES BYTE
 	DEFB	0		;TO BE FILLED IN
 	SET	7,(HL)		;FOR GRAPHICS
 	RET			;DONE
 ;  SUBROUTINE TO FILL MEMORY
 ;	D = BYTE TO FILL WITH
 ;	HL => START OF AREA
 ;	BC = # OF BYTES TO FILL
 FILL	LD	(HL),D		;STORE A BYTE
 	INC	HL		;POINT TO NEXT
 	DEC	BC		;REDUCE COUNT
 	LD	A,B		;GET MS
 	OR	C		;ANY BITS ON ?
 	JR	NZ,FILL		;KEEP GOING
 	RET			;DONE
 ;  SUBROUTINE TO MOVE MEMORY, BLOCKS MAY BE OVERLAPPING
 ;	HL = SOURCE START
 ;	DE = DESTINATION START
 ;	BC = # OF BYTES TO MOVE
 MOVE	PUSH	HL		;SAVE SOURCE
 	OR	A		;CLEAR CARRY FLAG
 	SBC	HL,DE		;COMPARE STARTS
 	POP	HL		;RESTORE SOURCE
 	JP	C,MOVEBK	;GO IF MOVE BACK
 	LDIR			;MOVE FOREWARD
 	RET			;DONE
 MOVEBK	ADD	HL,BC		;POINT TO END +1
 	DEC	HL		;POINT TO END
 	EX	DE,HL		;SWAP POINTERS
 	ADD	HL,BC		;POINT TO END +1
 	DEC	HL		;POINT TO END
 	EX	DE,HL		;SWAP BACK
 	LDDR			;MOVE BACK
 	RET			;DONE
 ;  THE FOLLOWING IS CALLED IF LOWER CASE
 ;	DRIVERS ARE NEEDED
 ;  THIS NEEDS TO BE CALLED ONLY ONCE TO SET UP
 ;	THE NECESSARY TABLES AND VECTORS.
 ;  THE UPPER CASE LOCK KEY IS:    <SHIFT> 0
 ;  TO START IN UPPER CASE, CHANGE:
 ;	LD	HL,0     TO     LD	HL,1
 ;
 LCFIX	LD	HL,KYBRD	;KEYBOARD DRIVER
 	LD	(4016H),HL	;INTERCEPT ROM DRIVER
 	LD	HL,VIDEO	;VIDEO DRIVER
 	LD	(401EH),HL	;INTERCEPT
 	LD	HL,LPRINT	;LINEPRINTER DRIVER
 	LD	(4026H),HL	;INTERCEPT
 	LD	HL,0		;START IN LOWERCASE
 	LD	(4019H),HL	;	ALWAYS ZERO
 	RET			;DONE WITH LC FIX
 KEY0	PUSH	BC		;SAVE ROW POINTER
 	LD	BC,04CBH	;DELAY LOOP FOR DEBOUNCE
 	CALL	60H		;DO THE LOOP
 	POP	BC		;RESTORE ROW
 	JR	KEY6		;BACK FOR TEST
 ;  IF THE NEW KEY PRESSED IS THE SAME AS THE LAST
 ;	IT IS REQUIRED THAT IT STILL BE PRESSED
 ;	AFTER THE DEBOUNCE ROUTINE
 KYBRD	LD	BC,3801H	;POINT TO KEYBOARD MEM.
 	LD	HL,4036H	;INPUT BUFFER
 	LD	D,0		;ROW COUNTER
 KYLOOP	LD	A,(BC)		;STROBE A ROW
 	LD	E,A		;SAVE KEY IF THERE
 	XOR	(HL)		;FIX BITS
 	LD	(HL),E		;PASS BACK
 	AND	E		;SAME AS LAST KEY ?
 	JR	NZ,KEY1		;NOT A NEW KEY
 	INC	D		;BUMP ROW COUNTER
 	INC	L		;NEXT MEMORY POINTER
 	RLC	C		;NEXT KEYBOARD ADDRESS
 	RET	M		;DONE IF LAST ROW
 	JR	KYLOOP		;TEST NEXT ROW
 KEY1	LD	E,A		;PASS TO E REG
 	LD	A,D		;GET ROW COUNT
 	RLA			;ALIGN BITS
 	RLA
 	RLA
 	LD	D,A		;PASS IT BACK
 	LD	A,E		;GET TEST VALUE BACK
 KEY2	RRCA			;ADJUST BITS
 	JR	C,KEY3		;DONE WITH ADJUST
 	INC	D		;BUMP COUNTER
 	JR	KEY2		;KEEP SHIFTING
 KEY3	LD	HL,3880H	;SHIFT KEY ADDRESS
 	BIT	0,(HL)		;PRESSED ?
 	JR	Z,KEY4		;NOT PRESSED
 	SET	6,D		;SET LOWER CASE BIT
 KEY4	LD	HL,4019H	;ALWAYS ZERO BYTE
 	BIT	0,(HL)		;IS IT RESET ?
 	JR	Z,KEY5		;YES IT IS
 	SET	7,D		;GRAPHICS BYTE
 KEY5	JR	KEY0		;DEBOUNCE LOOP
 KEY6	AND	E		;COMPARE
 	JR	NZ,KEY7		;NOT SAME
 	RET			;DONE
 KEY7	LD	HL,KTABLE	;KEY INDEX TABLE
 	LD	E,D		;GET THE KEY
 	LD	D,0		;KEY NOW IN DE
 	ADD	HL,DE		;POINT TO TABLE ENTRY
 	LD	A,(HL)		;GET THE ASCII
 	CP	80H		;BIT 7 ON ?
 	JR	NZ,KEY8		;NO IT ISN'T
 	LD	A,1		;FLAG VALUE
 	LD	HL,4019H	;ALWAYS ZERO ?
 	XOR	(HL)		;MASK BITS
 	LD	(HL),A		;SET FLAG FOR GRAPHICS
 	XOR	A		;ZERO IT 
 	RET			;DONE
 KEY8	CP	1		;VALUE OF 1 ?
 	RET	NZ		;NOT GRAPHICS
 	RST	28H		;FIX ASCII
 	RET			;DONE
 ;  FOLLOWING IS THE LOWER CASE VIDEO DRIVER
 VIDEO	LD	L,(IX+3)	;GET THE CURSOR
 	LD	H,(IX+4)	;	POSITION
 	JP	C,049AH		;DECODE ROUTINE
 	LD	A,(IX+5)	;GET CURSOR CHARACTER
 	OR	A		;SET FLAGS
 	JR	Z,VIDEO1	;NO BITS ON
 	LD	(HL),A		;CURSOR ON
 VIDEO1	LD	A,C		;GET CHARACTER
 	CP	20H		;SPACE ?
 	JP	C,0506H		;DECODE CONTROL CODES
 	CP	80H		;BIT 7 SET ?
 	JP	NC,04A6H	;SEE IF PRINTABLE CHAR.
 	PUSH	HL		;MUST SAVE
 	PUSH	DE		;	'EM BOTH
 	LD	HL,VTABLE	;VIDEO INDEX TABLE
 	LD	E,A		;PASS DISPLACEMENT
 	LD	D,0		;	TO DE REGS.
 	ADD	HL,DE		;POINT TO TABLE BYTE
 	LD	A,(HL)		;GET THE BYTE
 	POP	DE		;RESTORE
 	POP	HL		;	BOTH
 	JP	047DH		;BYPASS UPPER CASE ADJUST
 ;  FOLLOWING IS THE ENTRY POINT TO DESIRED
 ;	LINEPRINTER DRIVER
 LPRINT	JP	058DH		;RESIDENT ROM DRIVER
 ;  FOLLOWING IS THE KEYBOARD LOOK-UP TABLE
 KTABLE	DEFB	40H
 ;  ALL DEFW BYTES ARE REVERSED WHEN ASSEMBLED
 	DEFW	6261H
 	DEFW	6463H
 	DEFW	6665H
 	DEFW	6867H
 	DEFW	6A69H
 	DEFW	6C6BH
 	DEFW	6E6DH
 	DEFW	706FH
 	DEFW	7271H
 	DEFW	7473H
 	DEFW	7675H
 	DEFW	7877H
 	DEFW	7A79H
 	DEFW	0000H
 	DEFW	0000H
 	DEFB	00H
 	DEFW	3130H
 	DEFW	3332H
 	DEFW	3534H
 	DEFW	3736H
 	DEFW	3938H
 	DEFW	3B3AH
 	DEFW	2D2CH
 	DEFW	2F2EH
 	DEFB	0DH
 	DEFB	1FH
 	DEFB	01H
 	DEFB	5BH
 	DEFB	0AH
 	DEFW	0908H
 	DEFB	20H
 	DEFW	0FFFFH
 	DEFW	0FFFFH
 	DEFW	0FFFFH
 	DEFB	0FFH
 	DEFB	00H
 	DEFB	60H
 	DEFW	4241H
 	DEFW	4443H
 	DEFW	4645H
 	DEFW	4847H
 	DEFW	4A49H
 	DEFW	4C4BH
 	DEFW	4E4DH
 	DEFW	504FH
 	DEFW	5251H
 	DEFW	5453H
 	DEFW	5655H
 	DEFW	5857H
 	DEFW	5A59H
 	DEFW	0FFFFH
 	DEFW	0FFFFH
 	DEFB	0
 	DEFB	80H
 	DEFW	2221H
 	DEFW	2423H
 	DEFW	2625H
 	DEFW	2827H
 	DEFW	2A29H
 	DEFB	2BH
 	DEFW	3D3CH
 	DEFW	3F3EH
 	DEFB	0DH
 	DEFB	1FH
 	DEFB	1
 	DEFB	1BH
 	DEFB	1AH
 	DEFB	18H
 	DEFB	19H
 	DEFB	20H
 	DEFW	0FFFFH
 	DEFW	0FFFFH
 	DEFW	0FFFFH
 	DEFB	0
 	DEFW	4140H
 	DEFW	4342H
 	DEFW	4544H
 	DEFW	4746H
 	DEFW	4948H
 	DEFW	4B4AH
 	DEFW	4D4CH
 	DEFW	4F4EH
 	DEFW	5150H
 	DEFW	5352H
 	DEFW	5554H
 	DEFW	5756H
 	DEFW	5958H
 	DEFW	0000H
 	DEFW	0000H
 	DEFB	00H
 	DEFW	3130H
 	DEFW	3332H
 	DEFW	3534H
 	DEFW	3736H
 	DEFW	3938H
 	DEFW	3B3AH
 	DEFW	2D2CH
 	DEFW	2F2EH
 	DEFB	0DH
 	DEFB	1FH
 	DEFB	01H
 	DEFB	5BH
 	DEFB	0AH
 	DEFB	08H
 	DEFB	09H
 	DEFB	20H
 	DEFW	0FFFFH
 	DEFW	0FFFFH
 	DEFW	0FFFFH
 	DEFB	0FFH
 	DEFB	00H
 	DEFB	60H
 	DEFW	4241H
 	DEFW	4443H
 	DEFW	4645H
 	DEFW	4847H
 	DEFW	4A49H
 	DEFW	4C4BH
 	DEFW	4E4DH
 	DEFW	504FH
 	DEFW	5251H
 	DEFW	5453H
 	DEFW	5655H
 	DEFW	5857H
 	DEFW	5A59H
 	DEFW	0FFFFH
 	DEFW	0FFFFH
 	DEFB	0
 	DEFB	80H
 	DEFW	2221H
 	DEFW	2423H
 	DEFW	2625H
 	DEFW	2827H
 	DEFW	2A29H
 	DEFB	2BH
 	DEFW	3D3CH
 	DEFW	3F3EH
 	DEFB	0DH
 	DEFB	1FH
 	DEFB	01H
 	DEFB	1BH
 	DEFB	1AH
 	DEFW	1918H
 	DEFB	20H
 	DEFW	0FFFFH
 	DEFW	0FFFFH
 	DEFW	0FFFFH
 	DEFB	0FFH
 	DEFB	0
 ;  NOW THE VIDEO LOOK-UP TABLE
 VTABLE	DEFW	2020H		;CONTROL CHARACTERS
 	DEFW	2020H
 	DEFW	2020H
 	DEFW	2020H
 	DEFW	2020H
 	DEFW	2020H
 	DEFW	2020H
 	DEFW	2020H
 	DEFW	2020H
 	DEFW	2020H
 	DEFW	2020H
 	DEFW	2020H
 	DEFW	2020H
 	DEFW	2020H
 	DEFW	2020H
 	DEFW	2020H
 	DEFW	2120H
 	DEFW	2322H
 	DEFW	2524H
 	DEFW	2726H
 	DEFW	2928H
 	DEFW	2B2AH
 	DEFW	2D2CH
 	DEFW	2F2EH
 	DEFW	3130H
 	DEFW	3332H
 	DEFW	3534H
 	DEFW	3736H
 	DEFW	3938H
 	DEFW	3B3AH
 	DEFW	3D3CH
 	DEFW	3F3EH
 	DEFW	4140H
 	DEFW	4342H
 	DEFW	4544H
 	DEFW	4746H
 	DEFW	4948H
 	DEFW	4B4AH
 	DEFW	4D4CH
 	DEFW	4F4EH
 	DEFW	5150H
 	DEFW	5352H
 	DEFW	5554H
 	DEFW	5756H
 	DEFW	5958H
 	DEFW	5B5AH
 	DEFW	5D5CH
 	DEFW	5F5EH
 	DEFB	40H
 	DEFW	6261H
 	DEFW	6463H
 	DEFW	6665H
 	DEFW	6867H
 	DEFW	6A69H
 	DEFW	6C6BH
 	DEFW	6E6DH
 	DEFW	706FH
 	DEFW	7271H
 	DEFW	7473H
 	DEFW	7675H
 	DEFW	7877H
 	DEFW	7A79H
 	DEFW	2020H
 	DEFW	2020H
 	DEFB	20H
 ;  THE FOLLOWING IS A TABLE SEARCH ROUTINE
 ;	A  = KEY
 ;	HL = TABLE START
 ;	DE = LENGTH OF ENTRIES
 ;	C  = # OF ENTRIES
 ;EXIT	Z FLAG SET IF FOUND
 ;	HL = LOCATION OF MATCH
 ;	BC = CURRENT # LEFT
 ;	DE = UNCHANGED
 ;  IF BC > 0 THEN ANOTHER CALL MAY BE MADE IMMEDIATELY
 ;	AS ALL POINTERS ARE SET TO GO.
 SEARCH	LD	B,0		;BC NOW HAS NUMBER
 SEARLP	CPI			;COMPARE A WITH (HL)
 	JP	Z,FOUND		;GO IF FOUND
 	JP	PO,NOFIND	;AT END AND NOT FOUND
 	ADD	HL,DE		;POINT TO NEXT +1
 	DEC	HL		;CURRENT + LENGTH
 	JR	SEARLP		;TRY NEXT ENTRY
 FOUND	DEC	HL		;ADJUST TO FOUND LOC
 NOFIND	RET			;DONE
 FLALEN	DEFB	0		;LENGTH TO FLASH
 ;  ROUTINE TO SIMULATE REVERSE FIELD ON THE VIDEO
 ;  ROUTINE WILL FLASH GRAPHIC BLOCKS AND THE TEXT
 ;	VERY RAPIDLY AND WILL WAIT FOR A ONE KEY
 ;	INPUT FROM THE KEYBOARD.
 ;	USEFUL FOR MENU PROMPTING
 ;  START OF AREA TO FLASH IS IN (4020H) CURSOR POSITION
 ;  B = LENGTH OF AREA TO FLASH
 ;	RETURN
 ;  HL => INPUT CHARACTER
 ;   A = INPUT CHARACTER IN ASCII
 FLASH	LD	A,B		;GET REQUESTED LENGTH
 	LD	(FLALEN),A	;SAVE VALUE
 FLON	CALL	SETUP		;GET VALUES
 	LDIR			;MOVE VIDEO TO BUFFER
 	CALL	LITE		;LIGHT UP AREA
 	CALL	QSCAN		;QUICK KEY SCAN
 	JR	FLOFF		;TURN ON ASCII
 QSCAN	LD	BC,40H		;DELAY COUNT
 QSCALP	PUSH	BC		;MUST SAVE
 	CALL	2BH		;SCAN KEYBOARD
 	POP	BC		;RESTORE COUNT
 	OR	A		;SET FLAGS
 	JR	NZ,HAVEIT	;HAVE A KEY
 	DEC	BC		;DECREMENT COUNT
 	LD	A,B		;TEST IF <BC> IS ZERO
 	OR	C		;FLAGS ARE SET
 	JR	NZ,QSCALP	;NEXT COUNT
 	RET			;NO KEYS PRESSED
 FLOFF	CALL	SETUP		;GET VALUES
 	EX	DE,HL		;TRADE POINTERS
 	LDIR			;MOVE BUFFER TO VIDEO
 	EX	DE,HL		;TRANSFER VALUES
 	LD	(HL),20H	;SPACE AT END OF DISPLAY
 	CALL	QSCAN		;CHECK KEYBOARD
 	JR	FLON		;TURN BACK ON
 HAVEIT	LD	(CHAR),A	;SAVE CHARACTER FOR LATER
 	CALL	SETUP		;GET POINTERS
 	EX	DE,HL		;SWAP POINTERS
 	LDIR			;ASCII ON SCREEN
 	LD	HL,CHAR		;VALUE TO BASIC
 	LD	A,(HL)		;CHARACTER IN A
 	RET			;DONE
 SETUP	LD	HL,(4020H)	;CURSOR POSITION
 	LD	DE,STRING	;BUFFER POINTER
 	LD	A,(FLALEN)	;LENGTH TO FLASH
 	LD	C,A		;LSB OF BYTE COUNT
 	LD	B,0		;ZERO THE B REG.
 	RET			;ALL POINTERS SET
 LITE	CALL	SETUP		;GET POINTERS
 	PUSH	HL		;PASS VALUE TO
 	POP	DE		;   <DE> REGS.
 	INC	DE		;NEXT ADDRESS
 	LD	(HL),143	;GRAPHICS BYTE
 	LDIR			;MOVE BYTES
 	LD	A,20H		;ASCII SPACE
 	DEC	DE		;POINT TO END
 	LD	(DE),A		;WRITE IT
 	RET			;DONE
 ;	ROUTINE TO PRODUCE A BEEP TONE IN CASSETTE #1.
 ;
 ;	COULD BE USED IN AN INKEY$ ROUTINE TO "BEEP"
 ;	WHENEVER A KEY IS PRESSED.
 ;
 TONE	DI			;WE'RE BUSY !
 	LD	HL,DURAT	;DURATION ADDRESS
 	LD	C,(HL)		;GIVE BYTE TO C REG.
 TONEZ	LD	HL,FREQ		;FREQUENCY ADDRESS
 	LD	B,(HL)		;GIVE BYTE TO B REG.
 	LD	A,1		;SIGNAL ON BYTE
 	OUT	(0FFH),A	;TURN ON 1/2 CYCLE
 TONEY	DJNZ	TONEY		;DELAY FOR FREQUENCY
 	LD	HL,FREQ		;GET FREQUENCY AGAIN
 	LD	B,(HL)		;GIVE BYTE TO B REG.
 	LD	A,2		;SIGNAL OFF BYTE
 	OUT	(0FFH),A	;TURN ON OTHER 1/2 CYCLE
 TONEX	DJNZ	TONEX		;DELAY FOR FREQUENCY
 	DEC	C		;DECREMENT DURATION
 	JR	NZ,TONEZ	;GO IF NOT DONE
 	RET			;BACK TO CALL
 ;	RELOCATABLE MACHINE CODE TO TRANSFER THE
 ;	CONTENTS OF THE SCREEN TO THE LINEPRINTER.
 ;
 ;	GRAPHICS CHARACTERS ARE PRINTED AS PERIODS.
 ;
 ;	PRINTING MAY BE INTERRUPTED BY HITTING
 ;	THE <BREAK> KEY.
 ;
 VID	LD	A,(37E8H)	;LINE PRINTER ADDRESS
 	AND	80H		;TEST BIT 7
 	RET	Z		;PRINTER NOT READY
 	XOR	A		;ZERO ACCUMULATOR
 	LD	(VIDCNT),A	;LD INTO COUNTER ADDR.
 	LD	B,40H		;LENGTH OF SCREEN LINE
 	LD	DE,3BFFH	;VIDEO ADDR. -1
 	LD	HL,37E8H	;LINE PRINTER ADDRESS
 VIDE3	INC	DE		;INC. VIDEO ADDR.
 	LD	A,(DE)		;GET VIDEO BYTE
 	CP	80H		;GRAPHICS CHARACTER ?
 	JR	Z,VID4		;128 ASCII SPACE
 	JP	M,VID4		;GO IF NO
 	LD	A,46		;ASCII FOR PERIOD <.>
 VID4	CALL	VIDE2		;TRANSFER TO PRINTER
 	LD	A,(3840H)	;KEYBOARD MEMORY
 	CP	4		;<BREAK> KEY PRESSED ?
 	RET	Z		;RETURN IF IT IS
 	DJNZ	VIDE3		;GET NEXT CHARACTER
 	LD	A,0DH		;CARRIAGE RETURN BYTE
 	CALL	VIDE2		;PRINTER LINEFEED
 	LD	A,(VIDCNT)	;GET LOOP VALUE
 	INC	A		;INCREMENT
 	LD	(VIDCNT),A	;STORE NEW VALUE
 	CP	10H		;LOOP FOR 16 LINES
 	RET	Z		;RETURN IF DONE
 	LD	B,40H		;LOAD # CHAR. PER LINE
 	JR	VIDE3		;PRINT NEXT LINE
 VIDE2	LD	C,(HL)		;GET LINEPRINTER STATUS
 	BIT	7,C		;TEST IF READY
 	JR	NZ,VIDE2	;WAIT IF NOT READY
 	LD	(HL),A		;SEND BYTE TO PORT
 	RET
 VIDCNT	DEFB	0		;COUNTER BYTE
 DURAT	DEFB	8		;TONE DURATION BYTE
 FREQ	DEFB	60		;TONE FREQUENCY BYTE
 ;  FOLLOWING IS A DISK BACKUP ROUTINE FOR 48K MEM
 ;	TARGET DISKETTE MUST BE FORMATTED
 BACKUP	CALL	DISPLY
 	DEFW	1F1CH		;CLEAR SCREEN
 	DEFM	'- BREEZE SPECIAL BACKUP UTILITY -'
 	DEFW	0D0DH
 	DEFB	0
 	LD	B,3		;3 10 TRACK LOOPS
 	LD	DE,00		;TRACK SECTOR
 BACKLP	PUSH	BC		;SAVE COUNT
 	PUSH	DE		;SAVE TRACK/SECTOR
 	CALL	GETSRC		;GET SOURCE MOUNTED
 	POP	DE		;TRACK/SECTOR
 	LD	HL,100H		;100 SECTORS TO READ
 	LD	BC,5000H	;LOAD ADDRESS
 	CALL	READ		;READ 'EM
 	PUSH	DE
 	CALL	GETDES		;GET DESTINATION DISK
 	POP	DE
 	LD	HL,100H		;100 SECTORS TO WRITE
 ;  ALL DATA SECTORS ARE WRITTEN AS READ PROTECTED
 ;  SEEK BYTE MAY BE MODIFIED AT (SKTYPE)
 ;  WRITE BYTE MAY BE MODIFIED AT (WRTYPE)
 	LD	BC,5000H	;DATA BUFFER
 	CALL	WRITE		;WRITE 'EM
 	POP	BC		;RESTORE COUNT
 	DJNZ	BACKLP		;DO IT 3 TIMES
 ;  30 TRACKS HAVE NOW BEEN WRITTEN
 	PUSH	DE		;SAVE TRACK/SECTOR
 	CALL	GETSRC		;GET SOURCE DISK
 	POP	DE
 	LD	H,0
 	LD	A,(TRACKS)	;GET # OF TRACKS
 	SUB	30		;MINUS 30 TRACKS DONE
 	LD	L,A		;HL=# OF TRACKS LEFT
 	CALL	TIME10		;MULTIPLY X 10
 	LD	BC,5000H	;BUFFER
 	PUSH	HL		;SAVE SECTOR COUNT
 	CALL	READ		;READ 'EM
 	PUSH	DE
 	CALL	GETDES
 	POP	DE
 	POP	HL		;# OF SECTORS TO WRITE
 	LD	BC,5000H
 	CALL	WRITE
 	CALL	DISPLY
 	DEFW	0D0DH
 	DEFM	'FULL DISK COPY COMPLETED'
 	DEFB	0
 	CALL	GETSRC
 	RET			;DONE WITH ROUTINE
 GETSRC	CALL	DISPLY
 	DEFB	0DH
 	DEFM	'<ENTER> WHEN SOURCE DISK MOUNTED '
 	DEFB	0
 	JR	WAITKY
 GETDES	CALL	DISPLY
 	DEFB	0DH
 	DEFM	'<ENTER> WHEN DESTINATION DISK MOUNTED '
 	DEFB	0
 WAITKY	LD	B,1
 	CALL	GETSTR		;CURSOR AFTER REQUEST
 	RET			;ENTER WAS PRESSED
 ;  ROUTINE WILL MULTIPLY HL REG X 10
 TIME10	LD	B,H		;PASS TO BC ALSO
 	LD	C,L		;FOR INITIAL VALUE
 	ADD	HL,HL		;HL * 2
 	ADD	HL,HL		;HL * 4
 	ADD	HL,BC		;HL * 5
 	ADD	HL,HL		;HL * 10
 	RET			;DONE
 ;  ROUTINE TO RESTORE A DRIVE & CHECK STATUS
 ;  DRIVE IS IN (DRIVE)
 RESTOR	CALL	STATCK		;SELECT & CHECK STATUS
 	CALL	SELECT		;RESELECT THE DRIVE
 	DEFB	3EH		;LOAD ACCUMULATOR BYTE
 RSTYPE	DEFB	0BH		;RESTORE BYTE
 	LD	(37ECH),A	;PASS TO COMMAND REG
 RSLP	CALL	SELECT		;RE-SELECT THE DRIVE
 	LD	A,(37ECH)	;GET STATUS BYTE
 	RRCA			;SHIFT OUT BUSY BIT
 	JR	C,RSLP		;WAIT SOME MORE
 	RET			;RESTORE COMPLETE
 	END	ENTRY
