.TITLE 'BIOS FOR 48 TPI READ OF 96 TPI DRIVES'	
;
;  |----------------------------------------------|
;  |						  |
;  |    OTRONA  500 SERIES CP/M 2.2 BIOS & BOOT	  |
;  |					          |
;  |----------------------------------------------|
;
;  	S.GRAY	10-19-1983	
;  R.LINGEMANN
;     R.WINTER
;	
	.PABS
	.PHEX
	.XSYM
;
TPI	=	\' 0 = 48 TPI, 1 = 96 TPI     '
LSTDEF	=	\' EQUATES                    '
LSTCBT	=	\' COLD BOOT ROUTINE          '
LSTINT	=	\' BIOS INTERFACE             '
LSTDBK	=	\' BDOS DISK ROUTINES         '
LSTDSK	=	\' BIOS DISK ROUTINES         '
LSTFIN	=	\' FLOPPY INTERRUPT           '
LSTIO	=	\' CHARACTER I/O              '
LSTDSP	=	\' DISPLAY DRIVER CONTROL     '
LSTFNC	=	\' DISPLAY DRIVER ESC & CNTRL '
LSTMCH	=	\' DISPLAY DRIVER MULTI-CHAR. '
LSTDMC	=	\' DISPLAY DRIVER SUPPORT     '
LSTGRF	=	\' DISPLAY DRIVER GRAPHICS    '
LSTVLE	=	\' VALET EXECUTIVE (SET-UP)   '
LSTVLD	=	\' VALET DISK ROUTINES        '
LSTVLM	=	\' VALET SUPPORT ROUTINES     '
LST60H	=	\' 60 Hz INTERRUPT ROUTINE    '
LSTTBL	=	\' TABLES & MESSAGES          '
LSTVAR	=	\' VARIABLE STORAGE           '
;
	.IFE	LSTDEF,[
	.XLIST
]
	.PAGE
;
;	SELECT DISK PARAMETERS			
;					
LINES	=	24	; # OF LINES ON SCREEN
STPRAT	=	6	; STEP RATE IN mS (MUST BE BETWEEN 2 AND 32 IN EVEN
;			   INCREMENTS.)
SIDES	=	1	; DOUBLE SIDED
;
;	CONFIGURATION
;			
STACK	=	ENDMRK+1  ; TOP OF STACK
MSIZE	=	56	  ; CP/M VERSION MEMORY SIZE IN K-BYTES
BIAS	=	(MSIZE-20)*1024
CCP	=	3400H+BIAS; BASE OF CCP
BDOS	=	CCP+806H  ; BASE OF BDOS
BIOS	=	CCP+1600H ; BASE OF BIOS
NDISK	=	2	  ; NUMBER OF DISKS IN SYSTEM
CDISK	=	0004H	  ; CURRENT DISK NUMBER ADDR.
MNTR	=	0003H	  ; EPROM MONITOR ENTRY
MDISKOP	=	0006H	  ; EPROM DISKOP ENTRY	ŠMDSPLY	=	0009H	  ; EPROM DISPLAY DRIVER	
IOBYTE	=	0003H	  ; I/O BYTE LOCATION	
IOINIT	=	81H	  ; INITIAL IOBYTE VALUE
KBUFLN	=	16	  ; KEYBOARD BUFFER SIZE
FILBUF	=	0FE00H	  ; BUFFER SPACE FOR FORMAT
			  ;  WILL BE CHANGED BY DISK ROUTINE
;
	.PAGE
;
;  I/O CONSTANTS
;
TIMCW0	=	57H	; TIMER CONTROL BYTE
TIMTC0	=	02H	; 9600 BAUD
TIMTC1	=	02H	; 9600 BAUD
;
;  ASCII CODES
;
BEL	=	7H	; BELL
BS	=	8H	; BACKSPACE
CR	=	0DH	; CARRIAGE RETURN
CTRLJ	=	0AH	; CTRL-J
CTRLJH	=	0C8H	; CTRL-JH
CTRLK	=	0BH	; CTRL-K
CTRLO	=	0FH	; CTRL-O
CTRLP	=	10H	; CTRL-P
CTRLPS	=	0D3H	; CTRL-PS
CTRLQ	=	11H	; CTRL-Q
CTRLQP	=	90H	; CTRL-QP
CTRLS	=	13H	; CTRL-S
CTRLX	=	18H	; CTRL-X
ESC	=	1BH	; ESCAPE
FF	=	0CH	; FORM FEED
LF	=	0AH	; LINE FEED
SPC	=	20H	; SPACE
;
;	FLOPPY CONSTANTS
;
RWCODE  =	40H+3	; R/W COMMAND-2 OR 3
MTRTIM	=	300	; 5S MOTOR TIMEOUT
MTRDLY	=	45	; 750MS. MOTOR START DELAY
;
SRT	=	16-(STPRAT/2); HEAD STEP RATE
;
DHLT	=	16	; DISK HEAD LOAD TIME
DHUT	=	0FH	; DISK HEAD UNLOAD TIME
ND	=	0	; DMA MODE
;
;	CP/M DISK RETURN CODES
;
WRALL	=	0	;WRITE TO ALLOCATED
WRDIR	=	1	;WRITE TO DIRECTORY
WRUAL	=	2	;WRITE TO UNALLOCATED
;
;  DISK DRIVE PARAMETERS
;						
ALLTRË	=	36+(40*TPI)+SIDES*(40+(42*TPI))	
BLS	=	(TPI ! SIDES)+1
BLKSIZ	=	1024*BLS; DIRECTORY BLOCK SIZE
HSTSIZ	=	512	; HOST DISK SECTOR SIZE 
HSTSPT	=	10	; HOST SECTORS PER TRACK (CYL)
ALLDSK	=	ALLTRK*5/BLS
DSKSIZ	=	ALLDSK-(21-(BLS*7)+1)
SYSTRK	=	3	; SYSTEM RESERVED TRACKS
CNTSEC	=	2	; HSTSIZ/PHYSICAL SECTOR SIZE
;
HSTBLK	=	HSTSIZ/128	; CP/M SECT. PER HOST SECT.
CPMSPT 	=	HSTBLK * HSTSPT	; CP/M SECTORS PER TRACK
SECMSK	=	HSTBLK-1	; SECTOR MASK
BADDR	=	CCP-HSTSIZ
MAXTRK	=	39+(40*TPI)
DIRENT	=	64*((SIDES ! TPI)+1)
DIRALC	=	DIRENT/(BLKSIZ/32)
;
	.IFE	DIRALC-1,[
ALOC0	=	80H
]
	.IFE	DIRALC-2,[
ALOC0	=	0C0H
]
	.IFE	DIRALC-4,[
ALOC0	=	0F0H
]
;
TPA	=	100H
;
	.PAGE
;
;  I/O PORTS
;
FPYBCA	=	0E0H	;FLOPPY STATUS PORT
FPYBWR	=	0E1H	;FLOPPY DATA PORT
DSPBCA	=	0E2H	;DISPLAY BASE & CURRENT ADDRESS
DSPBWR	=	0E3H	;DISPLAY BASE & WORD COUNT
STDBCA	=	0E4H	;STD BUS BASE & CURRENT ADDRESS
STDBWR	=	0E5H	;STD BUS BASE & WORD COUNT
SIOBCA	=	0E6H	;SIO BASE & CURRENT ADDRESS
SIOBWR	=	0E7H	;SIO BASE & WORD COUNT
DMACSR	=	0E8H	;DMA COMMAND/STATUS REGISTER
DMAWRR	=	0E9H	;DMA WRITE R=EST REGISTER
DMAWSM	=	0EAH	;DMA WRITE SINGLE MASK BIT
DMAWMR	=	0EBH	;DMA WRITE MODE REGISTER
DMACBP	=	0ECH	;DMA CLEAR BYTE PNTR FLIP-FLOP
DMATMP	=	0EDH	;DMA TEMP REG & MASTER CLEAR
SDSPY	=	0EEH	;DISPLAY COMMAND/STATUS
DMAWAM	=	0EFH	;DMA WRITE ALL MASK REG BITS
DCOMM	=	0F0H	;COMM PORT DATA
SCOMM	=	0F1H	;COMM PORT STATUS
DPRTR	=	0F2H	;PRINTER PORT DATA
SPRTR	=	0F3H	;PRINTER PORT STATUS
BAUDC	=	0F4H	;BAUD TIMER FOR COMM PORTŠBAUDP	=	0F5H	;BAUD TIMER FOR PRINTER PORT
DSPINT	=	0F6H	;DISPLAY INTERRUPT (60HZ)
FPYINT	=	0F7H	;FLOPPY INTERRUPT TIMER
DPIOA	=	0F8H	;PIO PORT A DATA
			;  A0-7 = LATCH DATA OUT
			;	L0 = MOTOR ON
			;	L1 = GRAPHICS ENABLE
			;	L2 = EPROM ENABLE
			;	L3 7 DISPLAY BRTNS.
			;  A0-7 = 8910 DATA I/O
                        ;  A0-3 = 5832 D0-3 I/O
			;  A4-7 = 5832 A0-3 OUT
			;  A0-3 = 5101 D0-3 I/O
			;  A4-7 = 5101 A0-3 OUT
DPIOB	=	0FAH	;PIO PORT B DATA
			;  B0-1 = 5101 A4-5
			;  B2-4 = OPERATION SELECT
			;	0 = 8910 ADDR LOAD
			;	1 = 8910 DATA LOAD
			;	2 = 5832 WRITE
			;	3 = 5832 READ
			;	4 = 5101 WRITE
			;	5 = 5101 READ
			;	6 = LATCH LOAD
			;	7 = NO-OP
			;  B5 = /'138 OPERATION STROBE
			;  B6 = /KEYBOARD DATA IN
			;  B7 = /KEYBOARD CLOCK OUT
SPIOA	=	0F9H	;PIO PORT A COMMAND
SPIOB	=	0FBH	;PIO PORT B COMMAND
SFLPY	=	0FCH	;FLOPPY COMMAND/STATUS
DFLPY	=	0FDH	;FLOPPY DATA
DDSPY	=	0FEH	;DISPLAY DATA
DMAP	=	0FFH	;RAM VIRTUAL MAP DATA
;
	.LIST
	.IFE	LSTCBT,[
	.XLIST
]
	.PAGEŠ;
;|----------------------------------------------|
;|	BOOT - LOADED INTO FE00H BY PROM	|
;|----------------------------------------------|
;						
;BOOT CODE WILL BE SAVED IN SECTOR 1 OF TRACK 0
;AND IS SET UP HERE TO ASSEMBLE ONE SECTOR LENGTH
;AHEAD OF THE CCP. THE ADDRESS OFFSET FACTOR BOFF
;IS ADDED WHERE NEEDED SO THE BOOT CODE WILL RUN
;WHEN LOADED AT IT'S STARTING ADDRESS OF 0FE00H	
;THE BIOS CBOOT ROUTINE IS ALSO RUN HERE TO SAVE 
;SPACE AS THE ONLY TIME THIS ROUTINE IS USED IS
;DIRECTLY FOLLOWING A SYSTEM RESET.
;
MONSTK	=	0FE00H	;ADDR OF MON. STACK & DISK BUFF.
BTSTRT	=	CCP-HSTSIZ
BOFF	=	MONSTK-BTSTRT
;
	.LOC	BTSTRT
;
;	BOOT LOADER
;
	JMP	BOOT+BOFF	;GETSYS VECTOR
	.BYTE	0A7H		;INDICATES CP/M TO MONITOR
;
;|----------------------|
;|	COLD BOOT	|
;|----------------------|
;
CBOOT:	JMPR	CBOOT1
;
SIGNON:	.BYTE	ESC,'\',ESC,'3',18H ; CLEAR GRAPHICS & RESET SCREEN
	.ASCII	'CP/M 2.2.5'
;
	.IFN	TPI,[
	.ASCII	'/96'
]
	.ASCIS	' Otrona ATTACHE <56K>'	
;
;
CBOOT1:	DI		;TURN OFF INTERRUPTS
;
;	SET UP PERIPHERALS I/O VIA TABLE
;
	LXI	H,IOTBL+BOFF ;POINT TO I/O TABLE
CBL1:	MOV	A,M
	MOV	C,A	;C=PORT
	INR	A	;JUMP OUT IF DONE
	JRZ	CBJ1
	INX	H	;B=COUNT
	MOV	B,M
	INX	H
CBL2:	MOV	A,M	;MANUAL BLOCK OUTPUT
	OUTP	A	;  SO SLOW DEVICES
	INX	H	;  CAN KEEP UP
	DJNZ	CBL2
	JMPR	CBL1
;
CBJ1:	LXI  	H,MTRTIM
	SHLD	MTRCNT
	MVI	A,85H
	STA	LSTATE
;
;	INIT VARIABLES & BUFFERS
;
        XRA	A	
        LXI	H,DSPCYC
	MVI	B,47	
CBL3:	MOV	M,A
	INX	H
	DJNZ	CBL3
;
	STA	OKIFLG
	MVI	A,IOINIT; SET INITIAL IOBYTE VALUE
	STA	IOBYTE
	LXI	SP,STACK; SET STACK POINTER
;
;	SET UP SYSTEM PARAMETERS FROM CMOS RAM
;	-----	B = 0 FROM PREVIOUS OP
	CALL	RD5101	; MUST FIND XE,X5 IN 1ST TWO CMOS LOCATIONS
	CPI	0EH
	JRNZ	STRM	; 1ST BYTE NOT XE, GO SET CMOS RAM AND BIOS VARS.
	MVI	B,1	
	CALL	RD5101
	CPI	5	;  IF 2ND BYTE = X5
	JRZ	STCM	;   THEN READ CMOS RAM & SET BIOS VARIABLES
;
STRM:	MVI	A,1	;    ELSE SET CMOS RAM & BIOS VARIABLES
	CALL	WRTTON	;     SET KEYTONE
	MVI	A,1AH
	CALL	WRTBRT	;SET BRIGHTNESS
	MVI	A,9
	CALL	WRTPNT	;SET PRINTER BAUD
	MVI	A,9
	CALL	WRTCOM	;SET COMM. BAUD
	MVI	A,0FFH
	CALL	WRTBEL	;SET BELL TOGGLE
	MVI	A,0FH
	CALL	WRTVOL	;SET VOLUME LEVEL
	XRA	A
	CALL	WRTSLK	;SET SHIFT LOCK
	MVI	A,0EH
	MVI	B,0
	CALL	WR5101
	MVI	A,5
	MVI	B,1
	CALL	WR5101
	MVI	A,0FH
	MOV	B,A
	CALL	WR5101
	JMPR	IMPR	
;
STCM:	MVI	B,9	; GET KEYTONE
	CALL	RD5101
	STA	TONTYP	;  SET BIOS VAR.
	CALL	GTBRIT	; GET BRIGHTNESS
	STA	BRTLEV	;  SET BIOS VAR.
	MVI	B,5
	CALL	RD5101	; GET BELL TOGGLE
	STA	CURBEL	;  SET BIOS VAR.
	MVI	B,6
	CALL	RD5101	; GET VOLUME LEVEL
	STA	VOLEVL	;  SET BIOS VAR.
	MVI	B,0EH
	CALL	RD5101	; GET SHIFT LOCK
	ORA	A
	JRZ	SLOK	;   0=OFF, 0FFH=ON
	MVI	A,0FFH
SLOK:	STA	SHLOCK	;  SET BIOS VAR.
;
IMPR:	LXI 	H,NOTONE-15	; SET CURRENT KEYTONE POINTER
	LDA	TONTYP
	INR	A
	MOV	B,A
	LXI	D,15
IML1:	DAD	D
	DJNZ	IML1
	SHLD	CLIKAD		; STORE KEYTONE POINTER
	LDA 	BRTLEV		; SET PHYSICAL DEVICES:
	CALL	BRTADJ		;  BRIGHTNESS LATCH
	CALL	ADJPNT		;  PRINTER BAUD
	CALL	ADJCOM		;  COMM. BAUD
	LDA	VOLEVL		
	CALL	VOLADJ		;  VOLUME BYTES IN SOUND TABLE
 	MVI	A,0C7H		
	STA	GRFBIT+1	; SET GRAPHICS ROUTINE TO PLOT BRIGHT
;
;	CHECK FOR CLOCK CHIP TYPE
;
	MVI	B,4
CCL4:	PUSH 	B	
	MVI	B,0DH	
	CALL	R58174
	CPI	0FH
	POP	B
	JRNZ	NSCK	; <> 0FH = NATIONAL SEMI CLOCK
	DJNZ	CCL4
;
	MVI	A,0ACH
	STA	W58174+14
	MVI	A,0A8H
	STA	R58174+15
	STA	OKIFLG
;
;	CHECK FOR CLOCK SET
;
NSCK:	MVI	B,3	; MUST FIND XE,X5 IN TWO CMOS BYTES (3 & 4)
	CALL	RD5101	;  TO INDICATE CLOCK HAS BEEN SET
	CPI	0EH
	JRNZ	SETINT	; NO MATCH, SKIP TO SET INTERRUPT
	MVI	B,4
	CALL	RD5101
	CPI	5
	JRNZ	SETINT	; NO MATCH, SKIP TO SET INTERRUPT
	STA	CLKFLG	; ELSE SET CLKFLG <> 0 (CLOCK SET)
;
;	SET UP THE INTERRUPT STRUCTURE
;
SETINT:	MVÉ A,V60HZ/25¶	;SEÔ VECTOŇ AREA
	STAÉ
	IM2		;MODE 2
	EI		;INTERRUPTS ON
;
;	SIGN ON
;
	LXI	H,SIGNON+BOFF
	CALL	MESSG
;
;	SET UP DISK PARAMETERS
;
	CALL	CLRFLG
 	LXI	H,SPCTBL ;SETUP SPECIFY TABLE
 	CALL	DISKOP
 	EI
	XRA	A
	STA	CDISK	;SELECT DRIVE 0
	STA	HSTHD
	CALL	GOCPM
	JMP 	CCP
;
	.PAGE
;
;
;|------------------------------|
;|	I/O SETUP TABLE		|
;|------------------------------|
;
; FORMAT: PORT#, # OF BYTES, BYTES
;	  PORT ENTRY OF 0FFH TERMINATES
;
;	TIMERS
;
IOTBL:	.BYTE	BAUDC	; COMM PORT
	.BYTE	4
	.BYTE	3	; RESET
	.BYTE	(V60HZ-4) @ 256 ; INT. VECTOR
	.BYTE	TIMCW0	; CONTROL WORD
	.BYTE	TIMTC0	; COMM. BAUD (9600)
;
	.BYTE	DSPINT	; 60 HZ. INTERRUPT
	.BYTE	3
	.BYTE	3	; RESET
	.BYTE	0D5H	; + EDGE, INT. ON
	.BYTE	1	; COUNT OF 1
;
	.BYTE	FPYINT	; FLOPPY INTERRUPT
	.BYTE	3
	.BYTE	3	; RESET
	.BYTE	0D5H	; + EDGE, INT. ON
	.BYTE	1
;
;	DISABLE EPROM, TURN ON MOTOR
;
	.BYTE	SPIOA	; SET DIRECTION OUT
	.BYTE	2
	.BYTE	0CFH
	.BYTE	0
;
	.BYTE	DPIOA	; DATA FOR LATCH
	.BYTE	1
	.BYTE	85H
;
	.BYTE	DPIOB	; STROBE DATA INTO LATCH
	.BYTE	3
	.BYTE	0FBH
	.BYTE	0DBH
	.BYTE	0FBH
	.BYTE	0FFH	; TERMINATOR
;
;
	.PAGE
;
;|------------------------------|
;|	BOOT LOADER		|
;|------------------------------|
;
BOOT:	LXI	X,BOT1+BOFF	; ERROR RETURN ADDR.
	MVI	B,10		; 10 RETRIES
BOT0:	PUSH	B		
	LXI	H,BRCTBL+BOFF	; HL<- START OF RECAL TABLE
	CALL	MDISKOP		;  RECAL DRIVE
	POP	B
	JMPR	BOT2
BOT1:	POP	B		; ARRIVE HERE IF RECAL ERROR
	DJNZ	BOT0	
	JMPR	GOMON		; IF 10 BAD TRIES, BACK TO MON.
BOT2:	MVI 	C,27		; READ 27 SECTORS
BOT3:	LXI	X,BOT5+BOFF	; ERROR RETURN ADDR.
	MVI	B,10		; 10 RETRIES
BOT4:	PUSH	B
	LXI	H,BRDTBL+BOFF	; HL <- START OF READ TABLE
	CALL	MDISKOP
	JMPR	BOT6
BOT5:	POP	B		; ARRIVE HERE IF READ ERROR
	DJNZ	BOT4
	JMPR	GOMON		; IF 10 BAD TRIES, BACK TO MON.
BOT6:	POP	B 	
	DCR	C		; DCR SECTOR COUNTER
	JRZ	BTOV		; IF SECTOR = 0, THEN BOOT DONE
	LDA	BRDTBL+BOFF+2	;  ELSE INC LOAD POINTER BY 200H
	ADI	2
	STA	BRDTBL+BOFF+2
	LXI	H,BRREC+BOFF	;  INC PHYSICAL SECTOR
	INR	M
	MVI	B,10		; RESET RETRY COUNTER
	MOV	A,C
	CPI	18		;  AT 1ST TRACK BOUNDARY ?
	JRZ	BOT7		;   IF YES, GO ..BOT7
	CPI	8		;    ELSE AT 2ND TRACK BOUNDARY ?
	JRNZ	BOT4		;     IF NO THEN GO ..BOT4
BOT7:	LDA	BRCYL+BOFF	; INCREMENT TRACK
	INR	A
	STA	BRCYL+BOFF
	STA	BSKADD+BOFF
	MVI	A,1		; RESET PHYSICAL SECTOR
	STA	BRREC+BOFF
	LXI	X,BOT9+BOFF	; ERROR RETURN ADDR.
	MVI	B,10		; 10 RETRIES
BOT8:	PUSH	B
	LXI	H,BSKTBL+BOFF	; HL <- START OF SEEK TABLE
	CALL	MDISKOP		;  SEEK TO NEXT TRACK
	POP	B
	JMPR	BOT3		; GO GET NEXT SECTOR
;
BTOV:	DI			; SYSTEM HAS BEEN BOOTED
	JMP	BIOS		;  GOTO TO BIOS INIT ROUTINE
;
BOT9:	POP	B		; ARRIVE HERE IF SEEK ERROR
	DJNZ	BOT8		 
GOMON:	JMP	MNTR		; IF 10 BAD TRIES, THEN BACK TO MON.
;
;|----------------------|
;|	DISK TABLES	|
;|----------------------|
;
;	READ A SECTOR
;
BRDTBL:	.BYTE	39H
	.WORD	CCP
	.WORD	512-1
	.BYTE	40H+6
	.BYTE	0	;UNIT
BRCYL:	.BYTE	0	;C
	.BYTE	0	;H
BRREC:	.BYTE	2	;R
	.BYTE	2	;N
	.BYTE	10	;EOT
	.BYTE	15	;GP2
	.BYTE	0FFH	;DTL
;
;	SEEK TO NEW CYLINDER
;
BSKTBL:	.BYTE	23H
	.BYTE	0FH
	.BYTE	0	;HEAD & UNIT
BSKADD:	.BYTE	0	;NEW CYLINDER
;
;	RECALIBRATE TO CYLINDER 0
;
BRCTBL:	.BYTE	22H
	.BYTE	7
	.BYTE	0
;
	.LIST
	.IFE	LSTINT,[
	.XLIST
]
	.PAGEŠ;
;|--------------------------------------|
;|					|
;|     		BIOS		 	|
;|					|
;|--------------------------------------|
;
	.LOC	BIOS
;
;	JUMP VECTORS
;
	JMP	CBOOT+BOFF ;COLD START
WBOOTE:	JMP	WBOOT	;WARM START
	JMP	CONST	;CONSOLE STATUS
	JMP	CONIN	;CONSOLE CHAR. IN
	JMP	CONOUT	;CONSOLE CHAR. OUT
	JMP	LIST	;LIST CHAR. OUT
	JMP	PUNCH	;PUNCH CHAR. OUT
	JMP	READER	;READER CHAR. IN
	JMP	HOME	;MOVE HEAD TO HOME POS.
	JMP	SELDSK	;SELECT DISK
	JMP	SETTRK	;SET TRACK #
	JMP	SETSEC	;SET SECTOR #
	JMP	SETDMA	;SET DMA ADDRESS
	JMP	READ	;READ FROM DISK
	JMP	WRITE	;WRITE TO DISK
	JMP	LISTST	;RETURN LIST STATUS
	JMP	SECTRA	;SECTOR TRANSLATION
;
;DISK PARAMETER TABLE
;
;
DPBASE	=	.	; BASE OF DISK PARAMETER BLKS.
;
;	DISK 00
;
XLT0	=	0		; NO XLATION TABLE
XLT1	=	XLT0
	.WORD	XLT0,0		; XLATE TABLE
	.WORD	0,0		; SCRATCH AREA
	.WORD	DIRBUF,DPB0 	; DIR BUFF, PARM BLOCK
	.WORD	CSV0,ALV0   	; CHECK, ALLOC VECTORS
;
;	DISK 01
;
	.WORD	XLT1,0		; XLATE TABLE
	.WORD	0,0		; SCRATCH AREA
	.WORD	DIRBUF,DPB1	; DIR BUFF, PARM BLOCK
	.WORD	CSV1,ALV1	; CHECK, ALLOC VECTORS
;
;	DISK PARAMETER BLOCK FOR DRIVE A:
;
DPB0:	.WORD	CPMSPT		; SEC PER TRACK
	.BYTE	3+BLS-1		; BLOCK SHIFT
	.BYTE	7+((BLS-1)*8)   ; BLOCK MASK
EXM:	.BYTE	TPI ^ 1
	.WORD	DSKSIZ-1 	; DISKSIZE-1
	.WORD	DIRENT-1 	; DIRECTORY MAX
	.BYTE	ALOC0		; ALLOC0
	.BYTE	0		; ALLOC1
	.WORD	DIRENT/4	; CHECK SIZE
	.WORD	SYSTRK		; OFFSET
;
;	RESERVED FOR 3 INTERRUPT VECTORS (I=0DAH)
;
INT1:	.BLKB	2
INT2:	.BLKB	2
INT3:	.BLKB	2
;
;	JUMP TABLE FOR EXTERNAL USE
;
JMPTBL: JMP	DISK	; VECTOR TO DISK
	JMP 	DISPLY	; VALET CRTOUT
	JMP	TTYIST	; TEST COMM. INPUT STATUS
	JMP	TTYIN	; INPUT FROM COMM.
	JMP	TTYOUT	; OUTPUT TO COMM.
	JMP	SOUND	; TABLE DRIVEN SOUND
	JMP	PUTVAL	; EXIT VALET OVERLAY
	JMP	LINDSP+3; FOR BASIC GRAPHICS
;
;	VARIABLES FOR EXTERNAL USE
;
WSFLAG:	.BYTE	0
VALSTP:	.BYTE 	0FFH
DSKFLG:	.BYTE	0FFH
VALPND:	.BYTE	0
CLIKAD: .WORD	CLICK
VALCMD:	.BYTE	0
VALTIM:	.BYTE	0
;
;	VECTORS
;
	JMP	OUTBLK
	JMP	CLNVAL
	JMP	ADJPNT	; READ CMOS & CHANGE PRINT BAUD
	JMP	ADJCOM	; READ CMOS & CHANGE COMM. BAUD
	JMP	DOBOOT	; DO WARM BOOT BUT DON'T GO TO CCP
	JMP	GOCPM	; INITIALIZE ENVIRONMENT
	JMP	CMPOFF	; RETURN HL W/PROPER LINE OFFSET
WBTVEC:	JMP	CCP+3	; USED TO REDIRECT WARM BOOT CCP JUMP
;
;	MORE	VARIABLES
;
SIORG5:	.BYTE	0EAH	; INITIAL STATUS OF COMM. PORT RR 5	
SPOOL:	.BLKB	1	; USED IN BANKED SYSTEM FOR SPOOLER
PARPNT:	.WORD	CURCHR
LINOFS:	.BYTE	0
DSPFLG:	.BYTE	0
ALMWAT:	.BYTE	0
ALMCNT:	.BYTE	0	; COUNTS # OF ALARM TONES
BNKFLG:	.BYTE	0	; FLAG FOR BANKED OR UNBANKED
ALMFLG:	.WORD	600	; BIOS
VALTON:	.WORD	NOTONE
CLKFLG:	.BYTE	0
TIMFLG:	.BYTE	0FFH
NUMFLG:	.BYTE	0
KEYADR:	.WORD	KEYTBL
FLPTBL:	.WORD	FMTTBL
DSTMP:	.WORD	1019H	; DATE STAMP
	.IFN	TPI,[
	.BYTE	96
]
	.IFE	TPI,[
	.BYTE	48
]
	.BLKB	1	; FREE FOR USE
;
;|-----------------------------------|
;| INTERRUPT VECTORS - MUST BE ON A  |
;| BOUNDARY OF AN EVEN MULTIPLE OF 8 |
;|-----------------------------------|
;
	.BLKB	2	; RESERVED FOR CTC CH. 0
	.BLKB	2	; RESERVED FOR CTC CH. 1
V60HZ:	.WORD	SRV60	; 60 HZ TIMER (CTC CH. 2)
	.WORD	SRVFPY	; FLOPPY INT. (CTC CH. 3)
;
;	MORE USER INTERRUPTS
;
INT4:	.BLKB	2
INT5:	.BLKB	2
INT6:	.BLKB	2
INT7:	.BLKB	2
INT8:	.BLKB	2	
;
DSKNO:	.BYTE	2	; N.A. USED IN CPM-128
HRDVEC:	JMP	0	; N.A.	     "
DOHVEC:	JMP	0	; N.A.       "
DPBN3:	.WORD	0	; N.A.	     "
DPBN2:	.WORD	0	; N.A.       "
	.WORD	0	; N.A.       "
;
DPB1:	.WORD	CPMSPT		; SEC PER TRACK
	.BYTE	3+BLS-1		; BLOCK SHIFT
	.BYTE	7+((BLS-1)*8)   ; BLOCK MASK
EXMB:	.BYTE	TPI ^ 1
	.WORD	DSKSIZ-1 	; DISKSIZE-1
	.WORD	DIRENT-1 	; DIRECTORY MAX
	.BYTE	ALOC0		; ALLOC0
	.BYTE	0		; ALLOC1
	.WORD	DIRENT/4	; CHECK SIZE
	.WORD	SYSTRK		; OFFSET
;
	.PAGE
;
;|----------------------------------------------|
;|	WARM BOOT - RE-READ UP TO THE BIOS	|
;|----------------------------------------------|
;
WBOOT:	DI
	MVI	A,0FFH
	STA	VALSTP	; INHIBIT VALET AT THIS POINT
	LXI	SP,STACK; RESET STACK POINTER
	EI		
	CALL	DOBOOT
	ORA	A
	JRZ	WB1
	CALL	DISK
	LXI	H,WBTRY
	CALL	MESSG
	CALL	CONIN
	JMPR	WBOOT
;
WB1:	CALL	GOCPM	; INITIALIZE ENVIRONMENT
	JMP	WBTVEC	;  & JMP TO CCP OR CCP+3 (SEE WBTVEC)	
;	
DOBOOT:	MVI	A,11
	STA	SECCNT	; READ 11 SECTORS
	STA	RECNT	; RETRY 11 TIMES
			;  THROUGH, 10 THEREAFTER
	MVI	A,3	; SET COMMAND TO READ
	LXI	B,100H	; XFER 1 SECTOR AT A TIME
			;  SELECT DRIVE 0
	LXI	D,2	; START AT TRACK 0, SECTOR 2	
	LXI	H,CCP	;  LOAD START ADDRESS (BEGINNING OF CCP)
;
RWONE:	PUSH 	PSW	; SAVE LOAD DATA
	PUSH	B	;	'
	PUSH	D	;	'
;

	PUSH	PSW
	MOV	A,D
	CALL	CHKSID
RWJ1:	POP	PSW
;
	PUSH	H	;	'
	CALL	DISK 	; LOAD SECTOR
RWL1:	LDA 	DSKCYC	
  	ORA	A	; IF DSKCYC = 0
	JRZ	RWOK	;  THEN TRACK LOADED OK
	ANI	0E0H	;   ELSE SEE IF DISK OP DONE OR ERROR
	JRZ 	RWL1	;    IF DISK OP NOT DONE, THEN LOOP TO WAIT
	LXI	H,RECNT	;     ELSE TRY AGAIN
	DCR	M	; DECREMENT RETRY COUNTER
	POP	H	; RESTORE DISK COMMAND DATA
	POP	D
	POP	B
	JRZ	RWNFG	; IF 10 RETRYS, THEN ERROR
	POP	PSW
	JMPR	RWONE	; TRY AGAIN
;
RWOK:	LXI	H,SECCNT; DECREMENT SECTOR COUNTER
	DCR	M
	POP	H	; RESTORE DISK COMMAND DATA
	POP	D	
	POP     B
	JRZ	RWDONE	; IF SECTOR = 0 THEN GOTO CCP
	MVI	A,10	; ELSE SET RETRY COUNTER
	STA	RECNT
	INR	H	; INCREMENT LOAD POINTER BY
	INR	H	;  BY 200H (PHYSICAL SECTOR LENGTH)
	MOV	A,E
	CPI	10	; IS LAST READ SECTOR <> 10 ?
	JRNZ	RWUPSC	;  IF NOT, THEN GOT UPSC
	INR	D
	MVI	E,0	;    & SECTOR COUNT = 0 (NEXT INSTR. SETS TO 1)
RWUPSC:	INR	E	; INCREMENT SECTOR COUNT
  	POP	PSW	; RESTORE DISK COMMAND
	JMPR	RWONE	; GET NEXT SECTOR
;
RWNFG:	POP	PSW
	MVI	A,9
	RET
;
RWDONE:	POP	PSW	;  RECTIFY SP,
	XRA	A
	RET
;
;	COMMON CODE FOR BOOTS
;ŠGOCPM:	XRA	A	; INITIALIZE ACT. REG.
	STA	WSFLAG	; WORDSTR FLAG OFF
	STA	HSTACT	; HOST BUFFER INACTIVE
	STA	UNACNT	; CLEAR UNALLOC COUNT
	STA	NOKEY	; CLEAR VALET INHIBIT
	MVI	A,-3	;TURN OFF GRAPHICS
	CALL	LLATCH
	CALL	SETPG0
	LXI	B,80H	;DEFAULT DMA ADDRESS IS 80H
	CALL	SETDMA
	LXI 	H,WBINIT; GET ADDR OF SCREEN INITIALIZATION CHARS.
	CALL	MESSG	;  TURN OFF GRAPHICS & CLEAR TO EOS	
	LDA	CDISK   ; SEND CURRENT DISK # TO CCP
	MOV	C,A
	XRA	A
	STA	DSKFLG	; CLEAR DSKFLG
	RET	
;
SETPG0:	MVI	A,JMP	;JMP INSTRUCTION
	STA	0	;STORE JMP TO WBOOT
	LXI	H,WBOOTE ;WBOOT ENTRY POINT
	SHLD	1	;STORE JMP TO BDOS0
	STA	5
	LXI	H,BDOS	;BDOS ENTRY POINT
	SHLD	6
	RET
;
	.LIST
	.IFE	LSTDBK,[
	.XLIST
]
	.PAGE
;
SELDSK:	LXI	H,0	; SET ERROR CODE
	MOV	A,C	; GET DISK #
	CPI	NDISK	; IF DISK DOESN'T EXIST
	RNC		;  THEN RETURN
	STA	SEKDSK	; ELSE STORE DISK #
	ADD	A	; MULTIPLY BY 16
	ADD	A
	ADD	A
	ADD	A
	MOV	L,A
	LXI	D,DPBASE; ADD TO BASE OF DPB
	DAD	D
	RET
;
;|------------------------------|
;|set track given by register BC|
;|------------------------------|
;
SETTRK:	SBCD	SEKTRK	; TRACK TO SEEK
HOME:	RET		; RETURN ALSO USED BY DUMMY HOME
;
;|------------------------------|
;|set sector given by register c|
;|------------------------------|
;
SETSEC:	MOV	A,C
	STA	SEKSEC		;sector to seek
	RET
;
;|------------------------------|
;| set dma address given by BC	|
;|------------------------------|
;
SETDMA:	SBCD	DMAADR
	RET
;
;|------------------------------|
;| translate sector number BC	|
;|------------------------------|
;
SECTRA:	MVI	H,0
	MOV	L,C
	RET
;
;|------------------------------|
;|	READ A SECTOR		|
;|------------------------------|
;
READ:	xra	a		;accum=0
	sta	unacnt		;unacnt=0
	CMA			;DISABLE VALET INT.
	STA	DSKFLG
	mvi	a,1
	sta	readop		;read operation
	sta	rsflag		;must read data
	mvi	a,wrual
	sta	wrtype		;treat as unalloc
	jmp	rwoper		;to perform the readŠ;
;|------------------------------|
;|	WRITE A SECTOR		|
;|------------------------------|
;
WRITE:	xra	a		;0 to accumulator
	sta	readop		;not a read operation
	mov	a,c		;write type in c
	sta	wrtype
	cpi	wrual		;write unallocated?
	JRNZ	chkuna		;check for unalloc
;
;	write to unallocated, set parameters
;
	mvi	a,blksiz/128	;next unalloc recs
	STA	DSKFLG		; DISABLE VALET INT.
	sta	unacnt
	lda	sekdsk		;disk to seek
	sta	unadsk		;unadsk = sekdsk
	lhld	sektrk
	shld	unatrk		;unatrk = sectrk
	lda	seksec
	sta	unasec		;unasec = seksec
;
chkuna:	MVI	A,0FFH		;DISABLE VALET INT.
	STA	DSKFLG
;
;	check for write to unallocated sector
;
	lda	unacnt		;any unalloc remain?
	ora	a
	JRZ	alloc		;skip if not
;
;	more unallocated records remain
;
	dcr	a		;unacnt = unacnt-1
	sta	unacnt
	lda	sekdsk		;same disk?
	lxi	h,unadsk
	cmp	m		;sekdsk = unadsk?
	JRNZ	alloc		;skip if not
;
;	disks are the same
;
	lxi	h,unatrk
	call	sekcmp	;sektrk = unatrk?
	JRNZ	alloc	;skip if not
;
;	tracks are the same
;
	lda	seksec		;same sector?
	lxi	h,unasec
	cmp	m		;seksec = unasec?
	JRNZ	alloc		;skip if not
;
;	match, move to next sector for future ref

	inr	m		;unasec = unasec+1
	mov	a,m		;end of track?
	cpi	cpmspt		;count CP/M sectors
	JRC	noovf		;skip if no overflow
;
;	overflow to next track
;
	mvi	m,0		;unasec = 0Š	lhld	unatrk
	inx	h
	shld	unatrk		;unatrk = unatrk+1
;
;	match found, mark as unnecessary read
;
noovf:	xra	a		;0 to accumulator
	sta	rsflag		;rsflag = 0
	JMPR	rwoper		;to perform the write
;
;	not an unallocated record, requires pre-read
;
alloc:	xra	a		;0 to accum
	sta	unacnt		;unacnt = 0
	inr	a		;1 to accum
	sta	rsflag		;rsflag = 1
;
;|----------------------------------------------|
;|	Common code for READ and WRITE follows  |
;|----------------------------------------------|
;
rwoper:	xra	a		;zero to accum
	sta	erflag		;no errors (yet)
	STA	DSKFLG		;ENABLE VALET INT.
	lda	seksec		;compute host sector
	ORA	A	;>--|
	RAR		;>--|	
	ORA	A	;>--|-- # OF (ORA A/RAR) DEPENDANT
	RAR		;>--|	   ON VALUE OF HSTBLK
	sta	sekhst		;host sector to seek
;
;	active host sector?
;
	lxi	h,hstact	;host active flag
	mov	a,m
	mvi	m,1		;always becomes 1
	ora	a		;was it already?
	JRZ	filhst		;fill host if not
;
;	host buffer active, same as seek buffer?
;
	lda	sekdsk
	lxi	h,hstdsk	;same disk?
	cmp	m		;sekdsk = hstdsk?
	JRNZ	nomatch
;
;	same disk, same track?Š;
	lxi	h,hsttrk
	call	sekcmp	;sektrk = hsttrk?
	JRNZ	nomatch
;
;	same disk, same track, same buffer?
;
	lda	sekhst
	lxi	h,hstsec	;sekhst = hstsec?
	cmp	m
	JRZ	match		;skip if match
;
;	proper disk, but not correct sector
;

nomatch:lda	hstwrt		;host written?
	ora	a
	cnz	WRITEH		;clear host buff
;
;	may have to fill the host buffer
;
filhst:	lda	sekdsk
	sta	hstdsk
	lhld	sektrk
	shld	hsttrk
	lda	sekhst
	sta	hstsec
	lda	rsflag		;need to read?
	ora	a
	cnz	READHS		;yes, if 1
	xra	a		;0 to accum
	sta	hstwrt		;no pending write
;
;	COPY DATA TO OR FROM BUFFER
;
match:	lda	seksec		;mask buffer number
	ani	secmsk
	mov	l,a		;ready to shift
	mvi	h,0		;double count
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	dad	h
;	hl has relative host buffer address
	lxi	d,hstbuf
	dad	d		;hl = host address
	xchg			;now in DE
	lhld	dmaadr		;get/put CP/M data
;	mvi	c,128		;length of move
	lda	readop		;which way?
	ora	a
	JRNZ	rwmove		;skip if read
;
;	write operation, mark and switch direction
;
	mvi	a,1
	sta	hstwrt		;hstwrt = 1
	xchg			;source/dest swap
;
;	DE is source, HL is dest, MOVE 128 BYTES
;
rwmove:	XCHG		; LDIR MOVES (DE)<-(HL)
	LXI	B,128	; MOVE 128 BYTES
	LDIR		; DO MOVE
;
;	data has been moved to/from host buffer
;
	lda	wrtype		;write type
	cpi	wrdir		;to directory?
	lda	erflag		;in case of errors
	rnz			;no further processing
;
;	clear host buffer for directory write
;
	ora	a		;errors?
	rnz			;skip if so
	xra	a		;0 to accum
	sta	hstwrt		;buffer written
	call	WRITEH
	lda	erflag
	ret
;
;|----------------------------------------------|
;|	Utility subroutine for 16-bit compare   |
;|----------------------------------------------|
;
sekcmp:
	;HL = .unatrk or .hsttrk, compare with sektrk
	xchg
	lxi	h,sektrk
	ldax	d		;low byte compare
	cmp	m		;same?
	rnz			;return if not
;	low bytes equal, test high 1s
	inx	d
	inx	h
	ldax	d
	cmp	m	;sets flags
	ret
;
	.LIST
	.IFE	LSTDSK,[
	.XLIST
]
	.PAGE
;
;|----------------------------------------------|
;|  WRITEHST performs the physical write to	|
;|  the host disk, READHST reads the physical	|
;|  disk.					|
;|----------------------------------------------|
;
;hstdsk = host disk #, hsttrk = host track #,
;hstsec = host sect #. write 'hstsiz' bytes
;from hstbuf and return error flag in erflag.
;return erflag non-zero if error
WRITEH:	MVI	A,2	
	JMPR	RDH1
READHS:	MVI	A,3	
RDH1:	STA	DSKCMD
RDH2:	MVI	A,10	; SET FOR 10 RETRYS
	STA	DSKFLG	; INHIBIT VALET
HSL1:	STA	RECNT	; STORE RETRY
	CALL	GSTUFF	; GET REGS. FOR DISK
	LDA	DSKCMD	; GET COMMAND FOR DISK
	CALL	DISK	; DO DISK OPERATION
HSL2:	LDA	DSKCYC	; GET DSKCYC
	ORA	A	; IF DSKCYC <> 0
	JRNZ	HSL3	;  THEN ..L3
	LDA	DSKCMD	; ELSE TEST LAST OP
	CPI	2	;IF READ JUST FINISHED
	JRNZ	HSI1	; THEN CONTINUE
;
	MVI	C,3	; ELSE FORMAT OR WRITE JUST
HSL5:	MVI	B,0CDH	;  DONE SO DELAY TO GIVE TIME
HSL6:	DJNZ	HSL6	;  FOR TUNNEL ERASE FIELD TO 
	DCR	C	;  DECAY.
	JRNZ	HSL5
;
HSI1:	XRA	A	; OPERATION DONE
	STA	DSKFLG	; ENABLE VALET
	RET
HSL3:	ANI	0E0H	; IF NOT ERRONEOUS COMPLETION
	JRZ	HSL2	;  THEN TEST DSKCYC AGAIN
     	LDA	RECNT	; ELSE DCR. RETRY RETRY
	DCR	A	;  COUNTER. IF <> 0
	JRNZ	HSL1	;   THEN RETRY
	MVI	A,9	;  ELSE REPORT ERROR
	CALL	DISK
HSR1:	LXI	H,OPTMSG; PUT UP OPTION MESSG.
	CALL	MESSG
HSJ2:	MVI	C,CTRLX	; CLEAR KYBRD BUFFER
	CALL	DISPLY
	CALL	CONIN	; GET KEY
	ANI	0DFH	; MAKE UPPER CASE
	CPI	'W'	; IF KEY = W
	JRZ	HSR2	;  THEN WARM BOOT
	CPI	'I'	; ELSE IF KEY = I
	JRZ	HSI1	;  THEN IGNORE LAST OP.
	CPI	12H	; ELSE IF <> KEY = CTRL/R
	JNZ	RDH2	;  THEN RETRY DISK OP.
	MVI	A,8	; ELSE REPORT FDC RESULT BYTES
	CALL	DISK
	JMPR	HSR1	; LOOP TO OPTIONS AGAIN
;
HSR2:	LDA	SETFLG
	ORA	A	; IF IN VALET
	CNZ	CLNVAL	;  THEN RESET VALET VARIABLES
	JMP	WBOOT	; WARM BOOT
;
;	SET UP DATA FOR WRITEH & READHS
;
GSTUFF:	LXI	H,HSTBUF; HL SET (ADDRESS)
	LDA	HSTSEC
	INR	A
	MOV	E,A	; E SET	(SECTOR)
	MVI	B,1	; B SET	(# SECTORS TO XFER)
	LDA	HSTDSK
	MOV	C,A	; C SET	(DRIVE #)
;
	LDA	HSTTRK	; SET SIDE BIT IF NEEDED
	MOV	D,A
;
CHKSID	=	.
;
	.IFN	TPI,[
;
	BIT 	0,C
	LDA	EXM
	JRZ	CHKBTH
	LDA	EXMB
CHKBTH:	ORA	A
	MOV	A,D
	JRNZ	CHK48	
	CPI	80	; CHECK FOR SIDE 2 OF 48 TPI
	RC
	SUI	79+81H
	JMPR	SIDOK
;
]
	.IFE	TPI,[	
;
	JMP	CHK48
	.BLKB	18
;
]
;
CHK48:	CPI	40	; CHECK FOR SIDE 2 OF 96 TPI
	RC
	SUI	39+81H
;
SIDOK:	MOV	D,A
	RET
;
	.PAGE
;
;GENERAL FLOPPY HANDLER
;STARTS MOTOR, HOMES IF NEEDED,
;SEEKS IF NEEDED, AND INITIATES
;READ, WRITE, OR FORMAT
;
;ENTRY PARAMETERS
;
;	A = OPERATION CODE
;	  0 = RETURN CURRENT STATUS
;	  1 = FORMAT TRACK
;	  2 = SECTOR WRITE
;	  3 = SECTOR READ
;	  8 = DISPLAY FDC RESULT BYTE ERROR MSSG.
;	  9 = DISPLAY ENGLISH DISK ERROR MSSG.
;
;	B = # OF SECTORS TO TRANSFER (MUST = 1)
;	C = DRIVE #
;	D = TRACK TO BEGIN TRANSFER (BIT 7 = SIDE)
;	E = SECTOR TO BEGIN TRANSFER
;	HL = ADDRESS TO TRANSFER TO/FROM
;
;DSKCYC CODES
;
;       0 = SUCCESSFUL COMPLETION
;	1 = DFM DATA FORMAT
;	2 = DWR DATA WRITE
;	3 = DRD DATA READ
;	4 = RC1 RECAL 1
;	5 = SK1 SEEK TO 4
;	6 = RC2 RECAL 2
;	7 = SK2 SEEK TO TRACK
;       8 = WFR WAITING FOR READY
;
;ERROR IS INDICATED BY SETTING UPPER BIT(S) OF
;THE DSKCYC SEQUENCE CODE.
;
;	BIT  7     = u765 ERRONEOUS COMPLETION
;	BITS 7,6   = OPERATION TIME OUT
;	BITS 7,6,5 = u765 NOT READY
;
;
;|----------------|
;|  REPORT DSKYC  |
;|----------------|
;		
DISK:	ORA	A	;IF ACC. <>0
	JRNZ	DSJ1	; THEN GO NEXT TEST
	LDA	DSKCYC	; ELSE TEST DSKCYC
	BIT	7,A
	RET
;
;|--------------------------------------|
;|  REPORT ERROR WITH FDC RESULT BYTES	|
;|--------------------------------------|
;
DSJ1:	CPI	8	;IF ACC. <> 8
	JRNZ	DSJ2	; THEN GO ..J2
	CALL	CRLF
	LXI	H,DERMSG
	CALL	MESSG
	LDA	RESULT
	MOV	B,A	
	INR	B
	LXI	H,DSKCYC
DSL1:	MVI	C,SPC
	CALL	CONOUT
	PUSH	B
	MOV	B,M
	CALL	DSHEX
	INX	H
	POP	B
	DJNZ	DSL1
	RET
;
;|-------------------------------------|
;|  REPORT ERROR WITH ENGLISH MESSAGE  |
;|-------------------------------------|
;
DSJ2:	CPI	9
	JRNZ	DSJ3
	LXI	H,VCRLF
	CALL	MESSG
	LDA	RWUNIT
	ANI	1
	ADI	'A'
	STA	DRVNUM
	LDA	DSKCYC
	MOV	B,A
	ANI	0E0H
;
	LXI	H,TERR	; NODISK
	CPI	0C0H
	JRZ	DSV1
;
	CPI	0E0H
	JRNZ	DSV2
	MVI	B,0	; SYSTEM
;
DSV2:	MOV	A,B	; ALL OTHERS
	ANI	0FH
	CPI	4
	JRC	DSV2A
	ANI	5	; I.E. 7=5,6=4
DSV2A:	INR	A
	MOV	B,A
	LXI	H,CERR-6
	LXI	D,6
DSV3:	DAD	D
	DJNZ	DSV3
DSV1:	CALL	MESSG
	LXI	H,DERMSG
	JMP	MESSG
;
	.PAGE
;
;|---------------------|
;|  DO DISK OPERATION  |
;|---------------------|
;
;	SAVE DISK PARAMETERS
;
DSJ3:	STA	DSKCMD	;SET UP DISK OP. TABLES
	MOV	A,D	;--HD & UNIT
	ANI     80H
	RLC
	STA	RWHD
	RLC
	RLC
	ORA	C
	STA	FMUNIT
	STA	RWUNIT
	STA	SDUNIT
	STA	SKUNIT
	ANI	3
	STA	RCUNIT
	MOV	A,D
	ANI	7FH
	STA	RWCYL
;
	.IFN	TPI,[
;
	MOV	D,A	; ADJUST SKCYL FOR 48/96
	BIT	0,C	; CHECK DRIVE NUMBER
	LDA	EXM
	JRZ	CYLGN
	LDA	EXMB
CYLGN:	ORA	A
	MOV	A,D
	JRZ	OKCYL
	RAL
;
]
	.IFE	TPI,[
;
	JMP	OKCYL
	.BLKB	13
]
;
OKCYL:	STA	SKCYL
	MOV	A,E	;--SECTOR
	STA	RWREC
;
	SHLD	FMADDR	;--DATA ADDRESS
	SHLD	RWADDR
	RLCR	B	
        MVI	C,0
	DCX	B	
	SBCD	RWCNT	; DATA COUNT
;
	LDA	DSKCMD
	CPI	1
	JRZ	DSJ5	; IF COMMAND = FORMAT, THEN SKIP
	MOV	C,A	;  ELSE SET UP RWTBL
	MVI	A,RWCODE
	ADD	C
	STA	RWCMD
	MVI	A,39H
	BIT	0,C
	JRNZ	DSJ4
	ORI	40H
DSJ4:	STA	RWTBL
DSJ5:	DI
	LHLD	MTRCNT	;EXAMINE MOTOR COUNT
	MOV	A,H
	ORA	L	;IF MOTOR ON
	LXI	H,MTRTIM
	SHLD	MTRCNT
	JRZ	STRMTR
;
	EI
	CALL	SNSTAT
	BIT	5,A
	JRNZ	DSJ5A
	LXI	H,0
	SHLD	MTRCNT
	JMP	NOTRDY
DSJ5A:	CALL	GTFLGS	; EXAMINE PROPER HMFLG
	MOV	A,M
	ORA	A	;IF HMFLG = 0
	JRZ	DSJ8
	MVI	A,7	; DSKCYC = 7
	LXI	H,SKTBL
	JMPR	DSJ10
;
DSJ8:	MVI	A,4	; DSKCYC = 4
	LXI	H,RCLTBL
DSJ10:	CALL	DORCSK
	EI
 	RET
;
	.PAGE
;
;|------------------------------|
;|	MISC. DISK ROUTINES	|
;|------------------------------|
;
GTFLGS:	LDA	RWUNIT	; GET PROPER HMFLG
	LXI	H,HMFLGS
	BIT	0,A
	RZ
	INX     H
	RET
;
SETDT:	MVI	A,60	;SET OPERATION TIMEOUT
	STA	DSKCNT	; (DECREMENTED BY SRV60)
	XRA	A
	PUSH	H
	MVI	B,8	; AND CLEAR RESULT BYTES
	LXI	H,ST0
SDTL1:	MOV	M,A
	INX	H
	DJNZ	SDTL1
	POP	H
	RET
;
;	START DRIVE MOTORS
;
STRMTR:	MVI	A,40
	CALL    SETDT+2	; 1/2 SECOND FOR DRIVE UP TO SPEED
	MVI	A,8	; DSKCYC = 8
	STA	DSKCYC	
	SUI	7
	CALL	LLATCH
	EI
;
; CLEAR HOME FLAGS
;
CLRFLG:	LXI	H,0
	SHLD	HMFLGS	
	RET
;
;	CLEAR ANY RESULT BYTES FROM FDC
;	AND ISSUE ILLEGAL COMMAND TO RESET
;
CLRFDC:	MVI	B,8	; CLEAR FDC
CFL1:   MOV	C,B
	CALL	R765
	MOV	B,C
	DJNZ	CFL1	
	RET
;
	.PAGE
;		
;|----------------------------------------------|
;|  BASIC FLOPPY DRIVER				|
;|  SETS UP BOTH FLOPPY CONTROLLER AND DMA FOR	|
;|  A FLOPPY OPERATION AND DELIVERS COMMAND.	|
;|  SEE FLOPPY COMMAND TABLES FOR TABLE FORMAT.	|
;|  RETURNS WITH Z FLAG SET IF A TIMEOUT OCCURS.|
;|  'A' CONTAINS ST3 ON EXIT FOR 'SENSE DRIVE	|
;|  STATUS' COMMANDS				|
;|----------------------------------------------|
;
;---- LEAVES INTERRUPT DISABLED	----
;
SNSTAT:	LXI	H,SDSTBL	; SENSE DRIVE STATUS
	MVI	A,1
	JMPR	DORCS1
;
DORCSK:	STA	DSKCYC		; SEEK OR RECALIBRATE
	MVI	A,2
DORCS1:	STA	RESULT
	CALL	SETDT
;	DROP 	THROUGH TO DISKOP
;
DISKOP:	MOV	D,H
	MOV	E,L
	BIT	4,M
	JRZ	DOJ3	;Z=SKIP DMA SETUP
	MVI	A,44H	;--SET UP DMA MODE
	BIT	6,M
	JRZ	DOJ2
	MVI	A,48H
DOJ2:	OUT	DMAWMR
	PUSH	H
	INX	H
	MVI	C,FPYBCA
	OUTI
	OUTI
	MVI	C,FPYBWR
	OUTI
	OUTI
	MVI	A,0
	OUT	DMAWSM	;--MASK	OFF
	DCX	H
	XCHG
	POP	H	
DOJ3:	PUSH	H	;SEND 765 COMMANDS
	MOV	A,M
	ANI	0FH	;ISOLATE # BYTES TO SEND
	MOV	B,A	;B=#OF BYTES
	MOV	H,D
	MOV	L,E
	DI
DOL2:	INX	H	;DO UNTIL B=0 OR ERROR
	MOV	C,M
	PUSH	B
	CALL	W765	; SEND ONE BYTE TO FDC
	POP	B
	JRZ	DOJ5	; GO ..J5 IF ERROR
	DJNZ	DOL2	;END DO
	POP	H
	BIT	7,M	;IF READ ST3
	RZ		; THEN GO ..J4
;
	MVI	B,1	; READ ST3
	CALL	REDRES	
	RNZ		; HAVE READ ALL BYTES
	PUSH	H	;  ELSE ERROR
;
DOJ5:	POP	H	;KEEP SP CURRENT
;
NOTRDY:	CALL	CLRFDC
	LDA	DSKCYC
	ORI	0E0H
	STA	DSKCYC
	XRA	A
	RET		;RETURN (ERROR)
;
;This routine will wait for next byte ready then send the 
;command passed in the C reg to the floppy controller
;
W765:	MVI	B,31	
..L0:	DJNZ	..L0	; DELAY 36 US.(4 Mhz)
	MVI	B,10	; 10 RETRIES
..L1:	IN	SFLPY	; READ STATUS
	ANI	0C0H
	CPI	80H	; IF B7=1 & B6=0
	JRZ	..J0	;  THEN ..J0
	DJNZ	..L1	; ELSE RETRY
	RET
;
..J0:	ORA	A
	MOV	A,C	; CLEAR Z BIT
	OUT	DFLPY	; SEND BYTE
	RET
;
;This routine will wait next byte ready then input the
;next status byte from the FDC
;
R765:	MVI	B,31	
..L0:	DJNZ	..L0	; DELAY 36 US.(4 Mhz)
	MVI	B,10	; 10 RETRIES
..L1:	IN	SFLPY	; read status
	ANI	0C0H
	CPI	0C0H	; IF B7=B6=1
	JRZ	..J0	;  THEN ..J0
	DJNZ	..L1	; ELSE RETRY
	RET
;
..J0:	ORA	A	; CLEAR Z BIT = O.K.
	IN	DFLPY	; READ BYTE
	RET
;
	.LIST
	.IFE	LSTFIN,[
	.XLIST
]
	.PAGE
;
;||------------------------------------||
;||				       ||
;||	FLOPPY INTERRUPT ROUTINE       ||
;||				       ||
;||------------------------------------||
;
SRVFPY:	SSPD	TEMSTK	
	LXI     SP,INTSTK
       	PUSH	H
	PUSH	D
	PUSH	B
	PUSH	PSW
	IN	SFLPY	
	ANI	10H	; IF FDC NOT BUSY
	JRZ	FPJ2	;  THEN SENSE INT. STATUS
;
;|-----------------------------------------|
;|  RESULT PHASE FOR READ, WRITE OR FORMAT |
;|-----------------------------------------|
;
	MVI	B,7	; ELSE READ 7 RESULT BYTES
	CALL	REDRES
	JRZ	FPJ3	; DIDN'T READ ALL BYTES
	LDA	ST0	; CHECK ST0
	ANI	0F8H	; IF ST0 NOT OK
	LXI	H,DSKCYC
	JRNZ	FPJ5	; THEN ERROR
;
;|-----------------------------------------------|
;|  RESULT PHASE FOR SEEK, RECAL OR READY CHANGE |
;|-----------------------------------------------|
;
FPJ2:	MVI	C,8	
	CALL	W765	; ISSUE SENSE INT. STATUS
	JRZ	FPJ3	; IF ERROR, THEN GO DERTIM
	CALL	R765	
	JRZ	FPJ3	; READ 1ST RESULT BYTE
	MOV	C,A	; SAVE ST0
	CPI	80H	; IF INVALID COMMAND WAS ISSUED
	JRZ 	FPOK	;  THEN WE ARE DONE
	LXI	H,ST0
	MOV	M,C	; ELSE STORE ST0
	CALL	R765	; READ NEXT BYTE
FPJ3:	JZ	DERTIM	;  FDC NOT READY
	INX	H
	MOV	M,A	; STORE ST1
	MOV	A,C  
	ANI	0F8H
	CPI	20H	; IF SEEK OR RECAL JUST DONE
	JRZ	FPJ2	;  THEN CHECK FOR HIDDEN INT.
	LXI	H,DSKCYC;  ELSE READY LINE HAS CHANGED STATE
	MOV	A,M	
	CPI	8	; IF WAITING FOR READY
FPJ4:	JRZ	IIEND	;  THEN EXIT
FPJ5:	SET	7,M	; ELSE ERROR
	JMPR	FPJ2	; CHECK FOR HIDDEN INT.
;
;|--------------------------------------|
;|	CHECK FOR NEXT OPERATION	|
;|--------------------------------------|
;
FPOK:   XRA	A	
	STA	DSKCNT	; CLEAR DSKCNT
FPJ8:	LXI 	H,DSKCYC; AND CHECK DSKCYC
	MOV	A,M
	BIT	7,A	; IF BIT 7 SET
	JRNZ	FPC7	;  THEN ERROR
	MVI	M,0	; ELSE CLEAR DSKCYC
	SUI	4	; IF DSKCYC = 0,1,2, OR 3
	JRC	IIEND	;  THEN EXIT
	JRNZ	FPC1	; ELSE IF DSKCYC <> 4 THEN ..C1
;				
	MVI	A,4	; DSKCYC NOW = 4
	STA	SKCYL	;  SO DO SEEK TO TRACK 4
	INR	A	; NEW DSKCYC = 5
	LXI	H,SKTBL
	JMPR	FPC9	
;
FPC1:	DCR	A	; IF DSKCYC <> 5
	JRNZ	FPC2	;  THEN ..C2
	LXI	H,RCLTBL; DSKCYC NOW = 5
	MVI	A,6	; SO DO 2ND RECALIBRATE
	JMPR	FPC9	
;
FPC2:	DCR	A	; IF DSKCYC <> 6
	JRNZ	FPC5	;  THEN ..C5
;
	CALL	GTFLGS	; DSKCYC NOW = 6
	INR	M	; SO SET PROPER HMFLG
;
	LDA	RWCYL	; THEN SEEK TO DESIRED TRACK
	ORA	A
	JRZ	FPC6
	STA	SKCYL	;  STORE TRACK IN SEEK TABLE
	LXI	H,SKTBL
	MVI	A,7	; NEW DSKCYC  = 7
FPC9:	CALL	DORCSK	;  SEEK TO TRACK
IIEND:	JMP	IEND
;
FPC5:	DCR	A	; IF DSKCYC <> 7
FPC7:	JRNZ	DSKERR	;  THEN ERROR, ARE NO OTHERS
FPC6:	MVI	A,7	; DSKCYC NOW = 7
	STA	RESULT
	LXI	H,MTRTIM; SO RESET MOTOR TIMER
	SHLD	MTRCNT
	LDA	DSKCMD	; NEW DSKCYC = 1,2, OR 3
	STA	DSKCYC
	DCR	A	; IF DSKCYC <> = 1
	JRNZ	FPC3	; THEN ..C3
	LXI	H,FMTTBL;  ELSE NEXT OP IS FORMAT
	JMPR	FPC4
FPC3:	LXI	H,RWTBL	; NEXT OP IS READ OR WRITE
FPC4:	CALL	SETDT	;  CLEAR RESULT BYTES & RESET TIMEOUT COUNTER
	CALL	DISKOP	; ISSUE COMMAND
	JMPR	IIEND
;
;|------------------------------|
;|	READ RESULTS (B) TIMES  |
;|------------------------------|
;
REDRES:	LXI	D,ST0	; ELSE READ RESULTS
	LXI	H,RESNUM
RDRSL1:	PUSH	B
	CALL	R765	;READ 1 BYTE FROM FDC
	POP	B
	RZ		; ERROR, Z BIT SET
	STAX	D	;  SAVE BYTE
	INX	D
	INR	M	; INCR COUNTER
	DJNZ	RDRSL1	; READ NEXT BYTE
	INR	B	; CLEAR Z BIT
	RET
;
;|------------------------------|
;|	DISK ERRORS		|
;|------------------------------|
;
WFRBAD:	LXI	H,0	; -ERROR WHEN WAITING FOR READY
	SHLD	MTRCNT	;  CLEAR MTRCNT SO MOTOR IS STARTED
	JMP	TIMOUT	; DSKCYC OR WITH 0C0H
;
DSKERR:	CALL	CLRFDC	;  NORMAL OPERATION ERROR
	LDA	DSKCYC	;    DSKCYC OR WITH 80H
	ORI	80H
	STA	DSKCYC
	JMPR	IIEND	
;
DERTIM:	CALL    NOTRDY	;  u765 NOT READY ERROR
	JMPR	IIEND	;    DSKCYC OR WITH 0E0H
;
	.LIST
	.IFE	LSTIO,[
	.XLIST
]
	.PAGEŠ;
;|--------------------------------------|
;|		I/O DRIVERS		|
;|--------------------------------------|
;
;|-----------------------|
;|   IOBYTE REDIRECTION  |
;|-----------------------|
;
CONIN:	LDA	IOBYTE
	ANI	3
	JRZ	TTYIN
	BIT	0,A
	JRZ	LSTIN
	JMPR	CRTIN
;
CONOUT:	LDA	IOBYTE
	ANI	3
	JRZ	TTYOUT
	BIT	0,A
	JRZ	LSTOUT
	JMPR	CRTOUT
;
READER:	LDA	IOBYTE
	RAR
	RAR
	ANI	3
	JRZ	TTYIN
	DCR	A
	JRZ	LSTIN
	DCR	A
	JRZ	CRTIN
	JMPR	TTYIN
;
PUNCH:	LDA	IOBYTE
	RAR
	RAR
	RAR
	RAR
	ANI	3
	JRZ	TTYOUT
	DCR	A
	JRZ	CRTOUT
	DCR	A
	JRZ	LSTOUT
	JMPR	TTYOUT
;
LIST:	LDA	IOBYTE
	RAL
	RAL
	RAL
	ANI	3
	JRZ	TTYOUT
	DCR	A
 	JRZ	CRTOUT
	JMPR	LSTOUT
;
	.PAGE
;
;|----------------------|
;|	I/O ROUTINES    |
;|----------------------|
;
;	OUTPUT CHAR. TO LIST DEVICE (PRINT PORT)
;
LSTOUT:	CALL	LSTOST
	JRNZ	LSTOUT
	MOV	A,C
	OUT	DPRTR
	RETŠ;
;	INPUT CHAR. FROM LIST DEVICE (PRINT PORT)
;
LSTIN:	CALL	LSTIST
	JRZ	LSTIN
	IN	DPRTR
	RET
;
;	OUTPUT CHAR. TO TTY DEVICE (COMM.PORT)
;
TTYOUT:	CALL	TTYOST
	JRNZ	TTYOUT
	MOV	A,C
	OUT	DCOMM
	RET
;
;	INPUT CHAR. FROM TTY DEVICE (COMM. PORT)
;
TTYIN:	CALL	TTYIST
	JRZ	TTYIN
	IN	DCOMM
	RET
;
;	OUTPUT CHAR. TO CONSOLE DEVICE (CRT)
;
CRTOUT:	JMP	DISPLY
;
;	INPUT CHAR. FROM CONSOLE DEVICE (KEYBOARD)
;
CRTIN: 	EI
	LDA     TIMFLG
	ORA 	A
     	CZ	DSPTIM
	DI
	LDA	KEYCNT	;LOOP UNTIL CHAR.
	ORA	A
	JRZ	CRTIN
	PUSH	H
	PUSH	D
	PUSH	B
	LXI	H,KEYBUF+1
	LXI	D,KEYBUF
	LXI	B,KBUFLN-1
	LDAX	D
	LDIR
	LHLD	KEYPNT
	DCX	H
	SHLD	KEYPNT
	LXI	H,KEYCNT
	DCR	M
	EI
	ANI	7FH	;MASK OFF BIT 7
	POP	B
	POP	D
	POP	H
	RET
;
	.PAGE
;
;|----------------------------|
;|  I/O STATUS TEST ROUTINES  |
;|----------------------------|
;
;	TEST CONSOLE DEVICE INPUT STATUS
;
CONST:	LDA	IOBYTE
	ANI	3
	JRZ	TTYIST
	BIT	0,A
	JRZ	LSTIST
	LDA	KEYCNT
	ORA	A
	JMPR	TSTGEN
;
;	TEST LIST DEVICE OUTPUT STATUS
;
LISTST:	LDA	IOBYTE
	RAL	
	RAL
	RAL
	ANI	3
	JRZ	TTYOST
	DCR	A
	JRZ	TSTYGN
;
LSTOST:	MVI	A,10H	; TEST LIST OUTPUT STATUS
	OUT	SPRTR
	IN	SPRTR
TSTOGN:	ANI	24H
	CPI	24H
	JRZ	TSTYGN
	MVI	A,0
	RET
;
LSTIST:	MVI	A,10H	; TEST LIST INPUT STATUS
	OUT	SPRTR
	IN	SPRTR
	JMPR	TSTIGN
;
TTYOST:	MVI	A,10H	; TEST TTY OUTPUT STATUS
	OUT	SCOMM
	IN	SCOMM
	JMPR	TSTOGN
;
TTYIST:	MVI	A,10H	; TEST TTY INPUT STATUS
	OUT	SCOMM
	IN	SCOMM
TSTIGN:	ANI	1
TSTGEN:	RZ	
TSTYGN:	MVI	A,0FFH
	RET
;
	.PAGE
;
CRLF:	MVI	C,0AH
	CALL	CONOUT
	MVI	C,0DH
	JMP	CONOUT
;
;	GENERAL MESSAGE ROUTINE
;
MESSG:	MOV	C,M
	BIT	7,C
	RES	7,C
	INX	H
	JNZ	CONOUT
	CALL	CONOUT
	JMPR	MESSG
;
;	DISPLAY H AS FOUR ASCII CHARS.
;
DSADDR:	MOV	B,H
	CALL	DSHEX
	MOV	B,L
;
;	DISPLAY B AS TWO ASCII CHARACTERS
;
DSHEX:	MOV	A,B
	RLC
	RLC
	RLC
	RLC
	CALL	DHJ1
	MOV	A,B
DHJ1:	ANI	0FH
	ADI	30H
	CPI	3AH
	JM	DHJ2
	ADI	7
DHJ2:	MOV	C,A
	JMP	CONOUT
;	
;	CHANGE CONTROL LATCH: ENTER WITH BITS TO
;	BE CHANGED IN A. IF Z IS SET, LATCH WILL
;	BE ANDED WITH VALUE IN A; OTHERWISE ORED.
;	DISABLES INTERRUPT.Š;
LLATCH:	PUSH	PSW
	MVI	A,0CFH
	DI
	OUT	SPIOA
	XRA	A
	OUT	SPIOA
	LDA	LSTATE
	MOV	B,A
	POP	PSW
	JRZ	LLJ1
	ORA	B
	JMPR	LLJ2
LLJ1:	ANA	B
LLJ2:	STA	LSTATE
	OUT	DPIOA
	MVI	A,0B8H
	OUT	DPIOB
	MVI	A,98H
	OUT	DPIOB
	MVI	A,0B8H	
	OUT	DPIOB
	RET
;
;	MAKE THE SOUND SPECIFIED BY THE 14 BYTE TABLE
;  	POINTED TO BY H-L (R14 OF THE SOUND GENERATOR
;  	IS FIRST, R0 LAST)
;
SOUND:	MOV	A,M
	STA	TONPER
	INX	H
        MVI	A,0CFH
	DI
	OUT	SPIOAŠ	XRA	A
	OUT	SPIOA
	MVI	A,0FFH
	OUT	DPIOB
	LXI	B,14*256+DPIOA
SOL1:	DCR	B
	OUTP	B
	INR	B
	MVI	A,0C3H
	OUT	DPIOB
	MVI	A,0E3H
	OUT	DPIOB
	OUTI		;SEND THE DATA
	MVI	A,0E7H
	OUT	DPIOB
	MVI	A,0C7H
	OUT	DPIOB
	MVI	A,0E7H
	OUT	DPIOB
	JRNZ	SOL1
	RET
;
	.LIST
	.IFE	LSTDSP,[
	.XLIST
]
	.PAGEŠ;
;|--------------------------------------|
;|					|
;|   500 DISPLAY & KEYBOARD DRIVER	|
;|					|
;|--------------------------------------|
;
;|----------------------|	
;|    CONTROL CODES	|
;|----------------------|
;
;	CTRL/G	(07H) BELL
;	CTRL/H	(08H) BACKSPACE
;	CTRL/I	(09H) TAB
;	CTRL/J	(0AH) LINE FEED
;	CTRL/K	(0BH) REV. LINE FEED
;	CTRL/L	(0CH) RIGHT CURSOR
;	CTRL/M	(0DH) CARRIAGE RETURN
;	CTRL/X	(08H) CLEAR KEYBOARD BUFFER
;	CTRL/Z	(1AH) CLEAR ACTIVE REG. & HOME CURSOR
;	CTRL/^	(1EH) CURSOR HOME
;
;	BS	(08H) BACKSPACE
;	CR	(0DH) CARRIAGE RETURN
;	LF	(0AH) LINE FEED
;
;|----------------------|
;|    ESCAPE CODES	|
;|----------------------|
;
;	ESC 0XXYY PLOT POINT
;	ESC 1XXYY PLOT VECTOR
;	ESC 2XXYYXXYY 	BLOCK DRAW
;	ESC 3 	CLEAR GRAPHICS & PLOT BRIGHT
;	ESC 4XXYYXXYY	BLOCK FILL
;	ESC 5 M1M2 	SET MASKS
;	ESC 6	DISABLE GRAPHIC IMAGE
;	ESC 7	ENABLE GRAPHIC IMAGE
;	ESC 8	SET TO PLOT BRIGHT
;	ESC 9	SET TO PLOT DARK
;	ESC :	READ DATE
;	ESC ;	SET PRINTER BAUD FROM CMOS RAM
;	ESC <	SET COMM. BAUD FROM CMOS RAM
;	ESC =LC DIRECT CURSOR MOVE
;	ESC >	READ TIME
; 	ESC ?A	READ CMOS RAM
;	ESC @AD	WRITE TO CMOS RAM (CONSULT CMOS ALLOCATION)
;	ESC A	CURSOR UP
;	ESC B	CURSOR DOWN
;	ESC C	CURSOR RIGHT
;       ESC D   CURSOR LEFT
;       ESC E   -- NOT USED --
;       ESC F   -- NOT USED --
;       ESC G   -- NOT USED --
;       ESC H   HOME
;       ESC I   REVERSE LINE FEED
;	ESC J	ERASE TO END OF SCREEN
;	ESC K	ERASE TO END OF LINE
;	ESC L	INSERT LINE
;	ESC M	DELETE LINE
;	ESC N	SET TABS              
;	ESC O	CLEAR TABS          
;       ESC P   DELETE CHAR.
;       ESC Q   INSERT CHAR. MODE ON 
;       ESC R   INSERT CHAR. MODE OFF
;	ESC SA  SELECT CHAR. SIZE 
;	ESC TA  SELECT CHAR. SET
;       ESC UA  SELECT ATTRIBUTE
;       ESC VA  SELECT ALT. LEAD-IN
;	ESC WS1...S30  LOAD TONE TABLE AND EXECUTE
;       ESC XTB SET ACTIVE REGION
;       ESC YLC DIRECT CURSOR MOVE
;	ESC Z	RESET PARAMETERS
;	ESC [	SAVE PARAMETERS (SYSTEM USE ONLY)
;	ESC \   CLR. SCN. & RESET PAR.
;	ESC ]	RECALL PARAMETERS (SYSTEM USE ONLY)
;	ESC ^	WORD WRAP OFF
;	ESC _	WORD WRAP ON
;	ESC `	WSFLAG SET (ON)
;	ESC a	WSFLAG RESET (OFF)
;	ESC b	SOUND TONE FROM TONE TABLE
;	ESC c	CURSOR OFF
;	ESC d 	CURSOR ON
;		
	.PAGE
;
;|--------------------------------------|
;|	DISPLAY ENTRY (CHARACTER IN C)  |
;|--------------------------------------|
;
;	|---------------|
;	| MASTER MODULE	|
;	|---------------|
;
DISPLY:	DI
	SSPD	DSPSTK	; SAVE STACK POINTER
	LXI	SP,DSPTEM ; SET STACK POINTER TO DISPLAY STACK
	PUSH	PSW
	MVI	A,0FFH	; SET DSPFLG TO INHIBIT VALET
	STA	DSPFLG
	EI
	PUSH	B	; SAVE REGISTERS
	PUSH	D
	PUSH	H
;
;	ADD OFFSET TO LINE#
;
LFAGN:  CALL    CMPOF1	; CALCULATE LINE OFFSET
;
;	CHECK CYCLE
;
        LDA     DSPCYC 
        ORA     A	; IF DSPCYC <> 0
        JNZ     ESCCHK	;  THEN GO CHECK DSPCYC
;
;	IS CHARACTER ESCAPE ?
;
	RES	7,C	; ELSE MAKE SURE CHAR. IS ASCII
	MOV	A,C
	CPI	ESC	; IF CHAR. = ESC
	JRZ	DSPJ1	;  THEN DSPJ1
	LDA	LEADIN	; ELSE
	CMP	C	;  IF CHAR. <> LEADIN
	JNZ	DSPJ2	; THEN OUTPUT IT TO DISPLAY DRIVER
DSPJ1:  MVI	A,1	;  ELSE SET DSPCYC = 1
	JMP	EXIT3	;  AND EXIT
;
;	IS CHARACTER CONTROL ?
;
DSPJ2:  MOV     A,C	         
	ANI	60H	; IF CHAR. IS A CONTROL CHAR.
	JZ	CTROL	;  THEN GO TO CONTROL CASE
;
;	TRANSLATE CHARACTER TO ALTERNATE
;	 SET, IF NEEDED.
;
	CALL    CHKCHR  ; ELSE XLATE TO ALTERNATE SET IF NEEDED
;
;	OUTPUT CHAR. TO SCREEN AND  
;	 INCREMENT H ACCORDINGLY 
;
CHRRET: CALL    OUTCHR	; OUTPUT CHAR. TO SCREEN
	JRC	DSPRET	; EXIT IF END OF LINE (EOL)
	CPI	LF
	JRZ	LFAGN
;
;	STORE NEW H IN CHRADR+1
;
CUSTH:  MOV     A,H	; ELSE STORE POS. OF NEXT CHAR.
        STA     CHRADR+1
;
;	OUTPUT CURSOR TO (H)+1,(L)
;
CRSRET: CALL    OUTCUR 	; OUTPUT CURSOR
;
;	EXIT POINTS
;
EXIT2:	XRA	A	; CLEAR DSPCYC
EXIT3:	STA	DSPCYC	; STORE DSPCYC
DSPRET: POP	H
	POP	D	; RESTORE REGISTERS
	POP	B
	XRA	A
	DI
	STA	DSPFLG
	POP	PSW
	LSPD	DSPSTK	; RESTORE STACK POINTER
	EI
	RET		; RETURN
;
	.PAGE
;
;	|-----------------------|
;	|  MISC. ROUTINES FOR   |
;	|     MASTER MODULE	|
;	|-----------------------|
;
;
;	OUTPUT CHAR. TO HL
;
OUTCHR: MOV    	E,A
	MVI 	D,1
       	LDA     CURATT
        BIT     4,A
        JRZ     OUTCR1
        INR     D
OUTCR1: MOV     A,L
	MOV	B,H
        ORI     0E0H
        OUT     SDSPY
        MVI     C,DDSPY
        OUTP    E
        ANI     0DFH
        OUT     SDSPY
        ANI     1FH
        MOV     L,A
        LDA     CURATT
        OUTP    A
        MOV     A,H
	CPI	79	; IF EOL
	JRZ	OUTEXT	; THEN OUTEXT
;		
	INR     H	; ELSE
        DCR     D	; IF DOUBLE CHAR.
        JRNZ    OUTCR1 	;  THEN OUTCR1
	XRA	A	; ELSE CLEAR CARRY (NOT EOL)
        RET	  	; AND RETURN
;
OUTEXT: LDA	WRPFLG
	ADI	1	; IF LINE WRAP OFF
	RZ		; THEN RET W/CY SET
;
	XRA	A
	STA	CHRADR+1; COLOUMN = 0
	MVI	A,LF	; DO LINE FEED UPON RETURN
	MOV	C,A
	RET
;
;	OUTPUT CURSOR TO HL
;
OUTCUR: LDA	CURCTL
	ORA	A
	RNZ
	MVI     A,0ACH
      	OUT     SDSPY
        MOV     A,H
	INR	A
        OUT     DDSPY
        MVI     A,0ADH
        OUT     SDSPY
        MOV     A,L
        ANI     1FH
        OUT     DDSPY
        RET
;
;	ADD OFFSET TO LINE#
;
CMPOF1:	LHLD	CHRADR
CMPOFF: LDA     LINOFS
        ADD     L
        CPI     LINES
        JRC     CMPJ1
        ADI     -LINES
CMPJ1:	MOV     L,A
        RET
;
;	TRANSLATE ALT. CHAR. SET
;
CHKCHR:	MOV 	A,C
	CPI	'@'
	RC	
	CPI	80H
	RNC	
	ANI	3FH
	MOV	B,A
	LDA	CURCHR
	ORA	B
	RET
;
	.LIST
	.IFE	LSTFNC,[
	.XLIST
]
	.PAGE
;
;|--------------------------------------|
;|	     CONTROL CASE               |
;|--------------------------------------|
;
CTROL:	MOV	A,C			
;
;|--------------|
;|  BACK SPACE  |
;|--------------|
;
CTROL2:	CPI	BS
	JRNZ	CLCR
	LDA     CURATT
	BIT     4,A
	JRZ     CLJ1
	DCR     H
CLJ1:	DCR     H
	MVI     A,0FFH
	CMP     H
	JM      CUSTH
	LDA	WRPFLG
	ORA	A
	JRNZ	CLJ2
        MOV 	A,H
	SUI     176
	STA	CHRADR+1
	MOV	H,A
	JMP	REVLF
;
CLJ2:	MVI	H,0
	JMP	CUSTH
;
;|-------------------|
;|  CARRIAGE RETURN  |
;|-------------------|
;
CLCR:	CPI	CR
	JRNZ    CLF
	MVI	H,0
	JMP	CUSTH
;
;|-------------|
;|  LINE FEED  |
;|-------------|
;
CLF:	CPI	LF
	JRNZ	CLBL
CLF1:	LDA	BOTACT	;IF NOT AT BOTTOM
	MOV	B,A	
	LDA 	CHRADR
	CMP	B
	JRNZ    CLF4	; THEN MOVE CURSOR
	LDA	MAGACT	; ELSE IF REGION NOT
	CPI	LINES-1	;  FULL SCREEN
	JRNZ	CLF3	;  THEN SOFTWARE SCROLL
;
	MVI	L,0
	CALL	CMPOFF
	CALL	LFCLR1
	LDA	LINOFS	;GRAPHIC SCROLL
	MOV	D,A
	MVI	B,1	;CLEAR ONE LINE
	CALL	GRFCLR+4	
	MVI	A,0ABH	;  ELSE HARDWARE SCROLL
	OUT	SDSPY
	OUT	DDSPY
	LXI	H,LINOFS
	MOV	A,M
	INR	A
	CPI	LINES
	JRNZ	CLF2
	XRA	A
CLF2:	MOV	M,A
	CALL	CMPOF1	
	JMPR	CLF5	;  END HARDWARE SCROLL
;
CLF3:	CALL	SCRLUP	;  BEGIN SOFTWARE SCROLL
	LDA	CHRADR+1
	MOV	H,A
	JMPR	CLF5	;  END SOFTWARE SCROLL
;
CLF4:	INR	A	; BEGIN MOVE CURSOR DOWN
	STA	CHRADR
	MOV	L,A
	CALL	CMPOFF
CLF5:	JMP	CRSRET	; END MOVE CURSOR DOWN
;
;|--------|
;|  BELL  |
;|--------|
;
CLBL:	CPI	BEL
	JRNZ	CLTB
	LDA	CURBEL
	BIT	0,A
	JRNZ	CLEXT
	LXI	H,BELLTN
	CALL	SOUND
	EI
CLEXT:	JMP	EXIT2
;
;|-------|
;|  TAB  |
;|-------|
;
CLTB:	CPI	09H
	JZ	MOVTAB
;
;|------------------|
;|  REV. LINE FEED  |
;|------------------|
;
CLRV:	CPI	0BH
	JZ	REVLF
;
;|----------------|
;|  CURSOR RIGHT  |
;|----------------|
;
CLRT:	CPI	0CH
	JZ	RITCUR
;
;|---------------|
;|  CURSOR HOME  |
;|---------------|
;
CLHM:	CPI	1EH 	
        JZ	HOMCUR
;
;|-----------------------|
;|  CLEAR ACTIVE REGION  |
;|-----------------------|
;
CLCLR:	CPI	1AH
	JRNZ	CTLX	
	LDA	TOPACT
	MOV	L,A
	MVI	H,0
CTRLZ:	SHLD	CHRADR
	CALL	CMPOFF
	CALL	OUTCUR
	CALL	CLTOND
	CALL	GRFCLR
CLZ:	JMP	EXIT2
;
;|-------------------------|
;|  CLEAR KEYBOARD BUFFER  |
;|-------------------------|
;
CTLX:	CPI	CTRLX
	JRNZ	CLZ
	LXI	H,KEYBUF
	XRA	A
	DI
	STA	KEYCNT
	SHLD	KEYPNT
	EI
	JMPR	CLZ
;
	.PAGE
;
;|------------------------------|
;|	ESCAPE CASE 		|
;|------------------------------|
;
ESCCHK:	DCR	A
	JRZ	ESCCK1
;
	DCR	A
	CPI	15H
	JRNC	J19B
	PUSH	H
	LXI	H,CYCTBL
	JMPR	ESCCK2

;	CALCULATE ADDRESS OF VECTOR FROM CHAR.
;	GET VECTOR, PUSH IT AND EXECUTE (RET) 
;	TO JUMP TO IT.
;
ESCCK1:	MOV	A,C	; MOVE NEXT CHAR. TO A
	SUI	'0'	; SUBTRACT OFFSET
	JRC	NFGESC	; IF CARRY, THEN INVALID CHAR.
	CPI	'5'	; IF GREATER THAN 64H (NOW 34H)	
	JRNC	NFGESC	;  THEN INVALID CHAR.
	PUSH	H
	LXI	H,ESCTBL
;
ESCCK2:	RLC		; ELSE MULTIPLY BY 2
	MOV	E,A	; MOVE TO LSB OF OFFSET
	MVI	D,0	; MSB OF OFFSET = 0
	DAD	D	; HL=(HL + DE) POINTS TO VECTOR
	MOV	E,M	; MOVE LSB OF VECTOR TO E
	INX	H
	MOV	D,M	; MOVE MSB OF VECTOR TO D
	POP	H	; RESTORE CURSOR ADDRESS
	PUSH	D	; PUSH VECTOR ON STACK
	RET		; JUMP TO VECTOR ADDRESS
;
NFGESC:	MOV	A,C
	ANI	7FH
	JMP	CHRRET
;
	.PAGE
;
;|------------------|
;|  2 - BLOCK DRAW  |
;|------------------|
;
BLKDRW:	MVI	A,3
;
;|------------------|
;|  0 - PLOT POINT  |
;|------------------|
;
PPOINT:	STA 	GRFCMD
PPNT1:	MVI	A,0EH	; DSPCYC = 0EH
	JMPR	J19C	
;
;|-------------------|
;|  1 - PLOT VECTOR  |
;|-------------------|
;
PVCTOR:	MVI 	A,1
PVCT1:	STA	GRFCMD
	LHLD	GRX
	SHLD	GRX1
	SHLD	GRX12
	XRA	A
	STA	GRY+1
	LHLD	GRY
	SHLD	GRY1
	SHLD	GRY12
	JMPR	PPNT1
;
;|------------------|
;|  4 - BLOCK FILL  |
;|------------------|
;
BLKFIL:	MVI	A,2
	JMPR	PPOINT
;
;|--------------------------|
;|  5 - SET MASKS FOR FILL  |
;|--------------------------|
;
SETMSK:	MVI	A,0DH
	STA	GRFCMD
J19C:	JMP	EXIT3
;
;|-----------------------------|
;|  6 - DISABLE GRAPHIC IMAGE  |
;|-----------------------------|
;
DSBGRF:	XRA	A
	MVI	A,-3	; Z BIT SET ALREADY
L6:	CALL	LLATCH
	EI
J19B:  	JMP	EXIT2
;
;|----------------------------|
;|  7 - ENABLE GRAPHIC IMAGE  |
;|----------------------------|
;
ENBGRF:	MVI	A,2
	ORA	A	; A=2, Z BIT IS CLEAR
	JMPR	L6
;
;|----------------------|
;|  3 - CLEAR GRAPHICS	|
;|----------------------|
;
CLRGRF:	CALL	GRFCLR
;
;|--------------------------|
;|  8 - SET TO PLOT BRIGHT  |
;|--------------------------|
;
PTBRT:	MVI	A,0C7H
PTBR1:	STA	GRFBIT+1
	JMPR	J19B
;
;|------------------------|
;|  9 - SET TO PLOT DARK  |
;|------------------------|
;
PTDRK:	MVI	A,87H
	JMPR	PTBR1
;
;|-----------------|
;|  : - READ DATE  |
;|-----------------|
;
REDDAT: CALL	READAT
	LXI	H,OKIBYT
	LXI	B,7
RDAT2:	EI
	CPI	'?'	
	JRNZ	RDAT1
	LXI	B,1
	MOV	M,A
RDAT1:	CALL	PUSHKY
	JMPR	J19B
;
;|--------------------------------------|	
;|  ; - SET PRINTER BAUD FROM CMOS RAM  |
;|--------------------------------------|
;
CMOSPN:	CALL	ADJPNT
A513:	EI
	JMP	EXIT2
;
;|------------------------------------|
;|  < - SET COMM. BAUD FROM CMOS RAM  |
;|------------------------------------|
;
CMOSCM:	CALL	ADJCOM
	JMPR	A513
;
;|--------------------------|
;|  = - DIRECT CURSOR MOVE  |
;|--------------------------|
;
DRCTMV: MVI     A,2            
	JMPR	J19C
;
;|-----------------|
;|  > - READ TIME  |
;|-----------------|
;
REDTIM:	CALL	READTM
	LXI	H,SCNDS
	LXI	B,6
	JMPR	RDAT2
;
;|---------------------|
;|  ? - READ CMOS RAM  |
;|---------------------|
;
REDRAM:	MVI	A,12H
	JMPR	J19C
;
;|----------------------|
;|  @ - WRITE CMOS RAM  |
;|----------------------|
;
WRTRAM:	MVI	A,13H
	JMPR	J19C
;
;|-----------------|
;|  A - UP CURSOR  |
;|-----------------|
;
UPCUR:  LDA	CHRADR
	MOV	B,A
	LDA     TOPACT
	CMP	B	;IF TOP OF ACT. REG.
	JRZ 	A45A	; THEN RETURN
UPCUR1: DCR	L	; ELSE MOVE CURSOR UP
	JP	UPCUR2
	MVI	L,LINES-1
UPCUR2: DCR	B
        MOV     A,B
        STA     CHRADR
        JMPR	A42B
;
;|-------------------|
;|  B - DOWN CURSOR  |
;|-------------------|
;
DWNCUR: LDA	CHRADR
	MOV     B,A    
	LDA     BOTACT
	CMP	B	;IF BOTTOM OF ACT. REG.
	JZ 	EXIT2	; THEN RETURN
DNCUR1: INR 	L	; ELSE MOVE CURSOR DOWN
	MVI	A,LINES
	CMP	L
	JNZ	DNCUR2
	MVI	L,0
DNCUR2: INR	B
	MOV	A,B
	STA 	CHRADR
A42B:	JMP	CRSRET
;
;|--------------------|
;|  C - RIGHT CURSOR  |
;|--------------------|
;
RITCUR: LDA     CURATT
	BIT 	4,A	;DOUBLE WIDTH MODE ?
	JRZ	A431  
	INR	H
A431:   INR	H
	MVI 	A,79
	CMP	H	;IF NOT AT RIGHT BOUNDARY
	JP	CUSTH	; THEN MOVE CURSOR
;
	LDA	WRPFLG
	ORA	A	; IF WRAP OFF
	JRNZ	A45A	;  THEN EXIT2
;
	CALL	OUTEXT  ; ELSE CLEAR COLUMN #
	XRA	A
	STA	DSPCYC
	JMP	LFAGN	; AND DO A LINE FEED
;
;|-------------------|
;|  D - LEFT CURSOR  |
;|-------------------|
;
;	IS CTROL2+4 IN ESCTBL
;
;|----------------|
;|  E - NOT USED  |
;|----------------|
;
;	IS EXIT2 IN TABLE
;
;|----------------|
;|  F - NOT USED  |
;|----------------|
;
;	IS EXIT2 IN TABLE
;
;|----------------|
;|  G - NOT USED  |
;|----------------|
;
;	IS EXIT2 IN TABLE
;
;|-------------------|
;|  H - HOME CURSOR  |
;|-------------------|
;
HOMCUR: LDA	TOPACT
	MOV 	L,A
	MVI	H,0
	SHLD    CHRADR
	CALL	CMPOFF
	JMPR	A49A
;
;|----------------------|
;|  I - REV. LINE FEED	|
;|----------------------|
;
REVLF:  LDA     CHRADR
	MOV	B,A
	LDA	TOPACT
	CMP	B	;IF NOT AT TOP OF A.R.
	JNZ	UPCUR1	; THEN MOVE CURSOR
        CALL    SCRLDN	; ELSE SCROLL A.R
	CALL    CMPOF1
A49A:	JMP	CRSRET
;
;|-------------------------------------|
;|  J - CLEAR TO END OF ACTIVE REGION  |
;|-------------------------------------|
;
CLREND:	CALL    CLTOND                        
A45A:	JMP	EXIT2
;
;|----------------------------|
;|  K - CLEAR TO END OF LINE  |
;|----------------------------|
;
CLRELN:	CALL	LFCLR2
	JMPR	A49A
;
;|-------------------|
;|  L - INSERT LINE  |
;|-------------------|
;
INSLIN:	LDA	CHRADR
	MOV	B,A
	LDA     BOTACT
	SUB 	B	;IF AT BOTTOM
	JRZ	A4C1	; THEN CLEAR LINE & EXIT
	CALL    SCRDN1	; ELSE INSERT BLANK LINE
	JMPR	EXXIT2
A4C1:	CALL	LFCLR1	
	JMPR	EXXIT2
;
;|-------------------|
;|  M - DELETE LINE  |
;|-------------------|
;
DELLIN:	LDA	CHRADR  
	MOV	B,A
	LDA     BOTACT
	SUB	B	;IF AT TOP
	JRZ	A4C1	; THEN CLEAR LINE AND EXIT
	MOV	L,B	; ELSE SCROLL REGION
	MOV	B,A	;  UP & CLEAR BOTTOM LINE
	CALL    SCRUP1
	JMPR	EXXIT2
;
;|----------------|
;|  N - SET TABS  |
;|----------------|
;
SETTAB:	MVI	A,0AH
	JMPR	A51A
;
;|------------------|
;|  O - CLEAR TABS  |
;|------------------|
;
CLRTAB:	CALL	CLRTBS
EXXIT2:	JMP	EXIT2
;
;|--------------------|
;|  P - DELETE CHAR.  |
;|--------------------|
;
DELLCR:	CALL	DELCHR
	JMPR	EXXIT2
;
;|----------------------------|
;|  Q - INSERT CHAR. MODE ON  |
;|----------------------------|
;
INSCON:	MVI	A,0CH
A51A:	JMP	EXIT3 
;
;|-----------------------------|
;|  R - INSERT CHAR. MODE OFF  |
;|-----------------------------|
;
;	IS EXIT2 IN ESCTBL
;
;|-------------------------|
;|  S - SELECT CHAR. SIZE  |
;|-------------------------|
;
CHRSIZ:	MVI	A,9
	JMPR	A51A
;
;|------------------------|
;|  T - SELECT CHAR. SET  |
;|------------------------|
;
CHRSET:	MVI	A,8
	JMPR	A51A
;
;|-------------------------|
;|  U - SELECT ATTRIBUTES  |
;|-------------------------|
;
SELATR:	MVI	A,7
	JMPR	A51A
;
;|---------------------------|
;|  V - SELECT ALT. LEAD-IN  |
;|---------------------------|
;
SELDIN:	MVI	A,0BH
        JMPR	A51A
;
;|---------------------------------------------|
;|  W - LOAD SPECIFIED REGISTER OF TONE TABLE  |
;|---------------------------------------------|
;
DSPSND:	MVI	A,16H
	JMPR	A51A
;
;|-------------------------|
;|  X - SET ACTIVE REGION  |
;|-------------------------|
;
SETACR:	MVI	A,5
	JMPR	A51A
;
;|--------------------------|
;|  Y - DIRECT CURSOR MOVE  |
;|--------------------------|
;
;	IS DRCTMV IN ESCTBL
;
;|------------------------|
;|  Z - RESET PARAMETERS  |
;|------------------------|
;
RESPAR:	CALL	RSTPAR
	JMPR	EXXIT2
;
;|-----------------------|
;|  [ - SAVE PARAMETERS	 |
;|-----------------------|
;
SAVVPR:	CALL	SAVPAR
	JMPR	EXXIT2
;
;|---------------------------------------|
;|  \ - CLEAR SCREEN & RESET PARAMETERS	 |
;|---------------------------------------|
;
;	IS CLSCRN IN ESCTBL
;
;|-------------------------|
;|  ] - RECALL PARAMETERS  |
;|-------------------------|
;
RCLPAR:	CALL	RSTORP	;RESTORE PARAMETERS
	CALL	CMPOF1	; MOVE CURSOR TO
	JMP	CRSRET	; PREVIOUS POSITION
;
;|----------------|
;|  ^ - WRAP OFF  |
;|----------------|
;
WRPOFF:	MVI	A,0FFH
	JMPR	WRPGEN	
;
;|---------------|
;|  _ - WRAP ON	 |
;|---------------|
;
WRPON:	XRA	A
WRPGEN:	STA	WRPFLG
A5F0:	JMP	EXIT2
;
;|-----------------------|
;|  ` - WSFLAG SET (ON)  |
;|-----------------------|
;

SETWS:	MVI	A,0FFH
	JMPR	A512
;
;|--------------------------|
;|  a - WSFLAG RESET (OFF)  |
;|--------------------------|
;
CLRWS:	XRA	A
A512:	STA	WSFLAG
	JMPR	A5F0
;
;|-----------------------------|
;|  b - MAKE SOUND FROM TABLE  |
;|-----------------------------|
;
DOSND:	LXI	H,SNDTBL
	CALL	SOUND
	EI
	JMPR	A5F0
;
;|-----------------|
;| c - CURSOR OFF  |
;|-----------------|
;
OFFCUR:	MVI	H,81
	CALL	OUTCUR
	MVI	A,0FFH
	STA	CURCTL
	JMPR	A5F0
;
;|-----------------|
;|  d - CURSOR ON  |
;|-----------------|
;
ONCUR:	XRA	A
	STA	CURCTL
	JMP	CRSRET
;
	.LIST
	.IFE	LSTMCH,[
	.XLIST
]
	.PAGE
;
;|--------------------------------------|	
;|					|
;|   MULTI - CHAR. SEQUENCE HANDLERS	|	
;|					|
;|--------------------------------------|
;
;|--------------------------------------------|
;|  02H - DIRECT CURSOR POSITION LINE NUMBER  |
;|--------------------------------------------|
;
LINCHK:	MOV	A,C
	SUI	SPC
	MOV	B,A
	LDA	BOTACT
	CMP	B 
	JM      LNCKJ3	
	LDA	TOPACT
	CMP	B
	JRZ	LNCKJ1	
	JP 	LNCKJ3
LNCKJ1:	MOV	A,B
     	STA     CHRADR
	MOV	L,A
	CALL	CMPOFF
	MOV	A,L
LNCKJ2: STA	TEMLIN
	MVI	A,3
	JMP	EXIT3
LNCKJ3:	MVI	A,0FFH
	JMPR	LNCKJ2
;
;|----------------------------------------------|
;|  03H - DIRECT CURSOR POSITION COLUMN NUMBER  |
;|----------------------------------------------|
;
COLCHK:	LDA	TEMLIN
	CPI	0FFH
	JZ	EXIT2
	MOV	L,A 
	MOV	A,C
	SUI	SPC
	MOV	H,A
	JMP	CUSTH+1
;
;|------------------|
;|  04H - NOT USED  |
;|------------------|
;
;	IS EXIT2 IN TABLE
;
;|------------------------------|
;|  05H - TOP OF ACTIVE REGION  |
;|------------------------------|
;
TACTCK:	MOV	A,C
	SUI	SPC
	STA	TOPACT
	MVI	A,6
	JMP	EXIT3
;
;|---------------------------------|
;|  06H - BOTTOM OF ACTIVE REGION  |
;|---------------------------------|
;
BACTCK:	MOV	A,C
	SUI	SPC
	LXI	H,TOPACT
	MOV     B,M	; GET TOPACT
  	INX     H
	MOV	M,A	; STORE BOTACT
	SUB	B	; CALCULATE MAGACT
	INX     H
	MOV	M,A	; STORE MAGACT
	JMP	HOMCUR
;
;|--------------------------|
;|  07H - SCREEN ATTRIBUTE  |
;|--------------------------|
;
ATTCHK:	MOV	A,C
	ADI	20H
	ANI	38HŠ	RLC	
	MOV 	D,A
	MOV	A,C
	ANI	7H
	ORA	D
	RLC
	MOV	D,A
	LXI	H,CURATT
	MOV	A,M
	ANI	11H
	ORA	D
	MOV	M,A
	JMPR	EXXT2
;
;|-----------------------------|
;|  08H - ALTERNATE CHAR. SET  |
;|-----------------------------|
;
ALTCHK:	MOV	A,C
	ANI	3
	MOV	C,A
	MVI	B,0
	LXI	H,CHRTBL
	DAD	B
 	MOV	A,M
	STA	CURCHR
EXXT2:	JMP	EXIT2
;
;|---------------------------|
;|  09H - SELECT CHAR. SIZE  |
;|---------------------------|
;
SIZCHK: LDA	CURATT
	ANI	0EFH
	MOV	B,A
	MOV	A,C
	SUI	'0'
	JRZ	SZCKJ1
	MVI	A,10H
SZCKJ1:	ORA	B
	STA	CURATT
	JMPR	EXXT2
;
;|------------------|
;|  0AH - SET TABS  |
;|------------------|
;
TABCHK:	MOV	A,C
	CPI	ESC
	JRZ	EXXT2
	SUI	20H
	JM	EXIT2
	CPI	50H
	JRNZ	TBJ0
	CALL	CLRTBS
	JMP	DSPRET
TBJ0:	JP	EXIT2
	MOV	B,A
	LDA	LASTAB
	CMP	B
	MOV	A,B
	JRNC	TBOK
	STA	LASTAB
TBOK:	ANI	7H
	INR	A
	MOV	B,A
	MVI	A,80H
	JMPR	TBJ1
TBJ2:	SRLR	A
TBJ1:	DJNZ	TBJ2
       	MOV	B,A
	MOV	A,C
	CALL	GTEFAD
	MOV	A,M
	ORA	B
	MOV	M,A
	JMPR	SCHK1
;
;|---------------------------|
;|  0BH - ALTERNATE LEAD IN  |
;|---------------------------|
;
LEDCHK:	MOV	A,C
	STA	LEADIN
	JMPR	EXXT2
;
;|------------------------|
;|  0CH - INSERT MODE ON  |
;|------------------------|
;
INSCHK:	LDA	LEADIN
	CMP	C
	JRNZ	INCKJ2
INCKJ1:	MVI	A,1
	JMP	EXIT3	
INCKJ2:	MVI	A,ESC
	CMP	C
	JRZ 	INCKJ1
        PUSH	B
	PUSH	H
	CALL	INSCHR
	POP	H
	POP	B
	CALL    CHKCHR
        CALL 	OUTCHR
        JRC	SCHK1
	MOV	A,H
	STA	CHRADR+1
	CALL	OUTCUR
SCHK1:	JMP	DSPRET
;
	.PAGE         
;
;|------------------|
;|  0DH - GET MASK  |
;|------------------|
;
GRFCHK:	LDA	GRFCMD
	CPI	0DH
	MOV	A,C
	JRNZ	GRCK1	;MASKS FOR FILL
	STA	MASK
	XRA	A
	STA	GRFCMD
	JMPR	SCHK1
GRCK1:	STA	XMASK
	JMPR	GREXT2
;
;|-------------------|
;|  0EH - GET X MSB  |
;|-------------------|
;
GRFCK1:	XRA	A	
	BIT	2,C
	JRZ	GRCK3
	INR	A
GRCK3:	STA	GRX+1
	MOV	A,C
	RRC
	RRC
	ANI	0C0H
	STA	GRX
	MVI	A,0FH
	JMPR	GREXT3
;
;|-------------------|
;|  0FH - GET X LSB  |
;|-------------------|
;
GRFCK2:	MOV	A,C
	ANI	3FH	;REMOVE POSSIBLE OFFSET
	LXI	H,GRX
	ORA	M
	MOV	M,A
	MVI	A,10H
GREXT3:	JMP	EXIT3
;
;|-------------------|
;|  10H - GET Y MSB  |
;|-------------------|
;		
GRFCK3:	MOV	A,C
	RRC
	RRC
	ANI	0C0H
	STA	GRY
	MVI	A,11H
	JMPR	GREXT3
;		
;|-------------------|
;|  11H - GET Y LSB  |
;|-------------------|
;
GRFCK4:	MOV	A,C
	ANI	3FH	;REMOVE POSSIBLE OFFSET
	LXI	H,GRY
	ORA	M
	MOV	M,A
	LDA	GRFCMD
	ORA	A
	JRNZ	GRCK6
	CALL	PPLOT	
GREXT2:	JMP	EXIT2	
GRCK6:	DCR	A
	JRNZ	GRCK7
	CALL	VPLOT
	JMPR	GREXT2
GRCK7:	DCR	A
	JRNZ	GRDOIT
	MVI	A,4	;IF BLOCK FILL OR DRAW
GRCK8:	JMP	PVCT1	;GET SECOND POINT
GRDOIT:	DCR	A	
	JRNZ	GROK
	MVI	A,5
	JMPR	GRCK8
GROK:	LXI	H,EXIT2
	PUSH	H	;SET RETURN ADDRESS
	DCR	A
	JZ	FILL
	JMP	DRWBLK
;
;
	.PAGE
;
;|-----------------------|
;|  12H - READ CMOS RAM  |
;|-----------------------|
;
GRFCK5:	MOV	B,C
	CALL	RD5101
	EI
	ANI	0FH
	ORI	'0'
	LXI 	H,HRS10
	MOV	M,A
	LXI	B,1
	JMP	RDAT1
;
;|------------------------------------|
;|  13H - GET ADDRESS FOR CMOS WRITE  |
;|------------------------------------|
;
GRFCK6:	MOV 	A,C
	STA	MINS
	MVI	A,14H
EXXX3:	JMP	EXIT3
;
;|------------------------|
;|  14H - WRITE CMOS RAM  |
;|------------------------|
;
GRFCK7:	LDA	MINS
	MOV	B,A
	MOV	A,C
	CALL	WR5101
	EI
EXXX2:	JMP	EXIT2

;
;|----------------------------------------------|
;|  15H - FILL SPECIFIED ADDRESS IN TONE TABLE  |
;|----------------------------------------------|
;
GETSND:	LXI	H,SNDCNT
	BIT	0,M
	XCHG
	LHLD	SNDADR
	JRNZ	GTSND2
GTSND1:	MOV	M,C
	JMPR	GTSND3
;
GTSND2:	MOV	A,C
	RLD
GTSND3:	XCHG
	DCR	M
	JRZ	EXXX2
DS15:	MVI	A,15H
	JMPR	EXXX3	
;
;|------------------------------------|
;|  16H - GET ADDRESS IN TONE TABLE   |	
;|------------------------------------|
;
SETSND:	MVI	A,2EH
	SUB	C	; NUMBER NOW = OFFSET IN TABLE
	JM	EXXX2	; EXIT IF NEGATIVE
	CPI	15
	JRNC	EXXX2	; EXIT IF > 14
	MVI	B,0
	MOV	C,A
	LXI	H,SNDTBL
	DAD	B	; ADD TO BASE TO POINT TO REG.
GOTSND:	SHLD	SNDADR
	MVI	A,2
	STA	SNDCNT
	JMPR	DS15
;
	.LIST
	.IFE	LSTDMC,[
	.XLIST
]
	.PAGE
;
;|--------------------------------------|
;|	DISPLAY SUBROUTINES		|
;|--------------------------------------|
;
READAT:	LXI	H,NATDAT; GET POINTERS TO TABLES
	LXI	D,OKIDAT
	CALL	GETCLK	; READ DATE
	JRNZ	NOCLK	;  NOCLK IF CAN'T READ OR NOT SET
	LXI	H,OKIBYT
	MOV	A,C
	ORA	A	; IF NATIONAL CHIP
	JRZ	..J0	;  THEN ..J0
	INR	M	; ELSE INCREMENT DAY OF WEEK
..J0:	INX	H	; INCREMENT POINTER TO
	INX	H	; AND OFF PROPER VALUE
	JMPR	ANDIT
;
READTM:	LXI	H,NATTIM; GET POINTERS TO TABLES
	LXI	D,OKITIM
	CALL	GETCLK	; READ TIME
	JRNZ	NOCLK	;  NOCLK IF CAN'T READ OR NOT SET
	LXI	H,HRS10
;
ANDIT:	MOV	A,M
	ANI	0F3H
	MOV	M,A
	RET
;
NOCLK:	XRA	A
	STA	CLKFLG
	MVI	A,'?'
	RET
;
GETCLK:	PUSH	D
	MVI	B,3	; READ NYBBLE 3 OF CMOS
	CALL	RD5101	
	CPI	0EH	; IF <> 0EH
	JRNZ	..J0	;  THEN ..J0
	MVI	B,4	; ELSE READ NYBBLE 4 OF CMOS
	CALL	RD5101
	CPI	5	; IF <> 5
..J0:	POP	D  
	RNZ		; RETURN, CLOCK NOT SET
	STA	CLKFLG	; SET CLKFLAG
;
	LDA	OKIFLG	; USE PROPER TABLE
	ORA	A
	MOV	C,A	; SAVE OKIFLG
	JRZ	..J1
	XCHG
;
..J1:	MVI	B,10
..L0:	PUSH	B
	CALL	REDCLK
	POP	B
	RZ
	DJNZ	..L0
	RET
;
REDCLK:	LXI	D,HRS10
	DCX	H
..L0:	INX	H
	MOV	A,M
	ORA	A	; IF A = 0
	RZ		;  THEN WE'RE DONE
	INX	H	; ELSE GET ADDRESS
	MOV	B,M	; 
	PUSH	D	; SAVE D
	DCR	A	; IF A > 1
	JRNZ	..J0	;  THEN READ CMOS RAM
;
	CALL	R58174	; ELSE READ FROM CLOCK
	JMPR	..J1
;
..J0:	CALL	RD5101	; READ FROM CMOS RAM
..J1:	POP	D
	CPI	0FH	; IF <> 0FH
	JRNZ	..J2	;  THEN O.K READ
	ORA	A	; ELSE ERROR
	RET
;
..J2:	ORI	'0'
	STAX	D
	DCX	D
	JMPR	..L0
;
	.PAGE
;
;	SCROLL ACTIVE REGION UP
;
SCRLUP:	MOV	B,A
	ORA	A
	JRZ	LFCLR0	
	LDA	TOPACT
	MOV	L,A
SCRUP1: CALL 	CMPOFF
	MOV	E,L
	MOV	A,L
	INR	A
	CPI	LINES
	JRNZ	SCRUP2
	XRA	A
SCRUP2:	MOV	D,A
SCRUP3:	PUSH	D
	PUSH	B
	CALL	MOVLIN
	POP	B
	POP	D
	MOV	E,D
	INR	D
	MVI	A,LINES
	CMP	D
	JRNZ	SCRUP4
	MVI	D,0
SCRUP4:	DJNZ	SCRUP3
	MOV	L,E
	JMPR	LFCLR1
;
;	SCROLL ACTIVE REGION DOWN
;
SCRLDN:	LDA	MAGACT
	ORA	A
	JRZ	LFCLR0	
SCRDN1:	MOV	B,A
	LDA	BOTACT
	MOV	L,A
	CALL	CMPOFF
	MOV	E,L
	MOV	A,L
	ORA	A
	JRNZ	SCRDN2
	MVI	A,LINES
SCRDN2:	DCR	A
	MOV	D,A
SCRDN3:	PUSH	D
	PUSH	B
	CALL	MOVLIN
	POP	B
	POP	D
	MOV	A,D
	MOV	E,D
	ORA	A
	JRNZ	SCRDN4
	MVI	A,LINES
SCRDN4:	DCR	A
	MOV	D,A
	DJNZ	SCRDN3
	MOV	L,E
;
;|----------------|
;|  CLEAR LINE L  |
;|----------------|
;
LFCLR0:	CALL	CMPOF1		
LFCLR1:	MVI	H,0
	MOV	A,L
	ORI	0C0H
	MOV	L,A
	LXI	D,SPC
	LXI	B,79*256+SDSPY
	PUSH	B
	OUTP	L
	MVI	C,DDSPY
LFCL1:	OUTP	D
	DJNZ	LFCL1
	OUTP	D
	POP	B
	SET	5,L
	OUTP	L
	MVI	C,DDSPY
LFCL2:	OUTP	E
	DJNZ	LFCL2
	OUTP	E
	RET
;
;	CLEAR LINE L FROM POSITION H TO END OF LINE
;
LFCLR2:	MOV	A,L
	ORI	0C0H
	MOV	L,A
	LXI	D,SPC
	MOV	B,H
	MVI	A,80
LFCL3:	MVI	C,SDSPY
	CMP	B
	RZ
	OUTP	L	;CLEAR ATTRIBUTE
	MVI	C,DDSPY
	OUTP	D
	MVI	C,SDSPY
	SET	5,L
	OUTP	L	;CLEAR CHARACTER
	MVI	C,DDSPY
	OUTP	E
	RES	5,L
	INR	BŠ	JMPR	LFCL3
;
;	MOVE LINE D TO LINE E
;
MOVLIN:	MOV	A,D	;SET UP
	ORI	0C0H
	MOV	D,A
	MOV	A,E
	ORI	0C0H
	MOV	E,A
	MVI	B,79
	PUSH	H
	PUSH	B
	CALL	MOVLN1	;MOVE ATTRIBUTES
	POP	B
	POP	H
	SET	5,D	;MOVE CHARACTERS
	SET	5,E
MOVLN1:	MVI	C,SDSPY
	OUTP	D
	LXI	H,DSPBUF
	PUSH	H
	PUSH	B
	MVI	C,DDSPY
	INIR
	INI
	POP	B
	INR	B
	POP	H
	OUTP	E
	MVI	C,DDSPY
	OUTIR
	RET
;
;|----------------------------|
;|  MOVE CURSOR TO NEXT TAB   |
;|----------------------------|
MOVTAB:	LDA	LASTAB
	CMP	H
	JM	EXIT2
	JRZ	TBDON
	PUSH	H
	MOV	B,H
	MOV	A,H
	ANI	78H
	CALL	GTEFAD+2
	MOV	A,B
	ANI	7H
	MOV	B,A
	CPI	7
	JRZ	MOVTB3
	ADI	0F8H
	CMA
	MOV	D,A
	MOV	A,M
        INR	B
MOVTB1:	RLCR	A
	DJNZ	MOVTB1
        MOV	B,D
MOVTB2:	BIT 	7,A
	JRNZ	TBIT
	RLCR	A
	DJNZ	MOVTB2
MOVTB3:	MVI	A,9
	CMP	E
	JRZ	TBOVR
	INR	E
	INX	H
	MOV	A,M
	MVI	B,8
	JMPR	MOVTB2
TBIT:	MOV	A,B
	ADI	0F7H
	CMA
	MOV	B,A
	MOV	A,E
	ANA	A
	RAL
	RAL
	RAL
	ORA	B
	POP	H
	MOV	H,A
	JMP	CUSTH
TBOVR:	POP	H
TBDON: JMP	EXIT2
;
GTEFAD: SUI	SPC
	SRLR	A
	SRLR	A
	SRLR	A
	MOV	E,A
	MVI	D,0
	LXI	H,TABS
	DAD	D
	RET
;
;	RESET PARAMETERS
;
RSTPAR:	LXI	H,CURCHR
	MVI	M,40H
	XRA	A
	MVI	B,4
..L0:	INX	H
	MOV	M,A
	DJNZ	..L0
	MVI	A,LINES-1
	STA	BOTACT
	STA	MAGACT
	MVI	A,ESC
	STA	LEADIN
;
;	RESET OR CLEAR TABS
;
RSTABS:	MVI	A,4FH
	STA	LASTAB
	MVI	A,1
	JMPR	DOTABS
;
CLRTBS:	XRA	A
	STA	LASTAB
;
DOTABS:	LXI	H,TABS
	MVI	B,10
DOTBJ1:	MOV	M,A
	INX	H
	DJNZ	DOTBJ1
	RET
;
;	SAVE SCREEN PARAMETERS
;
SAVPAR:	LXI	H,CURCHR
	LXI	D,TEMPAR
	JMPR	PARGEN
;
;	RESTORE SCREEN PARAMETERS
;
RSTORP:	LXI	H,TEMPAR
	LXI 	D,CURCHR
PARGEN:	LXÉ	B,21
	LDIR
	RET
;
;	CLEAR SCREEN & RESET PARAMETERS
;
CLSCRN:	CALL	RSTPAR
	XRA	A
	STA	LINOFS
	MVI	A,0A6H
	OUT	SDSPY
	MVI	A,LINES-1
	OUT	DDSPY
	LXI	H,0
	JMP 	CTRLZ
;
;	CLEAR TO END OF ACTIVE REGION
;
CLTOND: CALL	LFCLR2
	LDA	CHRADR
	MOV	B,A
	LDA	BOTACT
	SUB	B
	RZ	
	MOV	B,A
CLND1:	MOV	A,L
	ANI	1FH
	INR	A
	CPI	LINES
	JRNZ	CLND2
	XRA	A
CLND2: 	MOV	L,A
	PUSH	B
	CALL	LFCLR1
	POP	B
	DJNZ	CLND1
	RET
;
;	INSERT OR DELETE CHAR.
;
INSCHR:	PUSH	H	 	;SET UP FOR INSERT
       	LXI     H,DSPBUF+1
	SHLD	MOVBEG
	MVI	A,23H	        ;INX	H
	STA	MODX
	JMPR	INSDEL
;
DELCHR:	PUSH	H		;SET UP FOR DELETE
       	LXI	H,DSPBFL+1
	SHLD	MOVBEG
 	MVI	A,2BH	        ;DCX	H
	STA	MODX
;
INSDEL:	XRA	A
	CALL	FILBFF		; INSERT OR DELETE
	POP	H
	PUSH	H
	MOV	A,L
	ORI	0C0H
	MOV	L,A
	PUSH	H
	CALL	INPLIN
	POP	H
	MOV	A,L
	MOV	E,H
	OUT	SDSPY
	LHLD	MOVBEG
	LDA	CURATT
	BIT	4,A
	JRZ	INDEL1
MODX:	DCX	H	        ;MODIFIABLE CODE
INDEL1: PUSH	H
	CALL	OUTLIN
	MVI	A,20H
	CALL	FILBFF
	POP	D
	POP	H
	PUSH	D
	MOV	A,L
	ORI	0E0H
	MOV	L,A
	PUSH	H
	CALL	INPLIN
	POP	H
	MOV	A,L
	MOV	E,H
	POP	H
	JMP	OUTLIN
;
FILBFF: LXI	H,DSPBFL	;FILL BUFFER WITH (A)
	MVI	B,84
FLBF1:	MOV	M,A
	INX	H
	DJNZ	FLBF1
	RET
;
INPLIN:	OUT	SDSPY		;INPUT PART OF LINE 
	MOV	A,H		;TO PART OF BUFFER
	DCR	A
	MVI	B,79
	MVI	C,DDSPY
	LXI	H,DSPBUF
INPLN1:	INI
	CMP	B
	JRNZ	INPLN1
	RET
;
OUTLIN:	MVI	B,80		;OUTPUT PART OF BUFFER
	MOV	A,E		;TO PART OF LINE
	MVI	C,DDSPY
OUTLN1:	OUTI
	CMP	B
	JRNZ	OUTLN1
	RET
;
	.LIST
	.IFE	LSTGRF,[
	.XLIST
]
	.PAGE
;
;	FILL COMMAND
;
GRFSTR	=	.
FILL:	LDA	GRY	;SET UP GRY,GRY1
	MOV	B,A
	LDA	GRY1	;AND GRX,GRX1 IN RIGHT ORDER
	SUB	B
	CC	SWPY
	XRA	A	;ZERO CARRY
	LHLD	GRX
	LDED	GRX1
	DSBC	D
	CC	SWPX
	LDA	XMASK	;CHECK MASKS
	MOV	B,A	;FOR BOTH = 0
	LXI	H,MASK
	MOV	A,M
	ORA	B
	MOV	A,B
	STA	CLFLG
	JRNZ	FILL1
	MVI	A,0A2H	;ANA	D
	STA	ORAD	;PREPARE TO CLEAR BLOCK	
	MVI	A,0FFH	;MAKE MASKS 'FF' FOR NOW AND COMPLEMENT 
	MOV	M,A	;AFTER FIXING EDGES
	STA	XMASK
FILL1:	INX	H
	MOV	M,A	;MASK2	
	INX	H
	INX	H
	MOV	M,A	;CURMSK
	XRA	A
	STA	CYC	;START CYCLE AT ZERO
	CALL	LINDSP	;CACULATE LINE
	LHLD	GRX	
	CALL	PIX	;PIX FINDS OUT WHICH BIT THE
	STA	PIXBT2	;PIXEL IS IN
	CALL	XDDR
	STA	STRX	;START FOR X
	LDA	GRY1	;DO THE SAME FOR
	CALL	LINDSP+3
	LHLD	GRX1	;OTHER POINT
	CALL	PIX
	MVI	C,0FH	;FIX TOP
	PUSH	H
	CALL	FIXNIB	;FIX MASK FOR TOP EDGE
	POP	H
	CALL	XDDR
	STA	STRX1	;START FOR X2
DOMSK:	LDA	GRY	;START LINE HERE
	MOV	B,A
	LDA	GRY1
	ORA	A	;IF GRY1 IS AT LAST LINE
	JRZ	LSTLIN	;THEN DO IT AND LEAVE
	SUB	B
	JRC	EXIT1	;DONE IF PAST GRY
	CZ	FIXBOT
	CALL	LINE	;DO A LINE
DOCOL:	CALL	COLUMN	;LOOP UNTIL ALL COLUMNS ARE DONE
	CALL	NXTBYT	;FIND NEXT BYTE
	JRNZ	DOCOL	
	LDA	CYC	;GET NEW MASK
	ORA	A
	JRZ	MSKDON	;CYCLE TELLS US WHICH ONE
	XRA	A
	STA	CYC
XMSK:	MVI	A,0FFH	;MODIFIED MASK
MSKOK:	STA	MASK2
	STA	CURMSK
	JMPR	DOMSK
MSKDON:	INR	A	
	STA	CYC
	LDA	MASK
	JMPR	MSKOK
;
XMASK	=	XMSK+1
;
EXIT1:	LDA	PIXBIT	;WE HAVE TO MAKE SURE TO GET
	ANI	4
	JRNZ	EXIT	;LAST LINE IF NEEDED.
	LDA	PIXBT2
	ANI	4
	JRZ	EXIT
;
LSTLIN:	CALL	LINE	;IF WE ARE AT THE LAST LINE 
	CALL	FIXBOT
LSTLN1:	CALL	COLUMN	;WE DO IT AND EXIT
	CALL	NXTBYT
	JRNZ	LSTLN1	;FALL INTO EXIT
;
;
EXIT:	LDA	CLFLG	;IF WE WERE CLEARING
	ORA	A
	RNZ		;A BLOCK WE NEED
	STA	MASK
	STA	XMASK	;TO RESTORE EVERYTHING
	MVI	A,0B2H	;ORA	D
	STA	ORAD
	STA	CLFLG
	RET
;
DNLIN:	MOV	M,A
	POP	PSW
	JMPR	LSTLIN
;
;
COLUMN:	LDA	CLFLG	;IF WE ARE
	ORA	A	;CLEARING A BLOCK
	LDA	MASK2
	JRNZ	CLMN1
	CMA		;THEN COMPLEMENT THE MASK AND
CLMN1:	MOV	D,A
	MVI	C,DDSPY	;AND IT INSTEAD OF ORING IT
	INP	A
ORAD:	ORA	D	;MODIFIED TO ANA D FOR CLEAR
	OUTP	A
	RET
;
LINE:	LDA	STRX	;IF THE BLOCK IS LESS THAN
	MOV	C,A	
	LDA	STRX1	;4 PIXELS WIDE  
	SUB	C
	CPI	4	;WE NEED TO FIX THE RIGHT EDGE
	CC	FIXRGT
	LDA	GRY1	;FIND SDSPY FOR NEW LINE
	CALL	LINDSP+3
	OUT	SDSPY
FIXLFT:	LDA	PIXBIT	;FIX THE LEFT EDGE
	ANI	03H
	SUI	3	;TAKE PIXELS OFF THE EDGES
	JRZ	FXLFT2
	NEG		;PIXBIT TELLS US HOW MANY 
	MOV	B,A
	LXI	H,MASK2	;PIXELS TO TAKE OFF
	MOV	A,M
	MVI	D,77H		
FXLFT1:	ANA	D
	RRCR	D
	DJNZ	FXLFT1
	MOV	M,A
FXLFT2:	LDA	STRX1	;WE NEED STRX1 IN B
	MOV	B,A	;FOR COL
	RET
;
;
PIX:	CALL	SETBIT	;SET BIT TELLS US WHICH 
	RRCR	A	;BIT IN A NIBBLE
	RRCR	A
	RRCR	A	;MOVE FROM BITS 3,4,5
	ANI	07H	;TO 0,1,2
	STA	PIXBIT
	RET
;
;
NXTBYT:	LDA	STRX1	;IF WE JUST FINISHED WITH 
	CMP	B	;THE FIRST BYTE
	JRNZ	NXBYT1
	LXI	H,CURMSK	;WE MUST UNFIX
	MOV	C,M		;THE LEFT EDGE
	DCX	H	;MMASK
	MOV	A,M		;MMASK TELLS US IF THE TOP
	ANA	C		;WAS FIXED OR NOT
	DCX	H	;MASK2	
	MOV	M,A		;MASK2 IS THE FIXED MASK
	MVI	A,0FFH		;MAKE MMASK 'FF'
	INX	H
	MOV	M,A	;MMASK
NXBYT1:	INR	B	;POINT TO NEXT BYTE
	LDA	STRX	
	CMP	B	;COMPARE TO LAST BYTE
	JRZ	FIXRGT	;IF EQUAL FIX RIGHT EDGE
	RNC		;IF LESS DO IT
	LXI	H,GRY1	;ELSE DECREMENT GRY1 TWICE
	MOV	A,M
	ORA	A	;TO GET TO NEXT LOWER BYTE
	RZ		;DO NOT GO BELOW ZERO
	DCR	A	;DOWN TWO LINES
	JZ	DNLIN
	DCR	A
	MOV	M,A
	XRA	A	;SET ZERO FLAG TO START A NEW LINE
	RET
;
;
FIXRGT:	LDA	PIXBT2	;PIXBT2 IS FOR THE RIGHT EDGE
	ANI	03
	JRZ	FXRGT2	;IF ZERO THEN NO FIXING NEEDED
	PUSH	B	;SAVE X
	MOV	B,A
	MVI	D,0EEH	;TAKE OFF 'PIXBT2' BITS
	LXI	H,MASK2	;OFF RIGHT EDGE
	MOV	A,M
FXRGT1:	ANA	D
	RLCR	D
	DJNÚ	FXRGT1
	MOV	M,A	;SAVE IN MASK2
	POP	B	;GET X
FXRGT2:	INR	A
	RET
;
;
FIXBOT:	MVI	C,0F0H	;BOTTOM EDGE
	LDA	PIXBT2	;BIT 2 OF PIXBIT TELLS
	CMA		;US WHICH NIBBLE WE ARE IN
FIXNIB:	ANI	4	;FIXNIB IS USED BY FIXTOP ALSO
	RNZ		;RETURN IF NO FIXING NEEDED
	LXI	H,MASK2
	MOV	A,C	;AND MASK2 WITH F0 OR 0F
	ANA	M	;TO TAKE OFF TOP OR BOTTOM LINE
	MOV	M,A	
	INX	H
	MOV	M,C	;PUT 0F OR F0 IN MMASK
	RET		;TO REMEMBER
;
GRFEND	=	.-GRFSTR
;
LINDSP:	LDA	GRY
	ADI	16	;FIND OUT WHICH NIBBLE
	CMA		
	LXI	H,PIXBIT
	RES	5,M
	BIT	0,A
	JRNZ	LNDSP1
	SET	5,M
LNDSP1:	SRLR	A
	MVI	B,-1	;AND WHICH LINE
LNDSP2:	INR	B
	ADI	-5
	JRC	LNDSP2
	ADI	5
	RRC
	RRC
	RRC
	MOV	C,A
	LDA	LINOFS
	PUSH	PSW	;SAVE LINOFS
	ADD	B
	CPI	LINES
	JRC	LNDSP3
	ADI	-LINES
LNDSP3:	ORA	C
	POP	B	;IN B FOR EXTERNAL USE
	RET
;
XDDR:	MOV	A,L	;X COORDINATE IN [HL]
	ANI	0FCH
	ORA	H
	RRC
	RRC
	RET
;
SETBIT:	MOV	A,L	;FIND OUT WHICH BIT
    	RLC
	RLC		;IN THE NIBBLE
	RLC
	ANI	18H
	MOV	B,A
	LDA	PIXBIT
	ANI	0E7H
	ORA	B
	XRI	18H
	RET
;
;
;
;PLOT POINT SPECIFIED BY GRX,GRY
;
PPLOT:	LDA	GRFBIT+1
	STA	PIXBIT
	CALL	LINDSP	;INVERT Y
	OUT	SDSPY
	LHLD	GRX
	CALL	SETBIT	;GET X
	STA	GRFBIT+1
	CALL	XDDR	;SET X ADDRESS
	MOV	B,A
	MVI	C,DDSPY
	INP	A
GRFBIT:	SET	0,A	;MODIFIED BIT SET
	OUTP	A
	RET
;
;
CMPH:	STA	GRMODE
	MOV	A,L
	CMA
	MOV	L,A
	MOV	A,H
	CMA
	MOV	H,A
	INX	H
	RET
;
	;
SWPX:	LHLD	GRX	;EXCHANGE GRX & GRX1
	LDED	GRX1
	SHLD	GRX1
	SDED	GRX
	RET
;
SWPY:	LHLD	GRY	;EXCHANGE GRY & GRY1
	LBCD	GRY1
	SHLD	GRY1
	SBCD	GRY
	RET
;
DRWBLK:	LHLD	GRX
	PUSH	H
	SHLD	GRX1
	CALL	VPLOT
	LHLD	GRX12
	PUSH	H
	SHLD	GRX1
	CALL	VPLOT
	POP	H
	SHLD	GRX
	SHLD	GRX1
	CALL	PPLOT
	LDA	GRY12
	STA	GRY	
	CALL	VPLOT
	POP	H
	SHLD	GRX
;
;PLOT VECTOR FROM X1,Y1 TO X,Y
;
;CALCULATE DELTA X
VPLOT:	CALL	SWPX
	PUSH	H
	XRA	A	;CLEAR CARRY & A
	STA	GRMODE	;INITIALIZE DELTA SIGNS
	DSBC	D
	JRNC	VPLOT1
	INR	A	;HANDLE -X
	CALL	CMPH	;COMPLEMENT H
VPLOT1:	XCHG		;LEAVE DELTA X IN D
; CALCULATE DELTA Y
	CALL	SWPY
	PUSH	H
	XRA	A	;CLEAR CARRY
	LDA	GRMODEŠ	DSBC	B
	JRNC	VPLOT2
	SET	1,A	;HANDLE -Y
	CALL	CMPH
; HL = DELTA Y
; COMPARE DELTA X AND DELTA Y
VPLOT2:	PUSH	H
	XRA	A	;CLEAR CARRY
	LDA	GRMODE
	DSBC	D
	POP	H
	JRC	VPLOT3
	XCHG		;SET UP FOR DELTA Y >= DELTA X
VPLOT3:	MOV	B,D	;SET UP FOR DELTA X > DELTA Y
	MOV	C,E
	SDED	GDELL
	SHLD	GDELS
	LXI	H,GRX
	LXI	D,GRY
	JRC	VPLOT4
	XCHG
	BIT	0,A	;SWAP BITS 1 & 0
	RAR
	RES	1,A
	JRZ	VPLOT4
	SET	1,A
VPLOT4:	SHLD	GLL	
	SHLD	GLS	
	XCHG
	SHLD	GSL	
	SHLD	GSS	
	BIT	1,A
	PUSH	PSW
	MVI	A,13H	;INX H
	JRZ	VPLOT5
	MVI	A,1BH	;DCX H
VPLOT5:	STA	GSI	;SET LONG DIMENSION INCREMENT
	POP	PSW
	BIT	0,A
	MVI	A,23H
	JRZ	VPLOT6
	MVI	A,2BHŠVPLOT6:	STA	GLI
; PLOT ACTUAL VECTOR
	MOV	H,B	;GRK=GDELL/2
	MOV	L,C
	SRLR	H
	RARR	L
	SHLD	GRK
VPLOT7:	MOV	A,B
	ORA	C
	JRZ	VPLOT9
	PUSH	B
GLL1:	LHLD	GRX	;MODIFIABLE CODE
GLI:	INX	H	;MODIFIABLE CODE
	SHLD	GRX	;MODIFIABLE CODE
	LHLD	GRK
	LDED	GDELS
	ORA	A
	DSBC	D
	JRNC	VPLOT8
	LDED	GDELL
	DAD	D
	LDED	GRY	;MODIFIABLE CODE
	INX	D	;MODIFIABLE CODE
	SDED	GRY	;MODIFIABLE CODE
VPLOT8:	SHLD	GRK
	CALL	PPLOT
	POP	B
	DCX	B
	JMPR	VPLOT7
VPLOT9:	POP	H	;RESTORE GRX & GRY
	SHLD	GRY
	POP	H
	SHLD	GRX
	RET
;
GLL	=	GLL1+1
GLS	=	GLL+4
GSL	=	GLL+25
GSI	=	GLL+27
GSS	=	GLL+30
;
;CLEAR GRAPHIC MEMORY
;
GRFCLR:	MVI	B,LINES
	MVI	D,0
GRFCL1:	PUSH	B	;--LOOP LINES LINES
	MVI	B,5
GRFCL2:	PUSH	B	;----LOOP 5 SCAN PAIRS
	MOV	A,D
	OUT	SDSPY
	LXI	B,79*256+DDSPY
	XRA	A
GRFCL3:	OUTP	A	;------LOOP 80 CHAR POS.
	DJNZ	GRFCL3	;------END LOOP
	OUTP	A
	MOV	A,D
	ADI	20H
	MOV	D,A
	POP	B
	DJNZ	GRFCL2	;----END LOOP
	MOV	A,D
	INR	A
	ANI	1FH
	MOV	D,A
	POP	B
	DJNZ	GRFCL1	;--END LOOP
	RET
;
	.LIST
	.IFE	LSTVLE,[
	.XLIST
]
	.PAGEŠ;
;|------------------------------|
;|           VALET		|
;|------------------------------|
;
VALCHK:	LHLD 	TEMSTK
        SHLD	VALPNT
        POP	PSW
        POP	B
	POP	D
	POP	H
	LXI	SP,VALSTK
	PUSH	H
	PUSH	D
	PUSH	B
	PUSH	PSW
	LXI	H,NUMFLG
	MOV	A,M
	MVI	M,0
	STA	NUMSAV
	LXI	H,WSFLAG
	MOV	A,M
	MVI	M,0
	STA	WSSAVE
	LXI	H,VALENT
	PUSH	H
	RETI
;
CLNVAL:	DI
	XRA	A	; 00H TELLS OUTBLK TO READ
	CALL	OUTBLK
	LXI	H,VALCLN
	LDA	LSAVE
	BIT	1,A
	JRNZ	CLNVL1
	INX	H
	INX	H
CLNVL1:	CALL	VALMSG
	XRA	A
	STA	VALSTP
	STA	VALTIM
	STA	SETFLG
	STA	NOKEY
	CMA
	STA	TIMFLG
	LDA	NUMSAV
	STA	NUMFLG
	LDA	WSSAVE
	STA	WSFLAG
;
RSTALM:	LXI	H,600
RSTAL1:	XRA	A
RSTAL2:	STA	ALMCNT
	SHLD	ALMFLG
	RET
;
VALEXT:	CALL	CLNVAL
	DI
	LXI     SP,VALSTK-8	
	POP	PSW
	POP	B
	POP	D
	POP	H
	LSPD	VALPNT
	EI
	RET
;
VALENT:	MVI	A,0FFH
	STA	SETFLG
	EI
	CALL	OUTBLK	;0FFH TELLS OUTBLK TO SAVE
	LDA	LSTATE
	STA	LSAVE
	LXI	H,VALPAR
	CALL	VALMSG
VALRTN:	MVI	A,0FFH
	STA	VALTIM
	LXI	H,2037H
	CALL	POSCUR
	LXI	B,5020H	
VLLOOP:	CALL	DISPLY
	DJNZ	VLLOOP
	CALL	BRTDSP	;DISPLAY CURRENT
	CALL	VOLDSP	;PARAMETERS 
	CALL	KEYDSP
	CALL	COMUP
	CALL	PNTUP
	CALL	BELDSP
VLVEX1:	EI		;POSITION CURSOR
	LDA	VALCMD
	CPI	'!'	; IF VALCMD IS ! 
	JRZ	VLV2	;  THEN GOTO OVERLAY
	CALL    CONIN	; ELSE GET KEY
	ORA	A	; IF = CTRL/ESC
	JRZ	VLV0	;  THEN EXIT SET-UP MODE
	CPI	9	; ELSE IF = ASCII TAB
	JRZ	VLV2	;  THEN GOTO OVERLAY
	CPI	3AH	; ELSE IF > ASCII 9	
	JRNC	VLV1	;  THEN ..V1
	CPI	29H	; ELSE IF > ASCII 0 
	JRNC	VLV3	;  THEN ..V3
VLV0:	JMP	VALEXT	; ELSE EXIT SET-UP MODE
VLV1:	ANI	0DFH	; CHANGE TO UPPER CASE
	CPI     'A'	; IF < ASCII 'A'
	JRC	VLV0	;  THEN EXIT SET UP MODE
	CPI     'Z'+1	; ELSE IF > ASCII 'Z'
	JRNC	VLV0	;  THEN EXIT SET-UP MODE
	STA	VALCMD	; ELSE STORE CHARACTER
VLV2:	JMP	GETVAL	; GOTO OVERLAY
VLV3:	SUI	30H	; SET ASCII NUMERIC TO 0 OFFSET
	LXI	H,VLVEX1
	PUSH	H
;
	JRNZ	VLBRIT	;0 - BELL TOGGLE
	LDA	CURBEL	;COMPLEMENT CURBEL
	CMA
	CALL	WRTBEL	;SAVE IN CMOS RAM
	JMP	BELDSP	;DISPLAY CURRENT STATE
;
VLBRIT: DCR     A	;1 - BRIGHT UP
	LXI	H,BRTLEV
	JRNZ	VLBTDN	 
	MOV	A,M	;CHECK CURRENT BRIGHTNESS
	CPI	1FH	;FOR MAX
 	RZ		;IF MAX-GET KEY
	INR	A	;ELSE INCREASE BRIGHTNESS
	JMPR	VLDOBT	
VLBTDN:	DCR     A	;2 - BRIGHT DOWN
	JRNZ	VLVLUP		
	MOV	A,M	;CHECK CURRENT BRIGHTNESS
	ORA	A	;FOR MINIMUM
	RZ		;IF MIN-GET KEY
        DCR	A	;ELSE DECREASE BRIGHTNESS
VLDOBT:	PUSH   	PSW
	CALL	WRTBRT
	POP	PSW
	PUSH	PSW
	CALL	BRTADJ	;ADJUST BRIGHTNESS TO NEW VALUE
	POP	PSW
	JMP	BRTDSP
VLVLUP:	DCR     A	
	LXI	H,VOLEVL
	JRNZ	VLVLDN
	MOV	A,M	;READ CURRENT VOLUME
        CPI	0FH	;MAX?
	RZ		;YES-GET KEY
        INR	A	;ELSE INCREASE
	JMPR	VLDOVL	;AND ADJUST
VLVLDN:	DCR	A	;4 - VOLUME DOWN
	JRNZ	VLCLKS
	MOV	A,M 	;READ CURRENT VOLUME
	ORA	A	;MIN?
	RZ		;YES-GET KEY
	DCR	A	;ELSE DECREASE
VLDOVL:	PUSH	PSW
	CALL	WRTVOL
	POP	PSW
	PUSH 	PSW
        CALL	VOLADJ	;ADJUST VOLUME TO NEW VALUE
	LXI	H,MIDA	
	CALL	SOUND	;OUTPUT SOUND
	POP 	PSW
	JMP	VOLDSP	;AND DISPLAY NEW VALUE
VLCLKS:	DCR	A	;5 - CHANGE CLICK
	JRNZ	VLCOM
	LDA	TONTYP	;READ CURRENT CLICK
	LHLD	CLIKAD	;POINT TO CLICK TABLE
	LXI	B,15	;POINT TO NEXT CLICK
        DAD	B
	INR	A
	CPI	5	;IF PAST END OF TABLE
 	JRNZ	VLCLK1	;RESET POINTER
	LXI	H,NOTONE;TO START OF TABLE
	XRA	A
VLCLK1:	PUSH	PSW
        PUSH    H
	CALL	WRTTON	;WRITE CURRENT CLICK TO
	POP	H	;CMOS RAM
	SHLD	CLIKAD
	CALL	SOUND	;OUTPUT A CLICK
	POP	PSW
	JMP	KEYDSP+3;DISPLAY NEW VALUE
VLCOM:	DCR	A		
	JRNZ	VLCMDN	
	CALL	REDCOM
	CPI	10
	RZ
	INR	A
	JMPR	VLDOCM
VLCMDN:	DCR	A
	JRNZ	VLPTUP
	CALL	REDCOM
	ORA	A
	RZ
       	DCR	A
VLDOCM:	CALL	WRTCOM
	CALL	COMUP
	JMP	ADJCOM
;
VLPTUP:	DCR	A
        JRNZ	VLPTDN
	CALL	REDPNT
	CPI	10
	RZ
	INR	A
	JMPR	VLDOPT
VLPTDN:	CALL	REDPNT
	ORA	A
	RZ
	DCR	A
VLDOPT:	CALL	WRTPNT
	CALL	PNTUP
	JMP	ADJPNT
;
	.PAGE
;
DSPTM1:	LXI	H,2037H
	CALL	POSCUR
	LXI	H,NOTSET
	CALL	VALMSG
	JMP	DSPTMX	
;
DSPTIM:	PUSH	H
	PUSH	D
	PUSH	B
	LHLD	CHRADR	; SAVE CURSOR POSITION
	LXI	D,2020H
	DAD	D
	PUSH	H
;
	CALL	READTM	; READ TIME
	EI
	CPI	'?'	; IF READ ERROR
	JRZ	DSPTM1	;  THEN DISPLAY ERROR
;
	LXI	H,2037H	; POSITION CURSOR
 	CALL	POSCUR
;
	LXI	H,HRS10	; DISPLAY HOURS
	MOV	A,M
	CPI	'0'	; SUPPRESS LEADING 0
	JRNZ	..J0	
	MVI	A,SPC
..J0:	MOV	C,A
	CALL	DISPLY
	DCX	H
	MOV	C,M
	CALL	DISPLY
;
	MVI	E,2	; DISPLAY MINS. & SECS.
..L0:	LXI	B,3*256+':'
..L1:	CALL	DISPLY
	DCX	H
	MOV	C,M
	DJNZ	..L1
	INX	H
	DCR	E
	JRNZ	..L0
;
	CALL	READAT	; READ DATE
	EI
	CPI	'?'	; IF ERROR
	JRZ	DSPTM1	;  THEN ERROR MESSAGE
;
	MVI	C,SPC
	CALL	DISPLY
	LXI	H,MINS10; ELSE DISPLAY DATE
	MOV	A,M
	ANI	0F3H	; ??????????
	CPI	'0'	; SUPPRESS LEADING 0
	JRNZ	..J1
	MVI	A,SPC	
..J1:	MOV	C,A	; DISPLAY DAY
	CALL	DISPLY
	DCX	H
	MOV	C,M
	CALL	DISPLY
;
	LXI	B,3*256+'/'
..L3:	CALL	DISPLY
	DCX	H
	MOV	C,M
	DJNZ	..L3
;
DSPTMX:	POP	H
	CALL 	POSCUR	;CURSOR TO LOWER RIGHT CORNER
	MVI	A,0FFH
	STA	TIMFLG	;SET FLAGS FOR SRV60 & CONIN
	STA	VALTIM
	POP	B
	POP	D
	POP	H
	RET
;
	.PAGE
;
ADJPNT:	CALL	REDPNT
	MVI	E,BAUDP
	JMPR	BAUDGN
;
ADJCOM:	CALL	REDCOM
	MVI	E,BAUDC
;
BAUDGN:	RLC		;OUTPUT TWO BYTES
	MOV	C,A	;FROM BAUD
	MVI	B,0	;TABLE
	LXI	H,BTABL
	DAD	B	;CONTROL WORD AND TIME CONSTANT WORD
	DI
	MOV	C,E
	MOV	A,M	;MASK OUT INT. ENAB. BIT
	ANI	70H
	ORI	7
	OUTP	A
	INX	H
	OUTI
	RET
;
BRTADJ:	ANI	1FH	;SHIFT LEVEL INTO
	RLC		; CORRECT POSITION
	RLC		; FOR LATCH
	RLC	
	MOV	D,A	; SAVE NEW LEVEL
	XRA	A
	MVI	A,7
	CALL	LLATCH	; CLEAR PRESENT LEVEL
	ORA	A
	MOV	A,D	
	JMP	LLATCH	; OR IN NEW LEVEL
;
GTBRIT:	MVI	B,0AH	;GET MSB AND LSB
	CALL	RD5101	;OF BRIGHTNESS LEVEL
	PUSH	PSW	;FROM CMOS RAM
	MVI	B,0BH
	CALL	RD5101
	POP	B
	JMP	PACK	;PACK INTO ONE BYTE
;
VOLADJ: LXI	H,NOTONE+4	
	MVI	B,5	;CHANGE VOLUME BY CHANGING
VOL1:   PUSH    B	;3 BYTES IN EACH
        MVI	B,3	;OF 5 SOUNDS
VOL2:   MOV	M,A	
	INX	H
	DJNZ	VOL2
	LXI	D,000CH
	DAD	D
        POP	B
	DJNZ    VOL1
	RET
;
OUTBLK:	MVI	B,2
	LXI	H,22
	LXI	D,DSPBFL
	ORA	A
	JRZ	..L1
;
..L0:	PUSH	B
	PUSH	H
	MVI	C,0C0H
	CALL	OTLIN
	POP	H
	PUSH	H
	MVI	C,0E0H
	CALL	OTLIN
	POP	H
	POP	B
	INR	L
	DJNZ	..L0
	RET	
;
..L1:	PUSH	B
	PUSH	H
	MVI	C,0C0H
	CALL	INLIN
	POP	H
	PUSH	H
	MVI	C,0E0H
	CALL	INLIN
	POP	H
	POP	B	
	INR	L
	DJNZ	..L1
	RET	
;
OTLIN:	CALL	CMPOFF
	MOV	A,L
	ORA	C
	OUT	SDSPY
	LXI	B,79*256+DDSPY
	XCHG
	INIR
	INI
	XCHG
	RET
;
INLIN:	CALL	CMPOFF
	MOV	A,L
	ORA	C
	OUT	SDSPY
	LXI	B,80*256+DDSPY
	XCHG
	OUTIR
	XCHG
	RET
;
VALMSG:	JMP	MESSG
;
BELDSP:	LDA	CURBEL	;SET HL TO CURSOR POSITION
	ANI	1
	LXI	H,6937H	;DE POINTS TO BELL TABLE
	LXI	D,BELTBL
	JMPR	BAUD1
;
KEYDSP: LDA	TONTYP
	LXI	H,4637H	;DE POINTS TO CLICK TABBBLE
	LXI	D,KNMTBL
	JMPR	BAUD1
;
COMUP:	CALL	REDCOM	; GET COMM. BAUD RATE
   	LXI    	H,5137H	;DE POINTS TO BAUD TABLE
	JMPR	BAUD0	
;
PNTUP:	CALL	REDPNT	; GET PRINTER BAUD RATE
      	LXI	H,6037H	;DE POINTS TO BAUD TABLE
BAUD0:	LXÉ	D,BNMTBL
BAUD1:	ORA	A
	PUSH	PSW
	CALL	POSCUR	;POSITION CURSOR
	POP	PSW
	JRZ	BAUD2
	MOV	B,A	;ADD INDEX TO TABLE POINTER
	RLC
	RLC
	ADD	B
BAUD2:	MOV	C,A
	MVI	B,0
	XCHG
	DAD	B
	JMP	VALMSG	;DISPLAY CURRENT PARAMETER
;
POSCUR:	SET	7,H	;POSITION CURSOR TO
	SHLD	POSITN
	LXI	H,GOPOS
	JMP	VALMSG
;
VOLDSP:	LXI     H,3F37H	;DISPLAY CURRENT VOLUME
	CALL	POSCUR
	LDA	VOLEVL
	JMPR	BTDSP1
;
BRTDSP:	LXI	H,3437H	;POSITION CURSOR
	CALL	POSCUR
	LDA	BRTLEV
BTDSP1:	INR	A	;CONVERT NUMBER IN A
	MVI	C,'0'
BTDSP2:	SUI	10	;TO ASCII
	JM	BTDSP3
	INR	C	;MOST SIGNIFICANT DIGIT IN C
	JMPR	BTDSP2
BTDSP3:	ADI	'9'+1	;LEAST SIGNIFICANT DIGIT IN A
	MOV	B,A
	MOV	A,C	;IN MSD IS 0
	CPI	'0'	;THEN SUPPRESS IT
	JRNZ	BTDSP4
	MVI	C,SPC
BTDSP4:	CALL	DISPLY	;DISPLAY
	MOV	C,B
	JMP	DISPLY
;
	.LIST
	.IFE	LSTVLD,[
	.XLIST
]
	.PAGE
;
;|-------------------------|
;|  	VALET DISK I/O	   |
;|-------------------------|
;
; ************ I M P O R T A N T ******************
; *						  *
; *   THIS MODULE IS COMPANY CONFIDENTIAL AND IS  *
; *	NOT TO BE SUPPLIED TO ANYONE OUTSIDE THE  *
; *	COMPANY REGARDLESS OF ANY CIRCUMSTANCES.  *
; *************************************************
;
;
;  THESE ROUTINES SAVE THE HOST BUFFER, AND FIND THE VALET.VL2
;	FILE.
;
VALSTR	=	2000H		;VALET ENTRY POINT
;	
GETVAL:	DI
	XRA	A
	STA	VALTIM
	CMA
	STA	TIMFLG
	STA	NOKEY
	EI
	LXI	D,20AH	;SAVE HOST BUFFER
	CALL	WRTSEC
	CALL	SCHDIR	;FIND AU'S FOR VALET.VL2
	MVI	B,0	;SAVE TPA
	MVI	A,2
	CALL	RWVAL
	JNZ	BWTERR
;
	MVI	B,3	; START AT A.U. 3
	MOV	A,B	; READ
	CALL	RWVAL
	JNZ	BRDERR
	LXI	H,SAVAUS	;ALLOCATION UNIT TABLE
	LDA	EXM
	JMP	VALSTR	;VALET ENTRY POINT
;
COMPAR:	LXI	D,HSTBUF	
	MVI	C,HSTSIZ/32	;# OF POSSIBLE FCB'S
CL3:	LXI	H,VALMOD	;COMPARE WITH VALET.VL2 FCB
CL2:	MVI	B,12		;
CL1:	LDAX	D
	ANI	7FH
	RES	7,M	
	CMP	M
	JRNZ	INCBUF	;NO MATCH HERE
	INX	H
	INX	D
	DJNZ	CL1
	LXI	H,4
	DAD	D	;HL=AU'S FOR VALET.VL2
	LDA	EXM	;IF 48 TPI
	ORA	A
	MVI	A,0
	RNZ		;WE ARE DONE
	LDA	SNDAU	;IF 96 TPI
	ORA	A
	MVI	A,0	;RETURN IF SECOND FCB
	RNZ		;
	PUSH	B
	CALL	GOTVLY	;SAVE THE FIRST
	POP	B	;16 AU'S
			;AND SEARCH FOR MORE
;
INCBUF:	LXI	H,32	;MOVE TO NEXT FCB
	PUSH	B
	MVI	A,12
	SUB	B
	MOV	C,A	
	MVI	B,0	;SUBTRACT THE CHARACTERS 
	DSBC	B	;THAT MATCHED
	DAD	D	;AND ADD 32
	XCHG		;GET RESULT IN DE
	POP	B
	DCR	C	;FCB COUNTER
	MVI	A,1	;FLAG FOR NO MATCH
	RZ		;END OF HSTBUF
	JMPR	CL3	;
;	
PUTVAL:	MVI	B,0	;RESTORE TPA
	MVI	A,3
	CALL	RWVAL
	JRNZ	BRDERR
;
PTVAL1:	LXI	D,20AH	;RESTORE HOST BUFFER
	CALL	REDSEC
	JMP	VALEXT
;
;        SEARCH DIRECTORY FOR VALET.VL2 FILE
;
SCHDIR:	XRA	A
	STA	SNDAU
	LXI	D,301H	;TRACK 3 - SECTOR 1
RWLOP:	LXI	B,100H	;1 SECTOR - DRIVE 0
RWLP1:	MVI	A,3	;READ
	LXI	H,SECCNT
	MVI	M,1		;1 SECTOR
	LXI	H,HSTBUF	;READ INTO HOST BUFFER
	CALL	RWONE
	ORA	A
	JNZ	BWTERR	;READ ERROR
	PUSH	D	;SAVE SECTOR & TRACK #
	CALL	COMPAR
	POP	D
	ORA	A
	JRZ	GOTVLY	;FOUND IT
	INR	E
	MOV	A,E	;8 SECTORS MAX.
	CPI	9	;FOR DIRECTORY
	JRNZ	RWLOP
	JMPR	BWTERR	;VALET NOT FOUND
;		
GOTVLY:	PUSH	D	;SAVE TRACK & SECTOR &
	LXI	D,SAVAUS+16
	LDA	SNDAU
	ORA	A
	JRNZ	LL1
	LXI	D,SAVAUS
LL1:	LXI	B,16
	LDIR
	MVI	A,1
	STA	SNDAU
	POP	D
	RET
;
BRDERR:	CALL	VLERRR
	LXI	H,OPTV1
	CALL	MESSG
	CALL	CONIN
	CALL	CLNVAL
	JMP	WBOOT
;
BWTERR:	CALL	VLERRR
	LXI	H,OPTV2
	CALL	MESSG
	CALL	CONIN
	JMPR	PTVAL1
;
VLERRR:	MVI	A,'A'
	STA	DRVNUM
	LXI	H,VALLER
	JMP	MESSG
;
WRTSEC:	MVI	A,2
	JMPR	SECTIN
REDSEC:	MVI	A,3
SECTIN:	PUSH	PSW
	MVI	A,10
	STA 	RECNT
	MVI	A,1
	STA	SECCNT
	POP	PSW
	LXI	B,100H
	LXI	H,HSTBUF
	JMP	RWONE
;	
;	B=START A.U. #
;	A=R/W COMMAND 2=WRITE 3=READ
;					
RWVAL:	LXI	H,VALSTR	; START AT VALET .LOC
	STA	VALOP	; STORE R/W COMMAND
	MVI	A,3
	STA	VALCNT	; DO 3 A.U.'S
;
RWVAL1:	PUSH	B
	PUSH	H
	CALL	GTRKSC	; GET STARTING TRACK & SECTOR OF A.U.
	POP	H
	PUSH	H
	MVI	A,4
	STA	SECCNT	; READ 4 SECTORS (1 A.U.)
	MVI	A,10
	STA	RECNT
	LXI	B,100H	; 1 SECTOR AT A TME, DRIVE 0
	LDA	VALOP	; GET RWCMD
	CALL	RWONE	; DO DISK OP
	POP	H
	POP	B
	ORA	A	; IF ERROR
	RNZ		;  THEN RETURN
	INR	B	; ELSE INC A.U.
	XCHG
	LXI	H,VALCNT
	DCR	M	; IF ALL A.U.S READ
	RZ		;  THEN RETURN
	XCHG		; ELSE CALC. NEW DMA ADDR.
	LXI	D,800H	
	DAD	D
	JMPR	RWVAL1
;
GTRKSC:	LXI	H,SAVAUS	;ALLOCATION UNITS FOR
	MOV	A,B		;VALET.VL2 FILE
	ORA	A
	LDA	EXM
	JRZ	GTRKS2
	ORA	A
	JRNZ	GTRKS1
	SLAR	B
GTRKS1:	INX	H
	DJNZ	GTRKS1
GTRKS2:	MOV	C,M
	INX	H
	MOV	B,M
	ORA	A
	JRZ	GTRKS3
	MVI	B,0
GTRKS3:	MOV	H,B
	MOV	L,C
	DAD	H	; MLPY BY 4
	DAD	H
	MOV	B,H	; SAVE
	MOV	C,L
	LXI	D,10
	XRA	A
GTRKS4:	INR	A
	ANA	A
	DSBC	D
	JP	GTRKS4
	DAD	D
	ADI	2
	INR	L
	MOV	D,A
	MOV	E,L
	RET
;
	.LIST
	.IFE	LSTVLM,[
	.XLIST
]
        .PAGE	
; 
;|----------------------------------------------|
;|	CLOCK AND BACKUP RAM I/O ROUTINES	|
;|----------------------------------------------|
;
WRTBRT:	STA	BRTLEV
	PUSH	PSW
	RLC
	RLC
	RLC
	RLC
	MVI	B,0AH
	CALL	WR5101
	POP	PSW
	MVI	B,0BH
	JMPR	WR5101
;
WRTBEL:	STA	CURBEL
	MVI	B,5
	JMPR	WR5101
;
WRTVOL:	STA	VOLEVL
	MVI	B,6
	JMPR	WR5101
;
WRTTON:	STA	TONTYP
	MVI	B,9
	JMPR	WR5101
;
WRTPNT:	MVI	B,7
	JMPR	WR5101
;
WRTCOM:	MVI	B,8
	JMPR	WR5101
;	
WRTSLK:	STA	SHLOCK
	MVI	B,0EH
;
WR5101:	CALL	SU5101
	XRA	A
	CALL	RWPORT
	MOV	A,D
	OUT	DPIOA
	MVI	C,DPIOB
	MOV	A,E
	ORI	0B0H
	JMP	WCOMON
;
W58174:	CALL	PACK
	MOV	D,A
	XRA	A
	CALL	RWPORT
	MOV	A,D
	OUT	DPIOA
	MVI	C,DPIOB
	MVI	A,0A8H
	JMPR	WCOMON
;
REDCOM:	MVI	B,8
	JMPR	RD5101
;
REDPNT:	MVI	B,7
;
RD5101:	CALL	SU5101
	MVI	A,0FH
	CALL	RWPORT
	MOV	A,D
	OUT	DPIOA
	MVI	C,DPIOB
	MOV	A,E
	ORI	0B4H
	JMPR	RCOMON
;
R58174:	CALL	PACK
	MOV	D,A
	MVI	A,0FH
	CALL	RWPORT
	MOV	A,D
	OUT	DPIOA
	MVI	C,DPIOB
	MVI	A,0ACH
;
RCOMON:	OUTP	A
	ANI	0DFH
	OUTP	A
	IN	DPIOA
	MOV	B,A
	JMPR	DSLC	
;
RWPORT:	MVI	C,SPIOA	
	MVI	B,0CFH
	DI
	OUTP	B
	OUTP	A
	RET
;
WCOMON:	OUTP	A
	ANI	0DFH
	OUTP	A
DSLC:   MVI	A,0A0H	
 	OUTP	A
	MOV	A,B
	ANI	0FH
	RET
;
SU5101:	CALL	PACK	
	MOV	D,A
	MOV	A,C
	ANI	30H
	RRC
	RRC
	RRC
	RRC
	MOV	E,A
	RET
;
PACK:	MOV	C,B
	ANI	0FH
	MOV	D,A
	MOV	A,B
	ANI	0FH
	RLC
	RLC
	RLC
	RLC
	ORA	D
	RET
;
	.LIST
	.IFE	LST60H,[
	.XLIST
]
	.PAGE
;
;|--------------------------------------|
;|					|
;|	60 HZ INTERRUPT ROUTINE		|
;|					|
;|--------------------------------------|
;
SRV60:	SSPD	TEMSTK
	LXI	SP,INTSTK
      	PUSH	H	;SAVE REGISTERS
	PUSH	D
	PUSH	B
	PUSH	PSW
;|------------------------------|
;|   CHECK KEYCLICK SHUTDOWN	|
;|------------------------------|
	LXI	H,TONPER
	MOV	A,M
	ORA	A
	JRZ	SRV60A
	DCR	M
	JRNZ    SRV60A
	INX	H
	CALL 	SOUND
;|------------------------------|
;|	HANDLE KEYBOARD		|
;|------------------------------|
SRV60A:	IN	DPIOB	;CHECK FOR KEY
	BIT	6,A
	JZ	CHKALM	; NO KEY PRESENT
	LDA	TONTYP	;IF KEYCLICK OFF
	ORA	A	;DO NOT CHANGE SOUND
	JRZ	NOSND
	LHLD    CLIKAD  ;SOUND THE KEY
	CALL	SOUND
NOSND:	MVI	B,9
SRV60B:	IN	DPIOB	;BIT INTO CARRY
	RLC
	RLC
	CMC
	RARR	L
	MVI	A,7FH	;CLOCK DOWN
	OUT	DPIOB
	MVI	A,0FFH	;CLOCK UP
	OUT	DPIOB
	DJNZ	SRV60B
;
;|------------------------------|
;|	TRANSLATE KEYCODE	|
;|------------------------------|
;
	MVI	H,0
	MOV	C,L
	LXI	D,KEYTBL
	DAD	D
	MOV	B,M
;
;|------------------------------|
;|	EVALUATE KEYCODE	|
;|------------------------------|
;
	LDA	WSFLAG
	ORA	A
	JRZ	CHKCTL	; NOT IN WORDSTAR
;
;	CHANGE NORMAL CODES TO WS CODES
;
	MOV	A,C
	CPI	50H	; 1EH -> 0A8H (CTRL/SHFT/^)
	JRNZ	WSCOD0	;  (HIDE)
	MVI	B,0A8H
WSCOD0:	CPI	7EH	; 1FH -> 0CH (CTRL/SHFT/_)
	JRNZ	WSCOD1	;  (FIND/REPLACE AGAIN)
	MVI	B,0CH
WSCOD1:	CPI	8CH	; 08H -> 13H (LEFT ARROW)
	JRNZ	WSCOD2	;  (CURSOR LEFT)
	MVI	B,13H
WSCOD2:	CPI	8DH	; 0CH -> 04H (RIGHT ARROW)
	JRNZ	WSCOD3	;  (CURSOR RIGHT)
	MVI	B,4
WSCOD3:	CPI	8EH	; 0BH -> 05H (UP ARROW)
	JRNZ	WSCOD4	;  (CURSOR UP)
	MVI	B,5	
WSCOD4:	CPI	8FH	; 0AH -> 18H (DOWN ARROW)
	JRNZ	CHKCTL	;  (CURSOR DOWN)
	MVI	B,18H
;
;	CONTROL CODE ?
;
CHKCTL:	BIT	7,B
	JRNZ	CHKSPL	; CONTROL CODE
;
;	KEYPAD MODE ?
;
	LDA	NUMFLG
	ORA	A
	JRZ	CHKCAP	; NOT 10 KEY PAD
;
;|------------------------------|
;|   10 KEY PAD TRANSLATION	|
;|------------------------------|
;
	MOV	A,C
	SUI	9BH	
	JM	CHKCAP
	CPI	ESC
	JRNC	CHKCAP
	LXI	H,PADTBL
	MOV	E,A
	MVI	D,0
	DAD	D
	MOV	A,M
	JMPR	NOCAP
;
;	NOT A CONTROL CHARACTER
;
CHKCAP:	LDA	SHLOCK	;CAPITALIZE IF NEEDED
	ORA	A
	MOV	A,B
	JRZ	NOCAP
;
;|------------------------------|
;|  CAPITALIZE IF SHIFT LOCKED	|
;|------------------------------|
;
	CPI	61H	;AFTER SMALL-A?
	JRC	NOCAP
	CPI	7BH	;BEFORE SMALL-Z?
	JP	NOCAP
	ANI	0DFH	;CAPITALIZE
NOCAP:	JMP	GOADDK	;ADD TO BUFFER
;
;|------------------------------|
;|    HANDLE CONTROL CODES	|
;|------------------------------|
;
;	HANDLE KEYPAD KEY
;
CHKSPL:	MOV	A,B
	CPI	0FDH
	JRNZ	CKSPL3
	LDA	NUMFLG
	ORA	A
	JRZ	CKSPL2
CKSPL1:	CMA
	STA	NUMFLG
	JMPR	CKSPL4
CKSPL2:	XRA	A
	STA	SHLOCK
	JMPR	CKSPL1
;
;	HANDLE CAPS LOCK KEY
;
CKSPL3:	CPI	0FEH
	JRNZ	CKVLKY
	XRA	A
	STA	NUMFLG
	LDA	SHLOCK
	CMA
	STA	SHLOCK
CKSPL4:	MVI	B,0EH
	CALL	WR5101
	JMP	CHKALM
;
;	HANDLE SET-UP KEY
;
CKVLKY: CPI	0FFH	 
	JRNZ	ALMDLY
CKVLK1:	LDA	NOKEY
	ORA	A	; IF IN VALET OVERLAY
	JNZ	CHKMTR	;  THEN IGNORE CTRL/ESC
	LDA	VALSTP	; ELSE
	MOV	B,A  	; IF NOT IN W OR C BOOT OR DISK OPERATION
	LDA	DSKFLG	;  OR DISPLAY DRIVER
	ORA	B
	MOV	B,A
	LDA	DSPFLG
	ORA	B
	MOV	B,A
	LDA	DSPCYC
	ORA	B
	JRZ	DOVLKY
;
	MVI	A,0FFH	; ELSE SET VALET PENDING FLAG TO WAIT
	STA	VALPND	;  FOR OK TIME TO ENTER OR EXIT VALET
	JMP	CHKMTR
;
DOVLKY:	XRA	A
	STA	VALPND
	LDA     SETFLG
	CMA	
	ORA	A
	JZ	GOADDK
	CALL	RSTALM
	JMP	VALCHK
;
;	ALARM DELAY (5 MINUTES)
;
ALMDLY:	CPI	0FCH
	JRNZ	CHKBRK
	MVI	A,0FFH
	STA	ALMWAT
	LXI	H,BELLTN
	CALL	SOUND
	JMPR	CHKALM
;
;	ALL OTHER CONTROL CHARACTERS
;
CHKBRK:	CPI	0FBH
	JRNZ	CKWSFL
	MVI	A,5
	OUT	SCOMM
	LDA	SIORG5
	ORI	10H
	OUT	SCOMM
	MVI	A,32
	STA	BRKCNT
	JMPR	CHKALM
;
CKWSFL:	MOV	B,A
	LDA	WSFLAG
	ORA	A	; IF NOT IN WS
	MOV	A,B
	JRZ	GOADDK	; THEN DON'T DO XLATION
;
;	WORDSTAR SPECIAL TRANSLATION
;
	STA	CTLCOD	;  ELSE XLATE TO WS SEQUENCE
	ANI	60H	; WHICH PREFIX?
	JRNZ	WSCOD7
	MVI	A,CTRLQ	;CTRL-Q
WSCOD6:	CALL	WSCODB
	JMPR	CHKALM	
;
WSCOD7:	CPI	20H
	JRNZ	WSCOD8
	MVI	A,CTRLK	;CTRL-K
	CALL	WSCODB
	CPI	CTRLS
	JRNZ	CHKALM
	MVI	A,CTRLQP ;CTRL-KSQP
	JMPR	CKWSFL
;
WSCOD8:	CPI	40H
	JRNZ	CHKALM
	LDA	CTLCOD	;CTRL-J, O, OR P
	CPI	CTRLJH
	JRNZ	WSCOD9
	MVI	A,CTRLJ	;CTRL-JH
	JMPR	WSCOD6
;
WSCOD9:	CPI	CTRLPS
	JRNZ	WSCODA
	MVI	A,CTRLP	;CTRL-PS
	JMPR	WSCOD6
;
WSCODA:	MVI	A,CTRLO	;CTRL-O
	CALL	WSCODB
	JMPR	CHKALM
;
WSCODB:	CALL	ADDKEY
	LDA	CTLCODŠ	ANI	1FH
	JMP	ADDKEY
;
GOADDK:	CALL	ADDKEY
;
;|------------------------------|
;|	CHECK ALARMS		|
;|------------------------------|
;
CHKALM:	LHLD	ALMFLG
	DCX	H
	SHLD	ALMFLG
	MOV	A,H
	ORA	L
	JRNZ	VALP
;
	LDA	ALMCNT	; SEE IF ALMCNT SHOULD BE RESET
	BIT	6,A
	CZ	RSTALM
;
	MVÉ	B,0FČ	» CMOÓ	RAÍ MONTH
	CALL	RD5101
	CPI	0FH
	JRZ	VALP
	PUSH	PSW
	CALL	READAT
	CPI	'?'
	POP	B
	JRZ	VALP
	LXI	H,MINS10
	MOV	A,M	; 10'S OF MONTH
	ANI	0FH
	DCX	H
	MOV	A,M	;UNITS OF MONTH
	JRZ	CKALM1
	ADI	0AH
CKALM1:	ANI	0FH
	CMP	B
	JRZ	CKALM2
	JNC	ALARM
	JMPR	VALP
CKALM2:	DCX	H
	LXI	B,1012H	; CMOS RAM DAY10
	CALL	CHKMOS
	JC	ALARM
	JRNZ	VALP
	CALL	READTM
	LXI	B,1216H	; CMOS RAM HRS. & MINS.
	LXI	H,HRS10
	CALL	CHKMOS
	JRZ	ALARM
	JRC	ALARM
;
;|------------------------------|
;|	VALET PENDING ?		|
;|------------------------------|
;
VALP:	LDA	VALPND
	ORA	A
	JNZ	CKVLK1
;
; DISPLAY TIME AND DATE ?
;
	LDA	VALTIM	
	ORA	A
	JRZ	CHKMTR
	XRA	A
	STA	TIMFLG
	STA 	VALTIM
;
;|------------------------------|
;|   FLOPPY MOTOR SHUT-DOWN	|
;|------------------------------|
;
CHKMTR:	LHLD	MTRCNT	;GET MOTOR TIMER
	MOV	A,H	;TEST FOR ZERO
	ORA	L
	JRNZ	CKMTR1	;IF <>0 ,THEN DECREMENT
	MVI	A,-2	; (Z BIT ALREADY SET)
	CALL	LLATCH	;  ELSE SHUT OFF MOTORS
	INX	H
CKMTR1:	DCX	H
	SHLD	MTRCNT
;
;|------------------------------|
;|   HANDLE DISK TIME OUT 	|
;|------------------------------|
;
	LDA	DSKCNT
	ORA	A
	JRZ	BREAK	; DSKCNT ALREADY = 0
	DCR	A
	STA	DSKCNT
	JRNZ	BREAK	; DSKCNT <> 0
	LDA	DSKCYC
	CPI	8	; IF NOT WAITING FOR READY
	JRNZ	TIMOUT	;  THEN ERROR
;
	CALL	SNSTAT	; ELSE SENSE DRIVE STATUS
	BIT 	5,A	;  IF DRIVE NOT OK
	JZ	WFRBAD	; THEN WAITING FOR READY ERROR
	LXI	H,RCLTBL; ELSE START 1ST RECAL
	MVI	A,4	; NEW DSKCYC = 4
	CALL	DORCSK
	JMPR	BREAK
;
;
TIMOUT:	CALL	CLRFDC	; -ALL OTHER TIMEOUT ERRORS
	LDA	DSKCYC	;  CLEAR OUT FDC 
	ORI	0C0H	;  DSKCYC OR WITH 0C0H
	STA	DSKCYC
;
BREAK:	LDA	BRKCNT
	ORA	A
	JRZ	IEND
	DCR	A
	STA	BRKCNT
	JRNZ	IEND
	MVI	A,5
	OUT	SCOMM
	LDA	SIORG5
	OUT	SCOMM
;
;|----------------------------------------------|
;|	EXIT SRV60 (ALSO USED BY SRVFPY)	|
;|----------------------------------------------|
;
IEND:	POP	PSW
	POP	B
	POP	D
	POP	H
	LSPD	TEMSTK
	EI       
        RETI
;
	.PAGE
;
;|--------------------------------------|
;|					|
;|    MISC. SRV60 SUBROUTINES		|
;|					|
;|--------------------------------------|
;
;|---------------------|
;|  SOUND VALET ALARM  |
;|---------------------|
;
ALARM:	LDA	ALMCNT
	ORI	40H
	CPI	40H
	JRNZ	ALJ3	
	LXI	H,ALMWAT
	MVI	M,0
;
ALJ0:	INR	A
	LXI	H,120
;
ALJ1:	CALL	RSTAL2
	MVI	A,'!'
	STA	VALCMD
ALJ2:	LXI	H,ALMSND
	CALL	SOUND
	JMP	VALP
;
ALJ3:	CPI	42H
	JRC	ALJ0
;
	LDA	ALMWAT
	ORA	A
	JRNZ	ALJ4
	MVI	B,17H
	CALL	RD5101
	ANI	2
	JRZ	ALJ4
	MVI	A,0FFH
	STA	VALPND
	LDA	NOKEY
	ORA	A
	JRZ	ALJ2	
;
ALJ4:	LXI	H,14400
	MOV	A,L	; L=40H
	JMPR	ALJ1
;		
;|----------------------------------------|
;|  COMPARE CMOS RAM TIME WITH REAL TIME  |
;|----------------------------------------|
;
CHKMOS:	PUSH	B
	CALL	RD5101
	POP	B
	ORI	30H
	CMP	M
	DCX	H
	RNZ
	INR	B
	MOV	A,B
	CMP	C
	JRNZ	CHKMOS
	RET
;
;|--------------------------------------|
;|  ADD KEY TO END OF KEYBOARD BUFFER	|
;|--------------------------------------|
;
ADDKEY:	MOV	B,A 
	LDA	KEYCNT	Š	CPI	KBUFLN	;IF BUFFER FULL
	LXI	H,BELLTN
	JZ	SOUND	; SOUND BELL, BUFFER FULL
	INR	A	; ELSE ADD KEY
	STA	KEYCNT
	LHLD	KEYPNT
	MOV	A,B
	MOV	M,A
	INX	H
	SHLD	KEYPNT
	RET
;
;|-----------------------------------|
;|  PUSH KEY(S) INTO KEYBOARD BUFER  |
;|-----------------------------------|
;
PUSHKY:	PUSH	H
	PUSH	B
	MVI	A,16
	SUB	C
	LXI	H,KEYBUF
	PUSH	H
	DI
	JRZ	PSHKY1	; IF PUSHING 16, THEN PSHKY1
;
	MOV	C,A	; ELSE MOVE OLD KEYS UP
	MVI	B,0
	DAD	B	; HL = (KEYBUF+(16-KEYS TO PUSH-1))
	DCX	H
	LXI	D,KEYBUF+15
	LDDR		; MOVE UP KEYS IN BUFFER
;
PSHKY1:	POP	D
	POP	B
;
	LDA	KEYCNT	; UPDATE KEYCNT	& KEYPNT
	LHLD	KEYPNT
	DAD	B
	ADD	C
	CPI	16
	JRC	PSHKY2
	MVI	A,16
	LXI	H,KEYBUF+16
PSHKY2:	STA	KEYCNT
	SHLD	KEYPNT
;
	POP	H
	LDIR		; ADD KEYS TO BUFFER
	EI
	RET
;															
	.LIST
	.IFE	LSTTBL,[
	.XLIST
]
	.PAGEŠ;
;|------------------------------|
;|	CLOCK READ TABLES	|
;|------------------------------|
;
;	FORMAT OF TABLES
;
;	1ST BYTE = OPERATION
;	  0 = TABLE TERMINATOR
;	  1 = READ FROM CLOCK CHIP
;	  2 = READ FROM CMOS RAM
;	2ND BYTE = ADDRESS TO READ FROM
;
NATTIM:	.BYTE	1,07	; TIME FROM NATIONAL CHIP
	.BYTE	1,06
	.BYTE	1,05
	.BYTE	1,04
	.BYTE	1,03
	.BYTE	1,02
	.BYTE	0
;
OKITIM:	.BYTE	1,05	; TIME FROM OKI CHIP
	.BYTE	1,04
	.BYTE	1,03
	.BYTE	1,02
	.BYTE	1,01
	.BYTE	1,00
	.BYTE	0
;
NATDAT:	.BYTE	2,13	; DATE FROM NATIONAL CHIP
	.BYTE	2,12
	.BYTE	1,12
	.BYTE	1,11
	.BYTE	1,09
	.BYTE	1,08
	.BYTE	1,10
	.BYTE	0
;
OKIDAT:	.BYTE	1,12	; DATE FROM OKI CHIP
	.BYTE	1,11
	.BYTE	1,10
	.BYTE	1,09
	.BYTE	1,08
	.BYTE	1,07
	.BYTE	1,06
	.BYTE	0
;
	.PAGE
	.RADIX	16
;
;|-------------------------------------|
;|     	   BAUD TABLE		       |
;|-------------------------------------|
;
BTABL:	.BYTE	37,0D,57,0AF,57,8F
	.BYTE	57,80,57,40,57,20
	.BYTE	57,10,57,08,57,04
	.BYTE	57,02,57,01
BNMTBL:	.ASCIS	'   75'
	.ASCIS	'  110'
	.ASCIS	'134.5'
	.ASCIS	'  150'
	.ASCIS	'  300'
	.ASCIS	'  600'
	.ASCIS	' 1200'
	.ASCIS	' 2400'
	.ASCIS	' 4800'
	.ASCIS	' 9600'
	.ASCIS	'19200'
BELTBL:	.ASCIS	' ON  '
KNMTBL:	.ASCIS	' OFF '
	.ASCIS	'CLICK'
	.ASCIS	' DINK'	
	.ASCIS	'BEEP1'
	.ASCIS	'BEEP2'
;
;|------------------------------|
;|	SOUND TABLES		|
;|------------------------------|
;
ALMSND:	.BYTE	00,03,20,20,1F,00,00,0F8
	.BYTE	00,41,87
;
TONPER:	.BYTE	0  ; LENGTH OF SOUND IN 1/60ths SEC.
;
NOTONE:	.BYTE	00,00,00,00,0F,0F,0F,0FF; NULL
	.BYTE	00,00,00,00,00,00,00
CLICK:	.BYTE	01,04,00,00,0F,0F,0F,00	; CLICK	
	.BYTE	80,47,1D,20,0F6,0AF,0ED
BEEP:	.BYTE	02,02,00,00,0F,0F,0F,32	; DINK
	.BYTE	54,20,32,56,20,3E,25
MIDA:	.BYTE	02,00,00,00,0F,0F,0F,0F8; BEEP1 
	.BYTE	1F,00,0FE,00,00,00,00	
AUP3O:	.BYTE	02,00,00,00,0F,0F,0F,0F8; BEEP2
	.BYTE	1F,02,0FA,00,00,00,00
BELLTN:	.BYTE	02,02,00,00,0F,0F,0F,32	; BELL
	.BYTE	54,20,32,56,20,3E,25
;
;|----------------------------------------------|
;|  ALTERNATE CHARACTER SET TRANSLATION TABLE	|
;|----------------------------------------------|
;
CHRTBL:	.BYTE	40	;0 = STANDARD SET
	.BYTE	00	;1 = FORMS RULING
	.BYTE	80	;2 = GREEK & LANGUAGES
	.BYTE	0C0	;3 = MATH & WORD PROCESSINGŠ;
;|-----------------------------------------------|
;|  KEYCODE TRANSLATION TABLE (WORDSTAR VERSION) |
;|-----------------------------------------------|
;
;	NO CTRL, SHIFT
;
KEYTBL:	.BYTE	08,09,0A,00,00,0D,00,0FE ; BS TAB LF NA NA CR NA LOCK
	.BYTE	20,00,00,1B,01,06,1A,17	 ; SP NA NA ESC LFT RT UP DN
	.BYTE	5E,21,40,23,24,25,26,2A	 ; ^!@#$%&*
	.BYTE	28,29,22,3A,3C,2B,3E,3F  ; ()":<+>?
	.BYTE	7E,41,42,43,44,45,46,47	 ; ~ABCDEFG
	.BYTE	48,49,4A,4B,4C,4D,4E,4F	 ; HIJKLMNO
	.BYTE	50,51,52,53,54,55,56,57	 ; PQRSTUVW
	.BYTE	58,59,5A,7B,7C,7D,5F,07	 ; XYZ{|}_DEL
;
;	CTRL, SHIFT
;
	.BYTE	08,09,0A,00,00,0D,00,0FD ; BS TAB LF NA NA CR NA LOCK
	.BYTE	20,00,00,0FF,93,84,92,83 ; SP NA NA ESC LFT RT UP DN
	.BYTE	1E,85,0C8,0D3,0B3,0B0,0A2,0AB ;^!@#$%&*
	.BYTE	0B6,0A3,27,3B,2C,0C,2E,2F; ()":<+>?	
	.BYTE	00,01,02,03,04,05,06,07	 ; CTRL-~ABCDEFG
	.BYTE	08,09,0A,0B,0C,0D,0E,0F  ; CTRL-HIJKLMNOŠ	.BYTE	10,11,12,13,14,15,16,17  ; CTRL-PQRSTUVW
	.BYTE	18,19,1A,1B,1C,1D,1F,19  ; CTRL-XYZ{|}_DEL
;
;	NO SHIFT OR CTRL
;
	.BYTE	08,09,0A,00,00,0D,00,0FE ; BS TAB LF NA NA CR NA LOCK
	.BYTE	20,00,00,1B,08,0C,0B,0A  ; SP NA NA ESC LFT RT UP DN
	.BYTE	30,31,32,33,34,35,36,37  ; 01234567
	.BYTE	38,39,27,3B,2C,3D,2E,2F  ; 89';,=./
	.BYTE	60,61,62,63,64,65,66,67  ; `abcdefg
	.BYTE	68,69,6A,6B,6C,6D,6E,6F  ; hijklmno
	.BYTE	70,71,72,73,74,75,76,77  ; pqrstuvw
	.BYTE	78,79,7A,5B,5C,5D,2D,7F  ; xyz[\]-DEL
;
;	CTRL, NO SHIFT
;
	.BYTE	0FC,09,0FB,00,00,0D,00,0FD ; BS TAB LF NA NA CR NA LOCK
	.BYTE	20,00,00,0FF,01,06,12,03 ; SP NA NA ESC LFT RT UP DN
	.BYTE	0CE,11,0A,0F,10,0B,16,02 ; 01234567
	.BYTE	0D8,0C9,27,3B,2C,81,2E,2F ; 89';,=./	
	.BYTE	00,01,02,03,04,05,06,07	 ; CTRL-`abcdefg
	.BYTE	08,09,0A,0B,0C,0D,0E,0F	 ; CTRL-hijklmno
	.BYTE	10,11,12,13,14,15,16,17  ; CTRL-pqrstuvw
	.BYTE	18,19,1A,1B,1C,1D,86,14  ; CTRL-xyz[\]-DEL
;
;	KEYPAD TABLE
;
PADTBL:	.BYTE	2A,2C,3D,2E,2F		 ; *,=./
	.BYTE	60,61,62,63,64,65,66,67	 ; `abcdefg
	.BYTE	68,35,31,32,33,30,6E,36  ; h51230n6
	.BYTE	2B,71,72,73,74,34	 ; +qrst4	
;
	.RADIX	10
;
	.PAGE
;
;|------------------------------|
;| ESCAPE SEQUENCE VECTOR TABLE |
;|------------------------------|
;
ESCTBL:	.WORD	PPOINT	; PLOT POINT
	.WORD	PVCTOR	; PLOT VECTOR
	.WORD	BLKDRW	; BLOCK DRAW
	.WORD	CLRGRF	; CLEAR GRAPHICS MEM.
	.WORD	BLKFIL	; BLOCK FILL
	.WORD	SETMSK	; SET MASK FOR BLOCK FILL
	.WORD	DSBGRF	; DISABLE GRAPHICS
	.WORD	ENBGRF	; ENABLE GRAPHICS
	.WORD	PTBRT	; SET TO PLOT BRIGHT
	.WORD	PTDRK	; SET TO PLOT DARK
	.WORD	REDDAT	; READ DATE FROM CLOCK CHIP
	.WORD	CMOSPN	; SET PRINTER BAUD FROM CMOS RAM
	.WORD	CMOSCM	; SET COMM. BAUD FROM CMOS RAM
	.WORD	DRCTMV	; DIRECT CURSOR MOVEMENT
	.WORD	REDTIM	; READ TIME FROM CLOCK CHIP
	.WORD	REDRAM	; READ CMOS RAM
	.WORD	WRTRAM	; WRITE CMOS RAM
	.WORD	UPCUR	; CURSOR UP
	.WORD	DWNCUR	; CURSOR DOWN
	.WORD	RITCUR	; CURSOR RIGHT
	.WORD	CTROL2+4; CURSOR LEFT
	.WORD	NFGESC	; -- NOT USED --
	.WORD	NFGESC	; -- NOT USED --
	.WORD	NFGESC	; -- NOT USED --
	.WORD	HOMCUR	; CURSOR HOME
	.WORD	REVLF	; REVERSE LINE FEED
	.WORD	CLREND	; CLEAR TO END OF ACTIVE REGION
	.WORD	CLRELN	; CLAR TO END OF LINE
	.WORD	INSLIN	; INSERT LINE
	.WORD	DELLIN	; DELETE LINE
	.WORD	SETTAB	; SET TAB
	.WORD	CLRTAB	; CLEAR TAB
	.WORD	DELLCR	; DELETE CHARACTER
	.WORD	INSCON	; INSERT CHAR. MODE ON
	.WORD	EXIT2	; INSERT CHAR. MODE OFF
	.WORD	CHRSIZ	; SELECT CHAR. SIZE
	.WORD	CHRSET	; SELECT CHAR. SET
	.WORD	SELATR	; SELECT CHAR. ATTRIBUTE
	.WORD	SELDIN	; SELECT ALT. LEAD-IN
	.WORD	DSPSND	; SOUND GENERATOR
	.WORD	SETACR	; SET ACTIVE REGION
	.WORD	DRCTMV	; DIRECT CURSOR MOVE
	.WORD	RESPAR	; RESET PARAMETERS
	.WORD	SAVVPR	; SAVE PARAMETERS (SYSTEM USE ONLY)
	.WORD	CLSCRN	; CLEAR SCREEN & RESET PARAMETERS
	.WORD	RCLPAR	; RECALL PARAMETERS (SYSTEM USE ONLY)
	.WORD	WRPOFF	; WORD WRAP OFF
	.WORD	WRPON	; WORD WRAP ON
	.WORD	SETWS	; SET WSFLAG (ON)
	.WORD	CLRWS	; RESET WSFLAG (OFF)
	.WORD	DOSND	; SOUND TONE FROM TONE TABLE
	.WORD	OFFCUR	; CURSOR OFF
	.WORD	ONCUR	; CURSOR ON
;
	.PAGE
;
;|-----------------------|
;|  DSPCYC VECTOR TABLE  |
;|-----------------------|
;
CYCTBL:	.WORD	LINCHK	; LINE NUMBER FOR DIRECT CURSOR
	.WORD	COLCHK	; COLUMN NUMBER FOR  '    '
	.WORD	EXIT2	;-- NOT USED --
	.WORD	TACTCK	; TOP OF ACTIVE REGION
	.WORD	BACTCK	; BOTTOM OF ACTIVE REGION
	.WORD	ATTCHK	; NEW ATTRIBUTE
	.WORD	ALTCHK	; ALTERNATE CHAR. SET
	.WORD	SIZCHK	; NEW SIZE
	.WORD	TABCHK	; NEW TAB
	.WORD	LEDCHK	; SOFT ESCAPE CHAR.
	.WORD	INSCHK	; INSERT MODE ON
	.WORD	GRFCHK	; GET MASK
	.WORD	GRFCK1	; GET X MSB
	.WORD	GRFCK2	; GET X LSB
	.WORD	GRFCK3	; GET Y MSB
	.WORD	GRFCK4	; GET Y LSB
	.WORD	GRFCK5	; GET ADDR. FOR CMOS READ
	.WORD	GRFCK6	; GET ADDR. FOR CMOS WRITE
	.WORD	GRFCK7	; GET DATA FOR CMOS WRITE
	.WORD	GETSND	; GET SOUND BYTES AFTER 1ST ONE
	.WORD	SETSND	; GET 1ST SOUND BYTE
;Š	.PAGE
;
;|------------------------------|
;|    FLOPPY COMMAND TABLES	|
;|------------------------------|
;
;FORMAT...
;	COMMAND INFO
;		NNNNNNNN
;		||||||||
;		||||BYTES TO 765
;		|||0=NO, 1=YES FOR DMA
;		||0=NO, 1=YES FOR INT
;		|0=RD, 1=WR TO DISK
;		0=NO, 1=YES TO READ ST3
;	ADDR TO START DATA XFER (IF NEEDED)
;	BYTE COUNT-1 (IF NEEDED)
;	COMMAND TO 765
;	UNIT # + 4*HEAD
;	CYLINDER
;	HEAD
;	RECORD
;	BYTES/SECTOR
;	SECTORS/TRACK
;	GAP 2 LENGTH
;	DATA LENGTH
;
;-------- FORMAT --------
;
FMTTBL:	.BYTE	76H
FMADDR:	.WORD	FILBUF
FMCNT:	.WORD	40-1
	.BYTE	40H+0DH
FMUNIT:	.BYTE	0
	.BYTE	2
	.BYTE	HSTSPT
	.BYTE	30
	.BYTE	0E5H
;
;-------- RECALIBRATE --------
;
RCLTBL:	.BYTE	22H
	.BYTE	7
RCUNIT:	.BYTE	0
;
;-------- READ OR WRITE --------
;
RWTBL:	.BYTE	39H
RWADDR:	.WORD	HSTBUF
RWCNT:	.WORD	HSTSIZ - 1
RWCMD:	.BYTE	40H+6H
RWUNIT:	.BYTE	0
RWCYL:	.BYTE	0
RWHD:	.BYTE	0
RWREC:	.BYTE	1
	.BYTE	2
	.BYTE	HSTSPT
	.BYTE	15	;GP2
	.BYTE	0FFH
;
;-------- SENSE DRIVE STATUS --------
;
SDSTBL:	.BYTE	82H
	.BYTE	4
SDUNIT:	.BYTE	0
;
;-------- SPECIFY --------
;
SPCTBL:	.BYTE	3
	.BYTE	3
	.BYTE	SRT*16+DHUT
	.BYTE	DHLT*2+ND
;
;-------- SEEK & RECALIBRATE --------
;
SKTBL:	.BYTE	23H
	.BYTE	0FH
SKUNIT: .BYTE	0	;UNIT+HD*4
SKCYL:  .BYTE	0	;NCN
;
	.PAGE
;
VALMOD:	.BYTE	0
	.ASCII	'VALET   VL2'
;		
;	GRAPHICS VARIABLES (INITIALIZED VALUES)
;
MASK:	.BYTE	0FFH	;THESE MUST
MASK2:	.BYTE	00H	;STAY IN
MMASK:	.BYTE	0FFH	;ORDER
CURMSK:	.BLKB	1	;TO HERE
CLFLG:	.BYTE	0FFH
CYC:	.BYTE	0
;
; 	MESSAGES 
;
GOPOS:	.BYTE	ESC,'='	; FOR DIRECT CURSOR MOVE
POSITN:	.BLKB	2	;  IN VALET
;
VALCLN:	.BYTE	ESC,'7',ESC,']'+80H
VALPAR:	.BYTE	ESC,'6',ESC,'[',ESC,'Z',ESC,'c',ESC,'^'		
	.BYTE	ESC,'X',36H,037H,ESC,'U',22H	;CURSOR HOME,REV. VIDEO
	.ASCII	'  TIME    DATE  BRIGHTNESS   VOLUME'
	.ASCII	'    KEY    COMMUNICATIONS   PRINTER'
	.ASCIS	'   BELL   '
NOTSET:	.ASCIS	'  CLOCK NOT SET'
WBINIT:	.BYTE	ESC,'Z',ESC,'J'+80H
WBTRY:	.BYTE	CR,LF
	.ASCIS	'RESET OR ANY KEY TO RETRY'
OPTMSG:	.BYTE	CR,LF
	.ASCIS	'OPTIONS: (R)ETRY,(W)ARM BOOT,(I)GNORE'
VALLER:	.BYTE	1AH	; HOME & CLEAR ACTIVE
	.ASCII	'FATAL'
DERMSG:	.ASCII	' ERROR ON DISK '
DRVNUM:	.BLKB	1
	.ASCIS	':'	
VCRLF:	.BYTE	CR,LF+80H
TERR:	.ASCIS	'NO DISK'
CERR:	.ASCIS	'SYSTEM'
WERR:	.ASCIS	' WRITE'
RERR:	.ASCIS	'  READ'
RLERRş	.ASCIS	'  HOME'
SKERR:	.ASCIS	'  SEEK'
;
OPTV1:	.BYTE	CR,LF
	.ASCIS	'CR TO WARM BOOT'
OPTV2:	.BYTE	CR,LF	
	.ASCIS	'CR TO ABORT'
;
	.LIST
	.IFE	LSTVAR,[
	.XLIST
]
	.PAGEŠ;
;|------------------------------|
;|	VARIABLES & BUFFERS	|
;|------------------------------|
;
;	DISPLAY VARIABLES & BUFFERS
;
;  NEXT 4 ITEMS MUST STAY IN ORDER
;
DSPBFL:	.BLKB	2
DSPBUF: .BLKB	82      ; BUFFER FOR MOVING LINES
BUFPNT:	.BLKB	2	; USED BY SCROLL ROUTINES
BYTBUF:	.BLKB	320-86	; VALET SCREEN SAVE
;
MOVBEG:	.BLKB	2	; USED BY INSDEL
CHRPNT:	.BLKB	1	; CHARACTER POINTER
GRFCMD:	.BLKB	1	; GRAPHICS COMMAND
GDELS:	.BLKB	2	; VECTOR SHORT DELTA
GDELL:	.BLKB	2	; VECTOR LONG DELTA
GRK:	.BLKB	2	; VECTOR ERROR ACCUMULATOR
GRMODE:	.BLKB	1	; VECTOR DIRECTION POINTERS
GRX:	.BLKB	2	; X COORDINATE
GRX1:	.BLKB	2	; VECTOR X START POINT
GRY:	.BLKB	2	; Y COORDINATE
GRY1:	.BLKB	2	; VECTOR Y START POINT
; NEXT 47 BYTES MUST STAY AS A BLOCK W/DSPCYC FIRST
DSPCYC:	.BLKB	1	; DISPLAY CYCLE COUNTER
			;  0 = NORMAL CHAR
			;  1 = ESC PENDING
			;  2 = LINE # PNDG. DIR. CUR.
			;  3 = CHAR # PNDG.  '    '
			;  4 = SCROLL FILL PENDING
			;  5 = LINE # PENDING; TOP ACT.
			;  6 =   '  '    '    BOT. ACT.
			;  7 = ATTRIBUTE PENDING
			;  8 = CHAR. SET PENDING
			;  9 = CHAR. SIZE PENDING
			;  A = NEW TABS PENDING
			;  B = ALT. LEAD IN PENDING
			;  C = INSERT CHAR. PENDING
			;  D = BRIGHTNESS CHAR. PENDING
KEYCNT:	.BLKB	1	; # OF KEYS IN BUFFER
SETFLG:	.BLKB	1	; SETUP MODE FLAG
	.BLKB	1	; ---------- NOT CURRENTLY USED ----------
BRKCNT:	.BLKB	1	; COUNTER FOR BREAK DURATION
;
; NEXT 21 BYTES MUST REMAIN IN THIS ORDER
;
CURCHR:	.BLKB	1	; CURRENT CHARACTER SET
CURATT:	.BLKB	1	; CURRENT ATTRIBUTE CODE
WRPFLG:	.BLKB	1	; WRAP	 0=ON, 0FFH=OFF
CURCTL:	.BLKB	1	; CURSOR 0=ON, 0FFH=OFF
TOPACT:	.BLKB	1	; TOP OF ACTIVE REGION
BOTACT:	.BLKB	1	; BOTTOM OF ACTIVE REGION
MAGACT:	.BLKB	1	; LINES IN ACTIVE REGION-1
LEADIN:	.BLKB	1	; SOFT ESCAPE CHARACTER
CHRADR:	.BLKB	2	; CHARACTER ADDRESS
			;   H=CHAR POSITION (0=LEFT)
			;   L=LINE# (0=TOP, 23=BOTTOM)
LASTAB:	.BLKB	1	; LAST TAB POSITION
TABS:	.BLKB	10 	; TAB KEY
TEMPAR:	.BLKB	21	; SAVE PARAMETERS HERE
TEMLIN:	.BLKB	1	; TEMPORARY STORAGE FOR LINE#
;
; KEYBOARD VARIABLES
;
CTLCOD:	.BLKB	1	; CONTROL KEY CODE
KEYBUF:	.BLKB	KBUFLN	; KEYBOARD BUFFER
KEYPNTş	.BLKB	2	; POINTEŇ TĎ KEYBUF
;
;MISC. VARIABLES
;
LSAVE:	.BLKB	1	; SAVE LSTATE IN VALET
SECCNT:	.BLKB	1	; SECTOR COUNTER FOR WBOOT
SNDADR:	.BLKB	2	; POINTER TO SOUND TABLE
SNDCNTş	.BLKB	±	; COUNTEŇ FOŇ SOUND TABLĹ INPUT
NUMSAV:	.BLKB	1	; SPACE TO SAVE NUMFLG
WSSAVE:	.BLKB	1	; SPACE TO SAVE WSFLAG
LSTATE:	.BLKB	1	; L0-7 STATE
VALPNT:	.BLKB	2	; SAVE SP IN VALET
TEMSTK:	.BLKB	2	; SAVE SP IN SRV60
DSPSTK:	.BLKB	2	; SAVE SP IN DISPLY
OKIFLG:	.BLKB	1	; 0=NAT., <>0 = OKI
TONTYP:	.BLKB	1	; KEYTONE
BRTLEVş	.BLKB	±	; BRIGHTNESÓ LEVEL
CURBEL:	.BLKB	1	; BELL TOGGLE
VOLEVL:	.BLKB	1	; VOLUME LEVEL
SHLOCK:	.BLKB	1	; SHIFT	LOCK
NOKEY:	.BLKB	1	; VALET INHIBIT FLAG
SNDTBL:	.BLKB	15	; SOUND TABLE FOR USER TONES
VALOP:	.BLKB	1	; R/W COMMAND FOR VALET DISK IO
VALCNT:	.BLKB	1	; # OF A.U.'S TO READ IN VALET DISK IO
;
;	GRAPHICS VARIABLES
;
GRX12:	.BLKB	2	
GRY12:	.BLKB	2
STRX1:	.BLKB	1	; USED IN FILL ROUTINE
STRX:	.BLKB	1
PIXBIT:	.BLKB	1
PIXBT2:	.BLKB	1
;
;	FLOPPY VARIABLES
;
;	ALL VARIABLES FROM HERE TO THE END MUST REMAIN AS THEY
;	ARE NOW. THIER RELATIVE POSITIONS MUST NOT CHANGE.
;
MTRCNT:	.BLKB	2	; MOTOR TIMER
RESULT:	.BLKB	1	; # OF BYTES TO GET FROM u765
DSKCMD: .BLKB	1	; DISK COMMAND
unacnt:	.BLKB	1	; unalloc rec cnt
unadsk:	.BLKB	1	; last unalloc disk
unatrk:	.BLKB	2	; last unalloc track
unasec:	.BLKB	1	; last unalloc sector
hmflgs:	.BLKB	ndisk	; home been here before flag
savech:	.BLKB	1
sekdsk:	.BLKB	1	; seek disk number
sektrk:	.BLKB	2	; seek track number
seksec:	.BLKB	1	; seek sector number
hstdsk:	.BLKB	1	; host disk number
hsttrk:	.BLKB	2	; host track number
hstsec:	.BLKB	1	; host sector number
sekhst:	.BLKB	1	; seek shr secshf
hstact:	.BLKB	1	; host active flag
hstwrt:	.BLKB	1	; host written flagŠhsthd:	.BLKB	1	; host hd (side) flag
erflag:	.BLKB	1	; error reporting
rsflag:	.BLKB	1	; read sector flag
readop:	.BLKB	1	; 1 if read operation
wrtype:	.BLKB	1	; write operation type
DMAADR:	.BLKB	2	; CPM DMA ADDRESS
DIRBUF:	.BLKB	128	; SCRATCH DIRECTORY AREA
RECNT:	.BLKB	1	;    RETRY COUNT
ALV0:	.BLKB	DSKSIZ/8+2 ; ALLOCATION VECTORS
CSV0:	.BLKB	DIRENT/4   ; CHECK VECTORS
ALV1:	.BLKB	DSKSIZ/8+2
CSV1:	.BLKB	DIRENT/4
;
;	THE NEXT 9 ITEMS MUST STAY IN THIS ORDER
;
DSKCYC:	.BLKB	1	; DISK	CYCLE
st0:	.BLKB	1	; status 0
st1:	.BLKB	1	; status 1
st2:	.BLKB	1	; status 2
cstat:	.BLKB	1	; cyl at status time
hstat:	.BLKB	1	; head at status time
rstat:	.BLKB	1	; sector at status time
nstat:	.BLKB	1	; # of data bytes at status time
RESNUM:	.BLKB	1	; NUMBER OF RESULT BYTES ACTUALLY READ
;
SAVAUS:	.BLKB	32	; ALLOCATION UNITS FOR VALET.VL2
CURREC:	.BLKB	4      	; FOR RANDOM ACCESS
;
DSKCNT:	.BLKB	1	; DISKOP TIMEOUT COUNTER
OKIBYT:	.BLKB	1	; STORAGE FOR CLOCK
SCNDS:	.BLKB	1	;	'
SECS10:	.BLKB	1	;	'
MINS:	.BLKB	1	; 	'
MINS10:	.BLKB	1	;	'
HRS:	.BLKB	1	;	'
HRS10:	.BLKB	1	;	'
;
hstbuf:	.BLKB	hstsiz	; host buffer
SNDAU:	.BLKB	1
ENDRAM	=	.
;
;   	STACK AREA
;
	.LOC	CCP+3B60H
;
	.BLKB	61
VALSTK:	.BLKB	1
	.BLKB	36
INTSTK:	.BLKB	1
	.BLKB	39
DSPTEM:	.BLKB	1
	.BLKB	20
ENDMRK	=	.
;
	.END
