.TITLE "---- OTRONA 503 SYSTEM MONITOR V[G] ----"
.SBTTL "COPYRIGHT 1983, OTRONA ADVANCED SYSTEMS CORP."
;
;|--------------------------------------|
;|    OTRONA 503 SYSTEM MONITOR V[HX]   |
;|          (FILE MON503.ASM)           |
;|--------------------------------------|
;
;	R.LINGEMANN 08/16/83
;	S.GRAY
;	L.LOVELACE
;
;|-------------------|
;|	 SET-UP	     |
;|-------------------|
;
BASE	=	0
;
	.LOC	BASE
;
STACK	=	0FE00H
;
	.PABS
	.PHEX
;
;	LIST CONTROL
;
	.PRNTX "LIST CONTROL (0=OFF, 1=ON)"
;
LSTDEF	=	\"  DEFINITIONS       "
LSTINI	=	\"  INITIALIZATION    "
LSTMTR	=	\"  MONITOR           "
LSTSUB	=	\"  GP & IO SUBROUTINES "
LSTDSK	=	\"  DISK ROUTINES     "
LSTDSP	=	\"  DISPLAY DRIVER    "
LSTINT	=	\"  INTERRUPT ROUTINES"
LSTTBL	=	\"  TABLES            "
LSTRAM	=	\"  RAM AREA          "
;
;	SELECT DISK CONFIGURATION
;
DBL	=	1	;DENSITY (0=SINGLE, 1=DOUBLE)
FILSIZ	=	(DBL+1)*256
SECS	=	1	;SECTORS (0=9, 1=10)
SIDES	=	1	;SIDES   (0=SINGLE, 1=DOUBLE)
FILBUF	=	0FE00H	; LOCATION OF DISK BUFFER
;
	.IFE	LSTDEF,[
	.XLIST
]
;
;|----------------------|
;|	CONSTANTS	|
;|----------------------|
;
;	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
;
;	I/O PORTS
;
STAT86	=	0B8H	; 8086 PORT STATUS
DATA86	=	0B9H	; 8086 PORT DATA
FPYBCA	=	0E0H	;FLOPPY BASE & CURRENT ADDRESS
FPYBWR	=	0E1H	;FLOPPY BASE & WORD COUNT
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 REQUEST 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 REGISTER
DMAWAM	=	0EFH	;DMA WRITE ALL MASK REG. BITS
DCOMM	=	0F0H	;COMMUNICATIONS PORT DATA
SCOMM	=	0F1H	;COMMUNICATIONS PORT COMMAND/STATUS
DPRTR	=	0F2H	;PRINTER PORT DATA
SPRTR	=	0F3H	;PRINTER PORT COMMAND/STATUS
BAUDC	=	0F4H	;BAUD TIMER FOR COMM PORT
BAUDP	=	0F5H	;BAUD TIMER FOR PRINTER PORT
DSPINT	=	0F6H	;DISPLAY INTERRUPT (60 HZ.)
FPYINT	=	0F7H	;FLOPPY INTERRUPT TIMER
DPIOA	=	0F8H	;PIO PORT A DATA
			;  A0-7 = LATCH DATA OUT
			;	L0 = /MOTOR ON
			;	L1 = MINI/FULL
			;	L2 = /EPROM ENABLE
			;	L3-7 = DISPLAY BRIGHTNESS
			;  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 ADDRESS LOAD
			;	1 = 8910 DATA LOAD
			;	2 = 5832 WRITE
			;	3 = 5832 READ
			;	4 = 5101 WRITE
			;	5 = 5101 READ
			;	6 = LATCH LOAD
			;	7 = NO-OP
			;  B5 = /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
;
;	CONTROL VALUES
;
TIMCW0	=	57H	;TIMER CONTROL BYTE
TIMTC0	=	2	;9600 BAUD
TIMTC1	=	16	;1200 BAUD
LINES	=	24	; # OF LINES IN DISPLAY
RDA	=	1	; RECEIVE DATA AVAIL. 1 = N.F.G
TBE	=	2	; TRANSMIT BUFFER EMPTY 2 = N.F.G.
TSTRAM	=	0F8H	; TEST 8086 RAM
TSTGPO	=	0F9H	; TEST GPIB OUT
TSTGPI	=	0FAH	; TEST GPIB INPUT
TSTSER	=	0FBH	; TEST 8086 SERIAL LOOP
;
;	FLOPPY PARAMETERS
;
HLT	=	8	;HEAD LOAD TIME
HUT	=	0FH	;HEAD UNLOAD TIME
ND	=	0	;DMA MODE
SRT	=	10	;STEP RATE = 12 MS
MTRTIM	=	300	;5S MOTOR TIMEOUT FOR TESTING ONLY
MTRDLY	=	45	;750MS. MOTOR START DELAY
;DISK ERROR CODES
;
;  1 = W765 TIMEOUT IN DISKOP
;  2 = R765 TIMEOUT IN DISKOP
;  3 = DISKOP INTERRUPT TIMEOUT
;
	.LIST
	.IFE	LSTINI,[
	.XLIST
]
;
	.PAGE
;
;|-------------------------|
;|	INITIALIZATION	   |
;|-------------------------|
;
;	VECTORS (USED BY SECONDARY BOOT ROUTINES)
;
	JMP	INIT	;INIT
	JMP	GOMON	;MONITOR
	JMP	DISKOP	;FLOPPY DRIVER
	JMP	DISPLY	;DISPLAY DRIVER
	JMP	ERROR	;DISK ERROR
;
; ------ ADD OTHER VECTORS HERE ------
;
;	SIGN-ON MESSAGE
;
SIGNON:	.BYTE	ESC
       	.ASCII	'JOTRONA ATTACHE [X]'
	.BYTE	CR,LF+80H
;
SIGNLN	=	.-SIGNON
;
;	SET UP ALL I/O VIA TABLE
;
INIT:	DI
	LXI	H,IOTBL	;POINT TO I/O TABLE
..L1:	MOV	A,M
	MOV	C,A	;C=PORT
	INR	A	;JUMP OUT IF DONE
	JRZ	CPUTST
	INX	H	;B=COUNT
	MOV	B,M
	INX	H
..L2:	MOV	A,M	;MANUAL BLOCK OUTPUT
	OUTP	A	;  SO SLOW DEVICES
	INX	H	;  CAN KEEP UP
	DJNZ	..L2
	JMPR	..L1
;
;	TEST CPU REGISTERS
;
CPUTST:	MVI A,0FFH	;MAIN SET
	STC
	STAI
	LDAI
..L1:	MOV	B,A
	MOV	C,B
	MOV	D,C
	MOV	E,D
	MOV	L,E
	MOV	H,L
	EXAF		;ALTERNATE SET
	MOV	A,H
	EXX
	MOV	B,A
	MOV	C,B
	MOV	D,C
	MOV	E,D
	MOV	L,E
	MOV	H,L
	EXAF
	MOV	A,H
	JRNC	CPU1
	CMA
	ANA	A	;FF PATTERN OK?
	JRZ	..L1	;--IF SO, TRY ZEROES
CPUERR:	HLT		;--ELSE ERROR
CPU1:	JRNZ	CPUERR
	ORA	A	;ERROR IF NOT ZERO
	JRNZ	CPUERR
	LXI	X,0FFFFH ;INDEX & SP REGISTERS
	SPIX
	DAD	SP
	XCHG
	LXI	Y,0FFFFH
	SPIY
	DAD	SP
	DAD	D
	JRNC	CPUERR
	INX	H
	LXI	X,0
	SPIX
	DAD	SP
	XCHG
	LXI	Y,0
	SPIY
	DAD	SP
	DAD	D
	INX	H
	MOV	A,H
	XRA	L
	JRNZ	CPUERR
;
;	TEST CPU FLAGS
;
	MVI	A,40H
	ADD	A	;SET V & S, CLEAR C & Z
	JRZ	CPUERR
	JRC	CPUERR
	JP	CPUERR
	JPO	CPUERR
	ADD	A	;COMPLEMENT C, S, & Z
	JRNZ	CPUERR
	JRNC	CPUERR
	JM	CPUERR
	ORI	1	;COMPLEMENT V
	JPE	CPUERR
	MVI	A,9	;CHECK H & N FLAGS
	ADI	1
	DAA
	CPI	10H
	JRNZ	CPUERR
	SBI	1
	DAA
	CPI	9
	JRNZ	CPUERR
;
;	MAP MEMORY
;
	LXI	SP,STACK
	LXI	H,STDMAP
	LXI	X,.+7
	JMP	MAP
;
;	TEST START BLOCK (RAM FD00-FDFF)
;	 & SET TO ZERO
;
RAMCHK:	LXI	H,0FD00H
..L1:	MVI	C,0FFH
..L2:	MOV	M,C
	MOV	A,C
	XRA	M
	JNZ	MEMERR
	SLAR	C
	JRC	..L2
	INR	L
	JRNZ	..L1
;
;	SET INITIAL VALUES
;
	CMA
	STA	SHLOCK
	MVI	A,0C0H	;SET LSTATE
	STA	LSTATE
;
;	REINITIALIZE DISPLAY IF 50 HZ
;
	MVI	D,2
	CALL	RDCMOS
	MOV	A,C
	CPI	9
	JRNZ	..J0
	MVI	A,0A4H
	OUT	SDSPY
	MVI	A,29
	OUT	DDSPY
	MVI	A,0A5H
	OUT	SDSPY
	MVI	A,37
	OUT	DDSPY
;
;	SEE IF 8086 PORT O.K.
;
..J0:	MVI	A,1	; SET UP PORT
	OUT	STAT86
	XTHL		; WASTE TIME
	XTHL
	XRA	A	; CLEAR PORT
	OUT	STAT86
	IN	DATA86
;
	LXI	B,250*256 ; SEE IF 8086 IS TALKING
..L0:	IN	STAT86
	ANI	RDA	; IF NO BYTE
	JRNZ	..J1	;  THEN ..J1
	IN	DATA86	; ELSE GET BYTE
	SUI	0F0H	; IF <> 0F0H
	JRZ	..J2	;  THEN KEEP TRYING
;
..J1:	DCR	C	; DECREMENT LOOP
	JRNZ	..L0
	DCR	B	; IF LOOP NOT DONE
	JRNZ	..L0	;  THEN ..L0
;
	MVI	A,0FFH	; ELSE 8086 NOT THERE
..J2:	STA	FLAG86	; 0 = O.K., <> 0 = N.F.G.
;
;	SET UP INTERRUPT SYSTEM
;
	MVI A,V60HZ/256	;SET TO USE INTERNAL DISPLAY
	STAI		;  & SET VECTOR AREA
	IM2		;MODE 2
	EI		;INTERRUPTS ON
;
;	SIGN ON
;
	LXI	H,SIGNON
	CALL	MSSG
	JMP	BOOT
;
	.LIST
	.IFE	LSTMTR,[
	.XLIST
]
;
	.PAGE
;
;|----------------------|
;|	 MONITOR 	|
;|----------------------|
;
;	COMMANDS
;
;	BS	=	OPEN, DECREMENT, CLOSE
;	CR	=	CLOSE
;	CTLR/LF =	GOTO TERMINAL MODE
;	LF	=	CLOSE, INCREMENT, OPEN
;	/	=	OPEN
;	SPACE	=	MOVE HL TO DE, CLEAR HL
;	G	=	DISPLAY TEST
;	H	=	ALPHA MEMORY TEST
;	I	=	JUMP
;	K	=	KEYBOARD ECHO
;	L	=	LOOP MODIFIER
;	M	=	MEMORY MAP
;	N	=	NOT USED
;	O	=	OUTPUT TO PORT
;	P	=	FORMAT DISK
;	Q	=	CMOS RAM TEST
;	R	=	RAM TEST
;	S	=	SET BAUD AND PORT
;	T	=	CLOCK TEST
;	U	=	UNIFIED TEST
;	V	=	READ FROM FLOPPY
;	W	=	WRITE TO FLOPPY
;	X	=	TRANSMIT BLOCK OF DATA
;	Y	=	RECEIVE BLOCK OF DATA
;	Z	=	FLOPPY R/W TEST
;	[	=	8086 RAM TEST
;	\	=	8087 TEST
;	]	=	8086 SCC TEST
;	)	=	GPIB CONTROLLER TEST
;	(	=	GPIB TALKER/LISTENER TEST
;	#	=	8086 DEBUGGER
;
	.PAGE
;
;	SEND CRLF & @
;
MNTR:	MVI	C,CR
	CALL	CO
	MVI	C,LF
	CALL	CO
	MVI	C,'@'
	CALL	CO
	LXI	D,0
	SDED	SAVDE
MNTR2:	MVI	H,0	;CLEAR B,L,H
	MOV	L,H
	MOV	B,H
;
;	GET CHAR, MAKE UPPER CASE
;
GET:	CALL	ABTTST	;CHECK FOR ABORT
	LDA	FLGCMD	;MACRO IN PROGRESS?
	ORA	A
	JRZ	..J1
	PUSH	H
	LHLD	CMDPTR	;YES, PROCESS MACRO
	MOV	A,M
	INX	H
	SHLD	CMDPTR
	POP	H
	ORA	A	;--ZERO IS END OF MACRO
	JRNZ	..J4
	STA	FLGCMD
..J1:	LDA	FLGLOP	;LOOP IN PROGRESS?
	CPI	80H
	JRNZ	..J2
	LXI	H,CMDSTT ;--YES, RESET U POINTERS
	SHLD	CMDPTR
	LHLD	SAVHL2	;--& RESTORE FOR NEXT CYCLE
	LDED	SAVDE2
	LDA	SVCMD2
	JMPR	..J4
;
..J2:	CALL	CIKIN
..J4:	BIT	6,A	;MAKE UPPER CASE
	JRZ	ECHO
	RES	5,A
ECHO:	MOV	C,A
	CALL	CO
	STA	SAVCMD
;
	.PAGE
;
;	BS - CLOSE, DECREMENT, AND OPEN
;
CBS:	CPI	BS
	JRNZ	CCR
	XCHG
	XRA	A	;IF DATA FLAG, SAVE NEW DATA
	ORA	B
	JRZ	..J1
	MOV	M,E
..J1:	DCX	H
	JMPR	LFRET
;
;	CR - CLOSE LOCATION
;
CCR:	CPI	CR
	JRNZ	CESC
	XRA	A
	ORA	B
	JZ	GOMON
	XCHG
	MOV	M,E
	JMP	GOMON
;
;	CTRL/LF - RETURN TO TERMINAL MODE
;
CESC:	CPI	86H
	JZ	GOTERM
;
;	LF - CLOSE, INCREMENT, AND OPEN
;
CLF:	CPI	LF
	JRNZ	CSLASH
	XCHG
	XRA	A	;IF DATA FLAG, SAVE NEW DATA
	ORA	B
	JRZ	..J1
	MOV	M,E
..J1:	INX	H	;INCREMENT ADDRESS
LFRET:	MVI	C,CR	;CRLF
	CALL	CO
	CALL	DSH	;DISPLAY NEW ADDRESS
	MOV	A,H
	MOV	H,L
	MOV	L,A
	CALL 	DSH
	MOV	A,L
	MOV	L,H
	MOV	H,A
	MVI	A,'/'	;FAKE A SLASH
	JMPR 	ECHO
;
;	/ - OPEN AND DISPLAY
;
CSLASH:	CPI	'/'
	JRNZ	CSPC
SLASH:	MVI	B,0	;CLEAR DATA FLAG
	MOV	D,H	;SAVE IN D-E
	MOV	E,L
	MOV	H,M	;GET DATA
	CALL	DSH
	MVI	C,SPC
	CALL	CO
	MVI	H,0	;CLEAR HL
	MOV	L,H
	JMP	GET
;
;	SPACE - SAVE HL VALUE IN DE, CLEAR HL
;
CSPC:	CPI	SPC
	JRNZ	CGRAPH
	SHLD	SAVDE
	XCHG
	JMP	MNTR2
;
;	G - PRESENT DISPLAY TEST PATTERN
;	& PROVIDE CLOCK SET-UP OUTPUT
;
CGRAPH:	CPI	'G'
	JRNZ	CALPHA
;
;	DISPLAY TEST PATTERN
;
	MVI	C,1EH	;HOME
	CALL	DISPLY
	LXI	D,2175	;SET COUNT
	MVI	C,'+'
..L1:	CALL	DISPLY	;SEND A SCREENFUL
	DCR	E
	JRNZ	..L1
	DCR	D
	JRNZ	..L1
;
;	CLOCK SET-UP
;
	CALL	CLKID	;WHICH CLOCK
	BIT	7,D
	JRZ	..J1
	MVI	D,0CFH	;OKI, HOLD 1024 HZ
	CALL	RDCMOS	;  ON PIN 9
	MVI	A,88H
	OUT	DPIOB
..L2:	IN	DPIOB	;WAIT FOR KEY WITH
	BIT	6,A	;  INTERRUPT OFF
	JRZ	..L2
	EI
	JMP	ABORT
..J1:	MVI	D,4FH	;NATIONAL, SET 2 HZ
	CALL	RDCLK	;  ON PIN 13
	EI
	CALL	ABTTST	;WAIT FOR ABORT
	JMPR	..J1
;
;	H - TEST ALPHANUMERIC DISPLAY MEMORY
;
CALPHA:	CPI	'H'
	JNZ	CIN
;
	LDA	FLAG86	; IF NO 8086 BOARD
	ORA	A
	JRNZ	..JE	; THEN ..JE
	MVI	A,0FDH	; ELSE TURN ON HI-RES GRAPHICS
	CALL	OUT86
	CALL	IN86
	CALL	IN86
;
..JE:	MVI	E,0
..L3:	MVI	C,DDSPY	;C = I/O POINTER
	MVI	D,80H	;TEST PATTERN
	MOV	A,E
	OUT	SDSPY	;LINE & FRAME
	MVI	B,0	;CHAR POS. 0
;
..L5:	INP	H	;GET CHARACTER
	OUTP	D	;SEND TEST PATTERN
	INP	A	;GET DATA BACK
	OUTP	H	;RESTORE CHARACTER
	CMP	D
	JRNZ	..JF
;
	LDA	FLAG86
	ORA	A	; IF NO 8086
	JRNZ	..J0	;  THEN ..J0
;
	MOV	A,E	; ELSE
	ANI	0E0H
	CPI	90H	; IF NOT TESTING GRAPHICS
	JRNC	..J0	;  THEN ..J0
	MVI	A,80H	; ELSE TEST ODD SCAN OF GRAPHICS
	XRA	B
	MOV	B,A
	ANI	80H	; IF ALREADY TESTED
	JRZ	..J0	;  THEN ..J0
	JMPR	..L5	; ELSE TEST ODD SACN
;
;	REPORT FIRST ERROR OF EACH FRAME
;
..JF:	XRA	D	;D = DATA
	MOV	D,A
	MOV	A,E
	ANI	1FH
	MOV	H,A	;H = LINE
	MOV	A,E
	ANI	0E0H
	MOV	E,A	;E = FRAME
	MOV	L,B	;L = CHAR. POS.
	CALL	DSDATA
	JMPR	..J1
;
;	ROTATE PATTERN
;
..J0:	RRCR	D
	JRNC	..L5
	INR	B	;LINE DONE?
	MOV	A,B
	CPI	80
	JRNZ	..L5
	INR	E	; FRAME DONE?
;
	LDA	FLAG86
	INR	A	;  FLAG86 = 0 OR 0FFH
	ADI	LINES	; A = 24 OR 25
	MOV	C,A
	MOV	A,E
	ANI	1FH
	CMP	C
	JRNZ	..L3
;
;	CHECK FOR NEXT FRAME
;
..J1:	MOV	A,E
	ANI	0E0H
..J2:	ADI	20H	;SET UP FOR NEXT BLOCK
	CPI	0A0H	; SKIP A0 RAM SEGMENT
	JRZ	..J2
	MOV	E,A
	ORA	A	; IF <> 0
	JRNZ	..L3	;  THEN DO NEXT
;
	LDA	FLAG86	; ELSE IF NO 8086 BOARD
	ORA	A
	JNZ	LOPTST	;  THEN EXIT
	MVI	B,0FEH	; ELSE TURN OFF
	JMP	DO86	;  HI-RES GRAPHICS
;
;	I - INPUT
;	FORMAT NNI WHERE NN IS THE PORT NUMBER
;
CIN:	CPI	'I'
	JRNZ	CJUMP
	MOV	C,L
	INP	H
	CALL	DSH
	JMP	LOPTST
;
;	J - JUMP AND EXECUTE (RETURNS TO MONITOR)
;
CJUMP:	CPI 	'J'
	JRNZ	CKYBD
	LXI	D,MNTR
	PUSH	D
	PCHL
;
;	K - KEYBOARD INPUT TO 500 DISPLAY
;	 ^ GETS BACK TO MONITOR
;
CKYBD:	CPI	'K'
	JRNZ	CLOOP
..L1:	CALL	CIKIN
	CPI	'^'
	JZ	GOMON
	MOV	C,A
	CALL	DISPLY
	MOV	H,A
	CALL	DSH
	CALL	SPACE
	JMPR	..L1
;
;	L - LOOP MODIFIER
;
CLOOP:	CPI	'L'
	JRNZ	CMAP
	MVI	A,0FFH
	STA	FLGLOP
	JMP	GOMON
;
;	M - MEMORY MAPPING TEST
;
CMAP:	CPI	'M'
	JRNZ	CN
	DI
	LXI	H,REVMAP ;REVERSE MAP
	LXI	X,.+7
	JMP	MAP
	LXI	H,0	;WRITE PATTERN
	MVI	B,7
..L1:	MOV	M,B
	MOV	A,H
	ADI	20H
	MOV	H,A
	DJNZ	..L1
	LXI	H,STDMAP ;RESTORE MAP
	LXI	X,.+7
	JMP	MAP
	EI
..J1:	LXI	H,2000H	;COMPARE
	MVI	B,1
..L2:	MOV	A,M
	CMP	B
	JRZ	..J2
	MOV	D,A	;PRINT ANY ERRORS
	MOV	A,H
	ORI	'0'
	MOV	C,A
	CALL	CO
	MOV	E,H
	MOV	H,D
	CALL	DSH
	MOV	H,E
..J2:	INR	B
	MOV	A,H
	ADI	20H
	MOV	H,A
	JRNZ	..L2
	JMP	LOPTST
;
;	N - 8086 UNIFIED TEST
;	    (8087 & RAM)
;
CN:	CPI	'N'
	JRNZ	COUT
	MVI	B,0F8H
	JMP	LOOP86
;
;	O - OUTPUT
; 	 FORMAT NNMMO WHERE NN IS THE PORT NUMBER
; 	 AND MM IS THE DATA TO SEND OUT
;
COUT:	CPI	'O'
	JRNZ	CP
	MOV	C,H
	OUTP	L
	JMP	LOPTST
;
;	P - FORMAT THE DISK IN A
; 	 SDP WHERE S=1 FOR 96TPI, ELSE 0
; 	 D=0 OR 1 CORRESPONDING TO DRIVE #
;
CP:	CPI	'P'
	JRNZ	CCMOS
	CALL	SELFMT
	JMP	GOMON
;
;	Q - CMOS RAM TEST (NON-DESTRUCTIVE)
;
CCMOS:	CPI	'Q'
	JNZ	CRAM
	MVI	C,0
..L1:	CALL	RDCMOS	;D=LOC CNTR, E=OUT CODE
	MOV	L,C
	MVI	B,0
..L2:	MOV	C,B	;WRITE PATTERN
	CALL	WRCMOS
	CALL	RDCMOS	;READ BACK
	MOV	H,C	;RESTORE
	MOV	C,L
	CALL	WRCMOS
	EI
	MOV	A,H
	ANI	0FH
	XRA	B
	JRNZ	..E1	;JUMP OUT IF ERROR
	INR	B	;LOOP ON ALL PATTERNS
	MOV	A,B
	CPI	16
	JRNZ	..L2
	INR	D	;LOOP ON ALL ADDRESSES
	MOV	A,D
	CPI	64
	JRNZ	..L1
	JMPR	..E2
;
;	ERROR REPORT
;
..E1:	MOV	H,D	;D=ADDRESS
	MOV	L,A	;E=ERROR MASK
	CALL	SPACE
	CALL	DSADDR
..E2:	JMP	LOPTST	;EXIT
;
;	R - RAM TEST
;	LNR WHERE N IS THE 16K BLOCK TO TEST (0-3)
;	& L WILL CAUSE LOOPING ON A WRITE TO THE
;	FIRST ERROR LOCATION
;
CRAM:	CPI	'R'
	JNZ	CSET
;
;	SELECT SEGMENT TO TEST
;
	DI
	MOV	A,L	;BLOCK 0 ?
	ANI	3
	MOV	A,L
	JRNZ	..J0
	LXI	H,0FD00H ;--IF SO, SAVE DATA IN BLK 3
	LXI	D,09D00H
	LXI	B,100H
	LDIR
..J0:	LXI	H,TBLMAP ; MAP TEST BLOCK TO BLK 2
	MOV	D,A
	ANI	3
	RLC
	RLC
	MOV	C,A
	MVI	B,0
	DAD	B
	LXI	X,.+7
	JMP	MAP
	EI
;
;	FILL RAM WITH THE PATTERN
;
	MVI	B,9	; MAX ERROR COUNT
	MVI	E,0	; INITIALIZE PATTERN
RL1:	LXI	H,8000H ; SET START ADDR
..L0:	MOV	A,L	; GET LOW ADDR
	XRA	H	; XOR WITH HIGH ADDR
	XRA	E	; XOR WITH MODIFIER
	MOV	M,A	; STORE IT
	INX	H	; LOOP TILL DONE
	MOV	A,H
	CPI	0C0H
	JRNZ	..L0
;
	DI		; 68 mS DELAY
	MVI	H,0E0H
..L1:	INX	H
	MOV	A,H
	ORA	L
	JRNZ	..L1
	EI
;
;	TEST AGAINST PATTERN
;
	MVI	H,080H ;RECONSTRUCT PATTERN
RL4:	MOV	A,L
	XRA	H
	XRA	E
	XRA	M	;COMPARE WITH PATTERN
	JRNZ	MEMERR	;REPORT IF ERROR
RL5:	INX	H	;ELSE LOOP TILL DONE
	MOV	A,H
	CPI	0C0H
	JRNZ	RL4
	CALL	KEYSTS	; CHECK FO ABORT
	JRNZ	RJ4
;
RAMINR:	INR	E	; INCREMENT MODIFIER
	JRNZ	RL1
	JMPR	RJ4
;
;	ERROR REPORT
;
MEMERR:	EXAF		;SAVE ERRORS
	MVI	C,SPC
	CALL	CO
	RES	7,H
	CALL	DSH
	SET	7,H
	MOV	A,H	;SAVE H
	MOV	H,L
	MOV	L,A
	CALL	DSH
	MVI	C,'-'
	CALL	CO
	MOV	A,H
	EXAF		;SHOW PATTERN
	MOV	H,A
	CALL	DSH
	MOV	H,L
	EXAF
	MOV	L,A
	BIT	4,D	;LOOP ON READ AT FAILURE ?
	JRZ	..J1
	MOV	M,A	;--YES, WRITE IN A LOOP
..J1:	DJNZ	RL5	;ERROR COUNTER
;
;	RESTORE MAP, VARIABLES, & INTERRUPT SYSTEM
;
RJ4:	DI		;ELSE, RESTORE INT & REMAP
	LXI	H,STDMAP
	LXI	X,.+7
	JMP	MAP
	MOV	A,D
	ANI	3
	JRNZ	..J2
	LXI	H,09D00H  ;RESTORE VARIABLES
	LXI	D,0FD00H
	LXI	B,100H
	LDIR
..J2:	EI
	JMPR	CTIM1
;
;	S - SET BAUD & SELECT PORTS FOR ERROR REPORTING
;
CSET:	CPI	'S'
	JRNZ	CTIMER
	MOV	A,L
	STA	OUTSEL
	MOV	A,H	;SET UP COMM BAUD
	MVI	C,BAUDC
	CALL	..S0
	MOV	A,H	;SET UP PRTR BAUD
	RRC
	RRC
	RRC
	RRC
	MVI	C,BAUDP
	CALL	..S0
	JMP	GOMON
;
..S0:	ANI	0FH	;SUBROUTINE TO SET BAUD
	RZ
	PUSH	H
	LXI	H,TBLBAD-1
	MVI	D,0
	MOV	E,A
	DAD	D
	MVI	B,57H
	OUTP	B
	OUTI
	POP	H
	RET
;
;	T - REAL TIME CLOCK TEST
;
	PUSH	H
	LXI	H,TBLBAD-1
	MVI	D,0
	MOV	E,A
	DAD	D
	MVI	B,57H
	OUTP	B
	OUTI
	POP	H
	RET
;
;	T - REAL TIME CLOCK TEST
;
CTIMER:	CPI	'T'
	JRNZ	CU
	CALL	CLKID	;WHICH CLOCK
	CALL	RDCLK	;GET SECONDS
	MOV	H,C
	MVI	B,125	;DELAY 2 SEC.
	CALL	DELAY
	CALL	RDCLK	;READ SECONDS AGAIN
	EI
	MOV	A,C
	CPI	0FH	;FAIL IF F
	JRZ	..J0
	CMP	H
..J0:	JZ	QERR	;FAIL IF VALUE NOT CHANGED
CTIM1:	JMP	LOPTST	;ELSE GO TO MONITOR
;
;	U - TYPE A UNITED SET OF TESTS
;	FORMAT UCCCCC...C RET
;	WHERE C IS A COMMAND AND
;	RET WILL START THE SEQUENCE
;	U RET WILL RUN AA PREDETERMINED
;	STANDARD TEST SEQUENCE (SEE ..T1)
;
CU:	CPI	'U'
	JRNZ	CV
	LDA	FLGLOP
	CPI	80H
	JRNZ	..J0
	LHLD	CMDSTT
	JMPR	..J3
..J0:	LXI	H,CMDBUF ;POINT TO CMMD BFR
	PUSH	H
	SHLD	CMDPTR
..L0:	MVI	M,0	; GET COMMANDS
	CALL	CIKIN
	MOV	C,A
	CALL	CO
	CPI	CR	; CR?
	JRZ	..J1
	MOV	M,A	;--NO, SAVE COMMAND
	INX	H
	JMPR	..L0
..J1:	POP	D	;YES, COMMAND STRING?
	ANA	A
	DSBC	D
	MOV	A,H
	ORA	L
	JRNZ	..J2
	LXI	D,TCMD	;IF NOT, USE STANDARD
..J2:	XCHG
	SHLD	CMDSTT
..J3:	SHLD	CMDPTR
	MVI	A,0FFH
	STA	FLGCMD
	JMPR	CTIM1
;
;	V - READ A FLOPPY SECTOR TO 8C00H
;	 FORMAT CCHSV WHERE CC IS THE
;	 CYLINDER, H IS SIZE, HEAD
;	 & DRIVE, & S IS SECTOR
;
;	HHHH
;	|| |
;	|| DRIVE
;	|HEAD
;	1=96 TPI
;
CV: 	CPI	'V'
	JRNZ	CWR
	LXI	X,ERROR
        CALL	FPREAD
CV1:	LDA	ST0
	ANI	0C0H
	CNZ	FPER
	JMPR	CTIM1
;
;	W - WRITE TO FLOPPY, FORMAT SAME AS
;	 U COMMAND
;
CWR:	CPI	'W'
	JRNZ	CXMT
	LXI	X,ERROR
	CALL	FPWRIT
	JMPR	CV1
;
;	X - TRANSMIT DATA TO ANOTHER SYSTEM
; 	 THROUGH PORTS SELECTED BY PREVIOUS
; 	 S COMMAND, FORMAT NNNN MMMMX
; 	 WHERE NNNN IS THE NUMBER OF BYTES TO
; 	 TRANSFER (IN HEX) AND MMMM IS THE
; 	 START OF THE DATA AREA TO TRANSMIT
; 	 FROM. THE FORMAT OF THE DATA IS AS
; 	 FOLLOWS:
;
;	CR
;	NN
;	NN
;	.
;	.
;	NN
;	CR
;
;  WHERE NN ARE TWO CHARACTERS FOR EACH
;  DATA BYTE IN PSUEDO HEX (0,1,2,3,4,5,
;  6,7,8,9,:,;,<,=,>,?) WITH MSD SENT
;  FIRST
;
CXMT:	CPI	'X'
	JRNZ	CY
	MVI	C,CR	;SEND LEADING CR
	CALL	CO1
..L0:	MOV	A,M	;SEND A BYTE
	RRC
	RRC
	RRC
	RRC
	ANI	0FH
	ORI	'0'
	MOV	C,A
	CALL	CO1
	MOV	A,M
	ANI	0FH
	ORI	'0'
	MOV	C,A
	CALL	CO1
	DCX	D	;DECREMENT COUNT
	INX	H	;INCREMENT ADDRESS
	MOV	A,D
	ORA	E
	JRNZ	..L0	;LOOP IF NOT DONE
	MVI	C,CR	;ELSE SEND FINAL CR
	CALL	CO1
	JMP	LOPTST	;AND LEAVE
;
;	Y - RECEIVE DATA FROM ANOTHER SYSTEM
; 	 THROUGH PRTR PORT, FORMAT NNNNY WHERE
; 	 NNNN IS THE STARTING ADDRESS OF THE
; 	 LOAD AREA. SEE X COMMAND FOR DATA
; 	 FORMAT
;
CY:	CPI	'Y'
	JRNZ	CZ
..L0:	CALL	CIPI	;WAIT FOR CR
	CPI	CR
	JRNZ	..L0
..L1:	CALL	CIPI	;TAKE DATA
	CPI	CR	;DONE IF CR
	JZ	LOPTST
	ANI	0FH	;ELSE STORE IT
	RLC
	RLC
	RLC
	RLC
	MOV	D,A
	CALL	CIPI
	ANI	0FH
	ORA	D
	MOV	M,A
	INX	H
	JMPR	..L1
;
;	Z - FLOPPY SPIRAL R/W TEST
;
CZ:	CPI	'Z'
	JNZ	CLBRK
;
;	GET PARAMETERS & FORMAT
;
	CALL	SELFMT
;
;	SET UP COUNTERS & BUFFER
;
	XRA	A
	STA	ERRCNT
	RES	6,L
..L0:	MOV	A,L	;SET SECTOR 1
	ANI	0D0H
	INR	A
	MOV	L,A
..L1:	PUSH	H	;LOAD FILE BUFFER
	LXI	H,FILBUF ; WITH DBE6 CODE
	LXI	B,FILSIZ
..L2:	MVI	M,0DBH
	CCI
	MVI	M,0E6H
	CCI
	JPE	..L2
	POP	H
;
;	WRITE 1 SECTOR ON EACH TRACK
;
..L3:	MVI	H,40	;SET MAXIMUM TRACK
	BIT	6,L	;48 TPI, SIDE 0: 40
	JRZ	..J0
	MVI	H,36	;48 TPI, SIDE 1: 36
..J0:	BIT	7,L
	JRZ	..L4
	MVI	H,80	;96 TPI, SIDE 0: 80
	BIT	6,L
	JRZ	..L4
	MVI	H,78	;96 TPI, SIDE 1: 72
..L4:	DCR	H
	CALL	ABTTST
	LXI	X,ERROR
	CALL	FPWRIT	;WRITE
	LDA	ST0	;CHECK & REPORT ERRORS
	ANI	0C0H
	CNZ	FPER
	MOV	A,H
	ORA	A
	JRNZ	..L4
;
;	READ & COMPARE ALL TRACKS
;
..L5:	PUSH	H
	CALL	ABTTST
	LXI	X,ERROR
	CALL	FPREAD	;READ
	LDA	ST0	;CHECK & REPORT FLOPPY ERRORS
	ANI	0C0H
	CNZ	FPER
	LXI	H,FILBUF ;REPORT RAM COMPARE ERRORS
	LXI	B,FILSIZ
..L6:	MVI	A,0DBH
	CCI
	JRNZ	..J1
	MVI	A,0E6H
	CCI
	JRNZ	..J1
	JPE	..L6
	POP	H
	JMPR	..J2
..J1:	POP	H	;RAM ERROR REPORT
	LDA	ST0
	ANI	0C0H
	STA	ST0
	STA	ST1
	CZ	FPER
;
;	CHECK FOR LAST TRACK
;
..J2:	INR	H
	MOV	A,H
	CPI	80
	JRZ	..J4
	CPI	78	;SIDE 2?
	JRNZ	..J3
	BIT	6,L
	JRNZ	..J4
..J3:	BIT	7,L	;48 TPI?
	JRNZ	..L5
	CPI	40
	JRZ	..J4
	CPI	36
	JRNZ	..L5
	BIT	6,L	;SIDE 2?
	JRZ	..L5
;
..J4:	INR	L	; DO NEXT SECTOR
	MOV	A,L
	ANI	0FH
	CPI	11
	JNZ	..L1
;
	BIT	6,L	; DO NEXT SIDE
	SET	6,L
	JZ	..L0
	JMPR	LOPTST
;
;	[ - 8:16 RAM TEST
;
CLBRK:	CPI	'['
	JRNZ	CKMAT
	MVI	B,0F9H
	JMPR	LOOP86
;
;	\ - 8:16 8087 TEST
;
CKMAT:	CPI	'\'
	JRNZ	SER86
	MVI	B,0FAH
	JMPR	LOOP86
;
;	] - 8:16 SERIAL TEST
;
SER86:	CPI	']'
	JRNZ	GPIBTK
	MVI	B,0FCH
	JMPR	LOOP86
;
;	) - 8:16 GPIB START AS CONTROLLER
;
GPIBTK:	CPI	')'
	JRNZ	GPIBLS
	MVI	B,0FBH
	JMPR	LOOP86
;
;	( - 8:16 GPIB START AS LISTENER
;
GPIBLS:	CPI	'('
	JRNZ	MON86
	MVI	B,0FFH
	JMPR	LOOP86
;
;	# - GOTO 8086 MONITOR
;
MON86:	CPI	'#'
	JRNZ	NUM
	LDA	FLAG86
	ORA	A
	JRNZ	NO86
	MVI	A,0F1H
	CALL	OUT86
..L0:	CALL	IN86
	ORA	A
	JRZ	END86
	CPI	1
	JRNZ	..J0
	CALL	CIKIN
	CALL	OUT86
	JMPR	..L0
;
..J0:	MOV	C,A
	CALL	CO
	JMPR	..L0
;
LOOP86:	LDA	FLAG86
	ORA	A
	JRNZ	NO86
DO86:	MOV	A,B
	CALL	OUT86
..L1:	CALL	IN86
	ORA	A
	JRZ	END86
	MOV	C,A
	CALL	CO
	JMPR	..L1
;
END86:	CALL	IN86
	JMPR	LOPTST
;
NO86:	CALL	SPACE
	MVI	C,'x'
	CALL	CO
	JMPR	LOPTST
;
	.PAGE
;
;	SPECIAL MONITOR EXITS
;
LOPTST:	LDA	FLGLOP
	ORA	A
	JRZ	GOMON
	CPI	80H
	JRZ	GOMON
	MVI	A,80H
	STA	FLGLOP
	LXI	H,SAVDE
	LXI	D,SAVDE2
	LXI	B,5
	LDIR
	JMPR	GOMON
;
;	0-F - SHIFT A NUMBER INTO HL
;
NUM:	SUI	'0'	;CONVERT TO HEX
	JRC	..J2
	CPI	10
	CMC
	JM	..J1
	CPI	11H
	SUI	7
	CPI	16
	CMC
..J1:	JRC	..J2	;SKIP OUT IF INVALID
	DAD	H	;ELSE SHIFT INTO H
	DAD	H
	DAD	H
	DAD	H
	ORA	L
	MOV	L,A
	INR	B	;SET DATA FLAG
	SHLD	SAVHL
	SDED	SAVDE
..J2:	JMP	GET
;
;	'?' ERROR
;
QERR:	MVI	C,'?'
	CALL	CO
	JMPR	GOMON
;
;	TEST FOR ABORT FROM CONSOLE
;
ABTTST:	CALL	KEYSTS
	RZ
;
ABORT:	CALL	CIKIN
	XRA	A
	STA	FLGLOP
	STA	FLGCMD
GOMON:	LXI	SP,STACK
	JMP	MNTR
;
	.LIST
	.IFE	LSTSUB,[
	.XLIST
]
;
.PAGE
;
;|------------------------------|
;| 	GENERAL SUBROUTINES	|
;|------------------------------|
;
;	GENERAL DISPLAY ROUTINES
;
;	RETURN ACCESS CODE FOR SECONDS OF THE
;	APPROPRIATE CLOCK CHIP. SET UP NATIONAL
;
CLKID:	MVI	C,9H	;SET NATIONAL INTERRUPT
	MVI	D,4FH
	CALL	WRCMOS
	CALL	RDCLK	;READ BACK
	MOV	H,A	;SAVE SECONDS ADDRESS
	MOV	A,C
	CPI	0FH
	JRZ	..J1	;JUMP IF OKI
	MVI	D,40H	;ENABLE NATIONAL
	MVI	C,7
	CALL	WRCMOS
	MVI	D,4EH
	MVI	C,1
	CALL	WRCMOS
..J1:	MOV	D,H	;D=CLOCK SECONDS ADDRESS
	RET
;
;	DELAY FOR B^3 MICROSECONDS
;
DELAY:	PUSH	B
..L1:	PUSH	B
..L2:	DJNZ	..L2
	POP	B
	DJNZ	..L1
	POP	B
	DJNZ	DELAY
	RET
;
;	DISPLAY A SPACE, HL, A DASH,
;  	& DE
;
DSDATA:	CALL	SPACE
	CALL	DSADDR
	MVI	C,'-'
	CALL	CO
	MOV	H,D
	MOV	L,E
;
;	DISPLAY HL
;
DSADDR:	CALL	DSH
	MOV	H,L
;
;	DISPLAY H IN HEX
;	(AC) [Y]
;
DSH:	MOV	A,H
	RLC
	RLC
	RLC
	RLC
	CALL	DSH1
	MOV	A,H
DSH1:	ANI	0FH	;CONVERT TO ASCII
	ADI	'0'
	CPI	'9'+1
	JM	..J1
	ADI	7
..J1:	MOV	C,A
	JMP	CO
;
;READ CLOCK - TRY 4 TIMES TO READ A NON-0FH
;VALUE FROM LOCATION F OF THE CLOCK. FAILURE
;MEANS OKI CHIP. RETURN ADDRESS OF SECONDS
;COUNTER ADDRESS OF APPROPRIATE CHIP.
;
RDCLK:	MVI	B,4
..L1:	CALL	RDCMOS
	DJNZ	..L1
	MOV	A,C
	CPI	0FH
	MVI	A,42H
	RNZ
	MVI	A,0C0H
	RET
;
;CMOS RAM OR CLOCK READ/WRITE
;  D=ADDRESS 0-63
;  D6,7=0 IF CMOS RAM
;  D6=1 IF CLOCK
;  D7=0 IF NATIONAL
;  D7=1 IF OKIDATA
;  C0-3=DATA TO BE WRITTEN
;  C4-7=0
;  ON EXIT C=DATA (IF READ)
;LEAVES WITH INTERRUPT OFF
;(A,C,D,E)
;
RDCMOS:	MVI	E,0FH
	JMPR	RWCMOS
WRCMOS:	MVI	E,0
RWCMOS:	MVI	A,0CFH	;SET "A" DIRECTION
	PUSH	D
	DI
	OUT	SPIOA
	MOV	A,E
	OUT	SPIOA
	MOV	A,D	;SET UP ADDRESS & DATA
	RLC
	RLC
	RLC
	RLC
	MOV	D,A
	ANI	0F0H
	ORA	C
	OUT	DPIOA
	MVI	A,0B0H
	BIT	0,E
	JRZ	..J1	;SET BIT 2 IF READ
	SET	2,A
..J1:	BIT	2,D	;CLOCK ?
	JRZ	..J2
	XRI	18H	;--YES
	BIT	3,D	;OKI ?
	JRZ	..J2
	XRI	4	;--YES, INVERT BIT 2
..J2:	MOV	C,A
	MOV	A,D
	ANI	3
	ORA	C
;PULSE A DEVICE ON THE PIO PORT
;  A CONTAINS THE PORT # IN 2-4, THE UPPER
;  TWO ADDRESS BITS (NEEDED ONLY FOR CMOS
;  RAM) IN 0 & 1, AND ONES IN 5 & 7.
;  C CONTAINS THE "A" PORT DATA AS READ
;  WHILE THE PULSE WAS ACTIVE.
	OUT	DPIOB	;SEND B0,B1
	RES	5,A
	OUT	DPIOB	;PULSE DOWN
	PUSH	PSW
	IN	DPIOA	;READ DATA
	ANI	0FH
	MOV	C,A	;SAVE IN C
	POP	PSW
	SET	5,A	;PULSE UP
	OUT	DPIOB
	POP	D
	RET
;
;MAP RAM FROM TABLE STARTING AT (HL)
;(A,B,C,H,L)[X]
;
MAP:	LXI	B,DMAP
..L1:	RLD
	OUTP	A
	MOV	A,B
	ADI	20H
	MOV	B,A
	RRD
	OUTP	A
	MOV	A,B
	ADI	20H
	MOV	B,A
	INX	H
	ORA	A
	JRNZ	..L1
	PCIX
;
;	SEND MESSAGE TO CRT
;
MSSG:	MOV	C,M
	INX	H
	BIT	7,C
	RES	7,C
	JNZ	CO
	CALL	CO
	JMPR	MSSG
;
;	MAKE SOUND SPECIFIED BY 14 BYTE TABLE
;	 POINTED TO BY H-L (R14 OF THE SOUND
;  	 CHIP IS FIRST, R0 LAST)
;	 ----- LEAVES INTERRUPTS OFF -----
;	 (A,B,C,H,L)
;
SOUND:	MVI	A,0CFH
	DI
	OUT	SPIOA
	XRA	A
	OUT	SPIOA
	MVI	A,0E3H
	OUT	DPIOB
	LXI	B,14*256+DPIOA
..L1:	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	..L1
	RET
;
	.PAGE
;
;|--------------------------------------|
;| 	I/O DRIVER SUBROUTINES		|
;|--------------------------------------|
;
;	KEYBOARD INPUT ROUTINE
;
CIKIN:	CALL	KEYSTS
	JRZ	CIKIN
	XRA	A	;--YES, GET IT
	STA	KEYFLG
	LDA	KEYCOD
	RET
;
;
;	COMM/PRTR INPUT ROUTINE
; 	 EITHER OR BOTH PORTS MAY BE SELECTED
; 	 AS SPECIFIED BY THE S COMMAND.
;	 FETCHES COMM. PORT 1ST.
; 	 RETURNS '?' IF NEITHER SELECTED
;
CIPI:	LDA	KEYFLG
	ORA	A	; IF KEY PRESSED
	JNZ	ABORT	;  THEN ABORT
;
	LDA	OUTSEL	; ELSE
	ANI	11H	;  IF NO PORT SELECTED
	JZ	QERR	;   THEN ERROR
;
	BIT	0,A	; ELSE IF PRINT PORT SELECTED
	JRZ	..J1	;  THEN ..J1
;
	CALL	CISTS	; ELSE IF NO BYTE AT
	JRZ	..J1	;  COMM. PORT, THEN ..J1
	IN	DCOMM	; ELSE GET BYTE
	RET
;
..J1:	LDA	OUTSEL
	BIT	4,A	; IF PRINT PORT NOT SELECTED
	JRZ	CIPI	;  THEN CIPI
;
	MVI	A,10H	;  ELSE CHECK PRINT PORT STATUS
	OUT	SPRTR
	IN	SPRTR
	ANI	1	; IF NO BYTE AT PRINT PORT
	JRZ	CIPI	;  THEN CIPI
	IN	DPRTR	; ELSE GET BYTE
	RET
;
;	COMM/PRINTER PORT INPUT ROUTINR
;
CO1:	LDA	OUTSEL
	BIT	4,A
	JRZ	..J0
;
..L0:	MVI	A,10H
	OUT	SPRTR
	IN	SPRTR
	ANI	24H
	CPI	24H
	JRNZ	..L0
	MOV	A,C
	OUT	DPRTR
;
..J0:	LDA	OUTSEL
	BIT	0,A
	JRZ	..J1
;
..L1:	MVI	A,10H
	OUT	SCOMM
	IN	SCOMM
	ANI	24H
	CPI	24H
	JRNZ	..L1
	MOV	A,C
	OUT	DCOMM
;
..J1:	MOV	A,C
	RET
;
;	CRT OUTPUT DRIVER
;	(A,C)
;
SPACE:	MVI	C,SPC
CO:	JMP	DISPLY	; OUTPUT?
;
;	KEYBOARD STATUS
;	(A)
;
KEYSTS:	LDA	KEYFLG
	ORA	A
	RET
;
;	COMM INPUT STATUS TEST
;	(A)
;
CISTS:	MVI	A,10H
	OUT	SCOMM
	IN	SCOMM
	ANI	1
	RET
;
	.PAGE
;
;	TERMINAL EMULATOR
;
TERMNL:	XRA	A
	STA	KEYFLG
..T0:  	CALL	CISTS	;CHECK COMM SATUS
	JRZ	..T1	;  THEN CONTINUE
	IN	DCOMM	;  ELSE OUTPUT CHAR. TO SCREEN
	ANI	7FH
     	MOV	C,A
	CALL	CO
..T1:	LDA	KEYFLG	;CHECK KEYBOARD
	ORA	A	; IF NO CHAR.
	JRZ	..T0	; THEN LOOP BACK
	LDA	KEYCOD
	MOV	C,A
	CPI	86H	; ELSE CHECK FOR EXIT CHAR.
	JRNZ	..T2	;  IF NO EXIT, THEN CONTINUE
	XRA	A
	DI
	STA	KEYFLG
	EI
	JMP	GOMON
..T2:	MVI	A,10H   ;CHECK COMM STATUS
	OUT	SCOMM
	IN	SCOMM
	ANI	4	; IF BUFFER NOT EMPTY
	JRZ	..T0  	;  THEN LOOP BACK
	DI		;  ELSE CLEAR KEYFLAG
	XRA	A
	STA	KEYFLG
	EI
	MOV	A,C
	OUT	DCOMM	;   TRANSMIT CHAR
	JMPR	..T0
;
;	8086 I/O ROUTINES
;
OUT86:	MOV	B,A
..L0:	IN	STAT86
	ANI	TBE	; IF NOT READY TO OUTPUT
	JRNZ	..L0	;  THEN ..J0
;
	MOV	A,B	; ELSE OUTPUT BYTE
	OUT	DATA86
	RET
;
IN86:	IN	STAT86
	ANI	RDA
	JRNZ	IN86
	IN	DATA86
	RET
;
	.LIST
	.IFE	LSTDSK,[
	.XLIST
]
;
.PAGE
;
;|------------------------------|
;| 	DISK SUBROUTINES	|
;|------------------------------|
;
;GENERAL FLOPPY HANDLER
;(A,B,C,D,E,H,L)
;READS A TABLE TO DO DISK OPERATIONS
;  FIRST BYTE
;	0-3 = # OF BYTES TO SEND TO 765
;	4 = 1 IF DMA TO BE ACTIVATED
;	5 = 1 IF INTERRUPT IS TO BE PROCESSED
;	6 = 1 IF WRITE TO DISK, ELSE READ
;	7 = 1 IF ST3 IS TO BE READ
;  IF DMA IS NEEDED, THE NEXT TO BYTES ARE
;    THE START LOCATION IN MEMORY
;  NEXT BYTES ARE TRANSFERRED TO THE 765
; IF ERROR, RETURN ADDRESS IN X REG.
;  (USUALLY CONTAINS ADDRESS OF ERROR ROUTINE)
;
DISKOP: PUSH	H
	LHLD	MTRCNT	;NZ=MOTOR ON
	MOV	A,H
	ORA	L
	PUSH	PSW
	LDA	LSTATE	;START MOTOR
	SET	0,A
	LXI	B,0FBH*256+DPIOB
	PUSH	PSW
	MVI 	A,0CFH
	DI
	OUT	SPIOA
	XRA	A
	OUT	SPIOA
	POP	PSW
	OUT	DPIOA	;SEND	MOTOR	BIT
	OUTP	B
	RES	5,B
	OUTP	B
	SET	5,B
	OUTP	B
	EI
	LXI	H,MTRTIM
	SHLD	MTRCNT
	POP	PSW
	JRNZ	..J1	;MOTOR ON ?
	LXI	D,MTRTIM-MTRDLY+1
..L1:	LHLD	MTRCNT	;NO,	WAIT FOR UP TO SPEED
	DSBC	D
	JP	..L1
..J1:	POP	H
       	MOV	D,H
	MOV	E,L
	BIT	4,M
	JRZ	..J3
	MVI	A,44H	;SET UP DMA MODE
	BIT	6,M
	JRZ	..J2
	MVI	A,48H
..J2:	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
..J3:	PUSH	H	;SEND 765 COMMANDS
	MOV	A,M
	ANI	0FH
	MOV	B,A
	MOV	H,D
	MOV	L,E
..L2:	INX	H
	MOV	C,M
	PUSH	B
	CALL	W765
	POP	B
	MVI	A,1
	JRNZ    ..L3
	POP	B
	POP	B
	PCIX
..L3:	DJNZ	..L2
;
	POP	H
	BIT	5,M	;WAIT FOR INT ?
        JRNZ	..J4
	BIT	7,M	;READ ST3?
	RZ
     	CALL	R765	;YES
	STA	ST3
	MVI	A,2
	RNZ
	POP	B
	PCIX
..J4:	MVI	B,2	;WAIT FOR INTERRUPT (1.2 S.)
..J41:	LXI	H,0A000H
..J5:	LDA	FPYFLG
	ORA	A
	JRNZ	FICLR
	DCX	H
	MOV	A,H
	ORA	L
	JRNZ	..J5
	DJNZ	..J41
	MVI	A,0FFH	;INTERRUPT TIMEOUT
	POP	B
 	PCIX
FICLR:	XRA	A	;NORMAL EXIT
	STA	FPYFLG
	RET
;
;PRINT FLOPPY ERROR INFORMATION
;
ERROR:	CALL	FPER
	JMPR	FPEEXT
FPER:	LDA	ST0
	MOV	D,A
	LDA	ST1
	MOV	E,A
	PUSH	H
	CALL	DSDATA
	POP	H
	LDA	ERRCNT
	INR	A
	STA	ERRCNT
	CPI	23
	RM
FPEEXT:	JMP	GOMON
;
;SEEK & SETUP FOR U AND W
;H=CYLINDER, L7=1 IF 96 TPI,
;L6=HEAD, L4=DRIVE, L0-3=SECTOR
;
FPYSET:	PUSH	H
	LXI	H,FPYTBL ;SET UP PARAMETERS
	LXI	D,TYPE
	LXI	B,21
	LDIR
	POP	H
	BIT	6,L	;SET DRIVE & HEAD
	JRZ	..J1
	MVI	A,1
	STA	RHD
..J1:	MOV	A,L
	RLC
	RLC
	RLC
	RLC
	ANI	5H
	STA	RDRV
	STA	SDRV
	RES	2,A
	STA	HDRV
	LDA	HOMES	;RECAL?
	BIT	4,L
	JRNZ	..J2
	BIT	0,A
	SET	0,A
	JRNZ	..J4
	JMPR	..J3
..J2:	BIT	1,A
	SET	1,A
	JRNZ	..J4
..J3:	STA	HOMES
	PUSH	H
	LXI	H,RCLTBL ;--YES, OUT-IN-OUT
	PUSH	H
	CALL	DISKOP
	LXI	H,SEKTBL
	CALL	DISKOP
	POP	H
	CALL	DISKOP
	POP	H
..J4:	MOV	A,L	;SET SECTOR
	ANI	0FH
	STA	RCRD
	MOV	A,H	;SEEK
	STA	NCN
	STA	RDCYL
	LXI	H,SEKTBL
	CALL	DISKOP
	LXI	H,TYPE	;SET TO READ
	RET
;
;READ A FLOPPY SECTOR, WHERE
;H=CYLINDER, L7=1 IF 96 TPI,
;L6=HEAD, L4=DRIVE, L0-3=SECTOR (1-10)
;
FPREAD:	PUSH	H
	CALL	FPYSET
	CALL	DISKOP
	POP	H
	RET
;
;WRITE A FLOPPY SECTOR, WHERE
;H=CYLINDER, L7=1 IF 96 TPI,
;L6=HEAD, L4=DRIVE, L0-3=SECTOR (1-10)
;
FPWRIT:	PUSH	H
	CALL	FPYSET
	MVI	M,79H
	MVI	A,DBL*40H+5
	STA	CMMD
	CALL	DISKOP
	POP	H
DLY2MS:	MVI	B,13
	JMP	DELAY
;
;FORMAT A DISK
;
SELFMT:	XRA	A	;SET SIZE
	BIT	4,L
	JRZ	..J1
	SET	7,A
..J1:	BIT	0,L	;SET DRIVE
	JRZ	..J2
	SET	4,A
..J2:	MOV	L,A
	MVI	H,0	;CYLINDER 0
FPFRMT:	XCHG
	LXI	H,FILBUF ;SET UP DATA FILE
	MVI	B,10	;10 SECTORS
..L1:	MOV	M,D	;--CYLINDER
	INX	H
	XRA	A	;--SIDE
	BIT	6,E
	JRZ	..J1
	MVI	A,1
..J1:	MOV	M,A
	INX	H
	MVI	A,11	;--SECTOR
	SUB	B
	MOV	M,A
	INX	H
	MVI	M,DBL+1 ;--N
	INX	H
	DJNZ	..L1
	XCHG
	PUSH	H	;SET UP FORMAT TABLE
	CALL	FPYSET	;SEEK
	PUSH	H
	XCHG
	LXI	H,FMTTBL ;SET UP
	LXI	B,11
	LDIR
	LDA	SDRV
	STA	RDRV
	POP	H
	CALL	ABTTST
	LXI	X,ERROR	;FORMAT THE TRACK
	CALL	DISKOP
	POP	H
	CALL	DLY2MS
	INR	H
	MOV	A,H	;FINAL TRACK?
	CPI	40
	JRC	FPFRMT
	BIT	7,L
	JRZ	..J3
..J2:	CPI	80
	JRNZ	FPFRMT
..J3:	BIT	6,L	;HEAD 1?
	SET	6,L
	MVI	H,0
	JRZ	FPFRMT
	RET
;
	.PAGE
;
;|----------------------|
;|	BOOT		|
;|----------------------|
;
BOOT:	MVI	C,0	;ISSUE ILLEGAL COMMAND
	CALL	CMD765	;  TO CLEAR 765
	CALL 	FICLR
        LXI	H,SPCTBL ;SET UP CONTROLLER
	CALL	DISKOP
	MVI	A,3	;TRY TO READ 3 TIMES
..L1:	SSPD	BOTSTK
..L3:	STA    	BOOTRY
	LXI	X,..J1
	LXI	H,1
        CALL 	FPREAD
	LXI	H,NOCPM
	LDA	ST0
	ANI	0C0H
	JRNZ	..J1
	LDA	FILBUF+3
	CPI	0A7H
	JZ	FILBUF
	LDA	BOOTRY
	DCR	A
	JRNZ	..L3
	JMPR	..J2
..J1:	MVI	C,8	;SENSE INTERRUPT STATUS
	CALL	CMD765
	CALL	R765
	LSPD	BOTSTK
	LDA	BOOTRY
	DCR	A
	JRNZ	..L1
;
	LXI 	H,NOHOM	;OUTPUT ERROR MESSAGE
..J2:	CALL	MSSG
GOTERM: LXI	H,OPTON
	CALL	MSSG
	DI
 	XRA	A
	STA	KEYFLG
	LXI	SP,STACK
	EI
	JMP	TERMNL
CMD765:	MVI	B,10	;CLEAR OUT LEFTOVER INFO
..L1:   PUSH    B
        CALL    R765
        POP     B
	DJNZ 	..L1
	CALL	W765	;SEND COMMAND
	JMP	R765	;READ FIRST DATA

;
;WRITE A BYTE FROM C TO THE FLOPPY CONTROLLER
;WHEN STATUS SAYS READY. SET Z IF TIMEOUT.
;(A,B,C)
W765:	MVI	B,1FH
..L1:	DJNZ	..L1
	MVI	B,10
..L2:	IN	SFLPY	;GET STATUS
	ANI	0C0H	;MASK READY & DIRECTION
	CPI	80H
	JRZ	..J1
	DJNZ	..L2
	RET
..J1:	ORA	A	;CLEAR Z
	MOV	A,C
	OUT	DFLPY
	RET
;
;READ FROM FLOPPY CONTROLLER
;WHEN STATUS SAYS READY
;(A,B,C) SET Z IF TIMEOUT
R765:	MVI	B,1FH
..L1:	DJNZ	..L1
	MVI	B,10
..L2:	IN	SFLPY	;GET STATUS
	ANI	0C0H	;MASK READY & DIRECTION
	CPI	0C0H
	JRZ	..J1
	DJNZ	..L2
	RET
..J1:	ORA	A
	IN	DFLPY
	RET
;
	.LIST
	.IFE	LSTDSP,[
	.XLIST
]
;
	.PAGE
;
;|--------------------------------------|
;|   500 DISPLAY & KEYBOARD DRIVER	|
;|--------------------------------------|
;
;	COMMAND CODES
;
;	BEL	BELL
;	BS	BACKSPACE
;	CR	CARRIAGE RETURN
;	LF	LINE FEED
;	CTRL/Z	HOME CURSOR & CLEAR SCREEN
;
;	ESC =LP	POSITION TO L(0-24) AND P(0-79)
;		OFFSET BY 20H
;	ESC YLP SAME AS ESC =LP
;	ESC A OR CTRL/K		CURSOR UP
;	ESC B			CURSOR DOWN
;	ESC C OR CTRL/L		CURSOR RIGHT
;	ESC D			CURSOR LEFT
;	ESC H OR CTRL/^		CURSOR	HOME
;	ESC J	ERASE TO END OF SCREEN
;	ESC K	ERASE TO END OF LINE
;
;	DISPLAY ENTRY (CHARACTER IN C)
;
DISPLY:	PUSH	X
	PUSH	H
	PUSH	D
	PUSH	B
	PUSH	PSW
;
;	CHECK CYCLE
;
DISP1:	LHLD	CHRADR	;H=COLUMN, L=LINE
	CALL	CMPOFF
	LDA	DSPCYC	;A=CYCLE
	ORA 	A
	JNZ	ESCCHK
;
;	CHARACTER OR CTRL
;
	MOV	A,C	;CONTROL?
	ANI	60H
	JRZ	CTROL
;
;	HANDLE CHARACTERS (FROM C)
;
	MOV	A,C	;TRANSLATE ALTERNATE
	CPI	'@'	;CHARACTER SET
	JRC	..J00
	CPI	'a'
	JRNC	..J00
	ANI	3FH
	PUSH	PSW
	LXI	D,CHRTBL
	XCHG
	LDA	CURCHR
	MOV	C,A
	MVI	B,0
	DAD	B
	MOV	A,M
	POP	B
	XCHG
	ORA	B
..J00:	MOV	E,A	;SAVE CHAR IN E
	MOV	A,L
	ORI	0E0H	;CHAR COMMAND
	OUT	SDSPY
	MOV	B,H
	MVI	C,DDSPY
	OUTP	E
;
;	SEND ATTRIBUTE
;
	ANI	0DFH	;ATTRIBUTE COMMAND
	OUT	SDSPY
	ANI	1FH
	MOV	L,A
	LDA	CURATT
	OUTP	A	;SEND IT
;
;	BUMP CHARACTER POSITION
;
	MOV	A,H
	CPI	79
	JRNZ	BUMP
EXIT0:	XRA	A
	STA	CHRADR+1
	MVI	C,LF
	JMPR	DISP1
BUMP:	INR	A
EXIT1:	MOV	H,A
	STA	CHRADR+1
CRSRET:	MVI	A,0ACH	;SET CURSOR
	OUT	SDSPY
	MOV	A,H
	INR	A
	OUT	DDSPY
	MVI	A,0ADH
	OUT	SDSPY
	MOV	A,L
	ANI	1FH
	OUT	DDSPY
EXIT2:	XRA	A
EXIT3:	STA	DSPCYC
DSPRET:	POP	PSW
	POP	B	;POP AND RETURN
	POP	D
	POP	H
	POP	X
	RET
;
;	CONTROL CHARACTERS
;
CTROL:	MOV	A,C
	CPI	ESC
	JRNZ	CTROL2
CTROL1:	MVI	A,1
	JMPR	EXIT3
CTROL2:	CPI	BS
	JRNZ	..J2
	MOV	A,H	;BS
	ORA	A
	JRZ	EXIT2
	DCR	A
	JMPR	EXIT1
..J2:	CPI	CR
	JRNZ	..J3
	XRA	A	;CR
	JMPR	EXIT1
..J3:	CPI	LF
	JRNZ	BELCHK
	LDA	CHRADR
	CPI	LINES-1
	JRZ	..J4	; LF NOT AT BOTTOM
	INR	A
	STA	CHRADR
	INR	L
	MOV	A,L
	CPI	LINES
	JRNZ	CRSRET
	XRA	A
	MOV	L,A
	JMPR	CRSRET
..J4:	MVI	A,0ABH	;LF AT BOTTOM
	OUT	SDSPY	;UP SCROLL
	OUT	DDSPY
	LDA	LINOFS	;BUMP OFFSET
	INR	A
	CPI	LINES
	JRNZ	..J5
	XRA	A
..J5:	STA	LINOFS
	MOV	A,L
	INR	A
	INR	L
	CPI	LINES
	JRNZ	..J6
	MVI	L,0
..J6:	CALL	LFCLR1
	LDA	CHRADR+1
	MOV	H,A
	JMPR	CRSRET
BELCHK:	CPI	BEL
	JRNZ	HOMCHK
	LXI	H,BEEP	;BELL
	CALL	SOUND
	EI
	JMPR	EXIT2
;
HOMCHK:	CPI	1EH
	JRNZ	UPCHK
HOMCK1:	LXI	H,1
	SHLD	CHRADR
	MVI	C,8
	JMP	DISP1
;
UPCHK:  CPI	0BH
	JZ	ESCHK1
;
LFCHK:	CPI	0CH
	JZ	ESCHK2
;
CLZCHK:	CPI	1AH
DSPRT:	JNZ	DSPRET
	LXI	H,0
	SHLD	CHRADR
	CALL	CMPOFF
	PUSH	H
	CALL	CLTOND
	POP	H
	JMPR	LP2
;
;	ESCAPE SEQUENCES
;
ESCCHK:	DCR	A
	JNZ	LINCHK
;FIRST CHAR. AFTER ESC
	MOV	A,C
	CPI	'='
        JRNZ	..J0
;
;	= - DIRECT POSITION
;
..JF:	LXI	H,DSPCYC ;SET DSPCYC=2
	INR	M
	JMPR	DSPRT
..J0:	CPI	'Y'
	JRZ	..JF
..J1:	CPI	'A'
	JRNZ	JMP2
;
;	A - UP
;
ESCHK1:	LDA	CHRADR
	ORA	A
	JRZ	EX2
	DCR	A
	DCR	L
	JP	LP1
	MVI	L,LINES-1
LP1:	STA	CHRADR
LP2:	JMP	CRSRET
JMP2:	CPI	'B'
	JRNZ	..J3
;
;	B - DOWN
;
	LDA	CHRADR
	CPI	LINES-1
	JRZ	EX2
	INR	A
	INR	L
	PUSH	PSW
	MOV	A,L
	CPI	LINES
	JRNZ	..J30
	MVI	L,0
..J30:	POP	PSW
	JMPR	LP1
..J3:	CPI	'C'
	JRNZ	ESC1
;
;	C - RIGHT
;
ESCHK2:	MOV	A,H
	CPI	79
	JZ	EXIT0
	INR	A
EX1:	JMP	EXIT1
ESC1:	CPI	'D'
	JRNZ	..J9
;
;	D - LEFT
;
	MOV	A,H
	ORA	A
	JRZ	EX2
	DCR	A
	JMPR	EX1
..J9:	CPI 	'J'
	JRNZ 	..J12
;
;	J - ERASE TO END OF SCREEN
;
	CALL	CLTOND
	JMPR	EX2
..J12:	CPI	'K'
	JRNZ	..J14
;
;	K - ERASE TO END OF LINE
;
	CALL	LFCLR2
	JMPR	LP2
;
;	H - CURSOR HOME
;
..J14:	CPI	'H'
	JZ      HOMCK1
;
;	I - CURSOR UP
;
	CPI	'I'
	JZ	ESCHK1
EX2:	JMP     EXIT2
;
;	MULTI-CHARACTER SEQUENCE HANDLERS
;
;	CURSOR POSITION LINE NUMBER
;
LINCHK:	DCR	A
	JRNZ	CHRCHK
	MVI	A,3
	STA	DSPCYC
	MOV	A,C
	SBI	SPC
	CPI	LINES
	JRNC	..J1
	STA	CHRADR
..J1:	JMP	DSPRET
;
;	CURSOR POSITION COLUMN NUMBER
;
CHRCHK:	DCR	A
	JRNZ	EX2
	MOV	A,C
	SBI	SPC
	CPI	80
	JM	EXIT1
	JMPR	EX2
;
;|------------------------------|
;|	DISPLAY SUBROUTINES	|
;|------------------------------|
;
;	CLEAR LINE L
;
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
..L1:	OUTP	D
	DJNZ	..L1
	OUTP	D
	POP	B
	SET	5,L
	OUTP	L
	MVI	C,DDSPY
..L2:	OUTP	E
	DJNZ	..L2
	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
..L1:	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	..L1
;
;	CLEAR TO END OF SCREEN
;
CLTOND:	CALL	LFCLR2	;CLEAR FIRST PARTIAL LINE
	LDA	CHRADR	;CALCULATE # OF FULL LINES
	SBI	LINES+1
	CMA
	MOV	B,A
	JMPR	..JJ2
..JL1:	MOV	A,L	;LOOP TO CLEAR LINES
	ANI	1FH
	INR	A
	CPI	LINES
	JRNZ	..JJ1
	XRA	A
..JJ1:	MOV	L,A
	PUSH	B
	CALL	LFCLR1
	POP	B
..JJ2:	DJNZ	..JL1
	RET
;
;	CALCULATE LINE OFFSET
;
CMPOFF:	LDA	LINOFS	;ADD OFFSET TO LINE
	ADD	L
	CPI	LINES
	JRC	..J1
	SBI	LINES
..J1:	MOV	L,A
	RET
;
;MOVE LINE D TO POSITION E
;
MOVLIN:	MOV	A,D	;SET UP
	ORI	0C0H
	MOV	D,A
	MOV	A,E
	ORI	0C0H
	MOV	E,A
	MVI	B,80
	PUSH	H
	PUSH	B
	CALL	..S1	;MOVE ATTRIBUTES
	POP	B
	POP	H
	SET	5,D	;MOVE CHARACTERS
	SET	5,E
..S1:	MVI	C,SDSPY
	OUTP	D
	LXI	H,DSPBUF
	PUSH	H
	PUSH	B
	MVI	C,DDSPY
	INIR
	POP	B
	POP	H
	OUTP	E
	MVI	C,DDSPY
	OUTIR
	RET
;
	.LIST
	.IFE	LSTINT,[
	.XLIST
]
;
	.PAGE
;
;|------------------------------|
;| INTERRUPT SERVICE ROUTINES	|
;|------------------------------|
;
;	50/60 HZ INTERRUPT
;
SRV60:	PUSH	H	;SAVE REGISTERS
	PUSH	D
	PUSH	B
	PUSH	PSW
;
;	HANDLE KEYBOARD
;
	IN	DPIOB	;CHECK FOR KEY
	BIT	6,A
	JRZ	..J2
;
	LXI	H,CLICK	;SOUND THE KEY
	CALL	SOUND
	MVI	B,9
..L3:	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	..L3
	BIT	6,L
	JRZ	..J1
	RES	7,L
..J1:	MVI	H,0
	LXI	D,KEYTBL
	DAD	D
	MOV	A,M
	CPI	0FEH
	LDA	SHLOCK
	JRNZ	..J4
	CMA
	STA	SHLOCK
	JMPR	..J2
..J4:	ORA	A
	MOV	A,M
	JRZ	..L4
	CPI	61H
	JRC	..L4
	CPI	7BH
	JP	..L4
	RES	5,A
..L4:	STA	KEYCOD
	MVI	A,0FFH
	STA	KEYFLG
;
;	FLOPPY MOTOR SHUT-DOWN
;
..J2:	LHLD	MTRCNT	;GET MOTOR TIMER
	MOV	A,H
	ORA	L
	JRNZ	..J3	;IF <> 0 THEN DECR. & EXIT
	MVI	A,0CFH
	OUT	SPIOA
	XRA	A
	STA	HOMES	; MOTOR OFF, CLEAR HOMES FLAG
	OUT	SPIOA
	LDA	LSTATE
	RES	0,A
	OUT	DPIOA
	LXI	B,0FBH*256+DPIOB
	OUTP	B
	RES	5,B
	OUTP	B
	SET	5,B
	OUTP	B
	INX	H
..J3:	DCX	H
	SHLD	MTRCNT
;
;	COMMON INTERRUPT EXIT
;
IEND:	POP	PSW
	POP	B
	POP	D
	POP	H
	EI
	RETI
;
;	FLOPPY INTERRUPT ROUTINE
;
SRVFPY: PUSH	H
	PUSH	D
	PUSH	B
	PUSH	PSW
	MVI	A,0FFH	;SET INTERRUPT TAKEN FLAG
	STA	FPYFLG
	IN	SFLPY	;FDC	BUSY ?
	ANI	10H
	JRZ	..J1
	LXI	H,ST0	;YES, READ AND SAVE RESULTS
	MVI	B,7H
..L1:	PUSH	B
	CALL	R765
	MOV	M,A
	INX	H
	POP	B
	DJNZ	..L1
	JMPR    IEND
..J1:	MVI	C,8	;NO, SENSE INTERRUPT STATUS
	CALL	W765
	CALL	R765
	JRNZ    ..J2
	BIT	7,A
        JRZ	..J2
	BIT	6,A
	JRZ	IEND	;IF SO, EXIT
..J2:	STA     ST0	;NO, SAVE ST0 & PCN
	CALL	R765
	STA	CYL
	JMPR	IEND
;
        .LIST
	.IFE	LSTTBL,[
	.XLIST
]
;
	.PAGE
;
;|------------------------------|
;|            TABLES		|
;|------------------------------|
;
;	I/O SETUP TABLE
; 	 FORMAT: PORT#, # OF BYTES, BYTES
;	 PORT ENTRY OF 0FFH ENDS IT
;
;	DISPLAY
;
IOTBL:	.BYTE	SDSPY	; START TIMING CHAIN
	.BYTE	1
	.BYTE	0AEH
	.BYTE	DDSPY
	.BYTE	1
	.BYTE	0
	.BYTE	SDSPY	; RESET
	.BYTE	1
	.BYTE	0AAH
	.BYTE	DDSPY
	.BYTE	1
	.BYTE	0
	.BYTE	SDSPY	; REG 0
	.BYTE	1
	.BYTE	0A0H
	.BYTE	DDSPY
	.BYTE	1
	.BYTE	97	; 98 CHAR-1
	.BYTE	SDSPY	; REG 1
	.BYTE	1
	.BYTE	0A1H
	.BYTE	DDSPY
	.BYTE	1
	.BYTE	42H	; H WIDTH=15, H DLY=1
	.BYTE	SDSPY	; REG 2
	.BYTE	1
	.BYTE	0A2H
	.BYTE	DDSPY
	.BYTE	1
	.BYTE	04DH	; 10 SCANS/ROW, 80 CHAR LINES
	.BYTE	SDSPY	; REG 3
	.BYTE	1
	.BYTE	0A3H
	.BYTE	DDSPY
	.BYTE	1
	.BYTE	97H	; 24 LINES
	.BYTE	SDSPY	; REG 4
	.BYTE	1
	.BYTE	0A4H
	.BYTE	DDSPY
	.BYTE	1
	.BYTE	3
        .BYTE	SDSPY	;REG 5
	.BYTE	1
        .BYTE	0A5H
	.BYTE	DDSPY
	.BYTE	1
        .BYTE	20	; 60HZ, V DLY=12
	.BYTE	SDSPY	; REG 6
	.BYTE	1
	.BYTE	0A6H
	.BYTE	DDSPY
        .BYTE	1
	.BYTE	LINES-1	; LAST ROW=23
	.BYTE	SDSPY	; RESTART CHAIN
	.BYTE	1
	.BYTE	0AEH
	.BYTE	DDSPY
	.BYTE	1
	.BYTE	0
;
;	PARALLEL PORT
;
	.BYTE	DPIOB	;SETUP TO TURN ON HIGH
	.BYTE	1
	.BYTE	0FFH
	.BYTE	SPIOA	;DATA & ADDRESS PORT
	.BYTE	3
	.BYTE	4FH	;RESET
	.BYTE	0CFH	;BIT MODE
	.BYTE	0	;ALL OUT
	.BYTE	SPIOB	;CONTROL PORT
	.BYTE	3
	.BYTE	4FH	;RESET
	.BYTE	0CFH	;BIT MODE
	.BYTE	40H	;BIT 6 IN, OTHERS OUT
	.BYTE	DPIOA	;BRIGHTNESS, MOTOR OFF,
	.BYTE	1	;  EPROM ON
	.BYTE	0C0H
	.BYTE	DPIOB	;LOAD STATUS LATCH
	.BYTE	3
	.BYTE	0FBH
	.BYTE	3BH
	.BYTE	0FBH
;
;	DMA CONTROLLER
;
	.BYTE	DMATMP	;RESET DMA
	.BYTE	1
	.BYTE	0
	.BYTE	DMACSR	;PARAMETERS
	.BYTE	1
	.BYTE 01000000B ;DACK LOW, DREQ LOW,
			;LATE WRITE, FIXED
			;PRIORITY, NORMAL TIMING,
			;ENABLED, NO HOLD OR
			;MEMORY-TO-MEMORY
	.BYTE	DMAWMR	;MODES
	.BYTE	DMALN
TBLDMA:	.BYTE 01001000B	;FLOPPY - SINGLE, INCREMENT,
			;  AUTOINIT OFF, READ
	.BYTE 01001001B	;INIT OTHERS FOR STABLE OPERATION
	.BYTE 01001010B
	.BYTE 01001011B
DMALN	=	.-TBLDMA
	.BYTE	DSPBCA	;DISPLAY CHANNEL
	.BYTE	2
	.WORD	0	;DISPLAY BASE & CURRENT ADDRESS
	.BYTE	DSPBWR
	.BYTE	2
	.WORD	0	;DISPLAY BASE & CURRENT WORD COUNT
;
;	TIMERS
;
	.BYTE	BAUDC	;COMM PORT
	.BYTE	4
	.BYTE	3	;RESET
	.BYTE (V60HZ-4)@256 ;INT. VECTOR
	.BYTE	TIMCW0	;CONTROL WORD
	.BYTE	TIMTC0	;COMM BAUD
	.BYTE	BAUDP	;PRTR PORT
	.BYTE	2
	.BYTE	TIMCW0	;CONTROL WORD
	.BYTE	TIMTC0	;PRTR BAUD
	.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	;COUNT OF 1
;
;	SERIAL PORTS
;	 COMM PORT
;
	.BYTE	SCOMM	;MODES
	.BYTE	SIOLN
TBLSIO:	.BYTE	0	;REG 0
	.BYTE	0,0D8H	;RESET
	.BYTE	4	;REG 4
	.BYTE	44H	;X16 CLOCK, 1 STOP, ASYNC
	.BYTE	1	;REG 1
	.BYTE	60H	;NO INTERRUPT, DMA READY
	.BYTE	3	;REG 3
	.BYTE	0C1H	;RCV 8 BITS, ENABLE RCVR
	.BYTE	5	;REG 5
	.BYTE	0EAH	;DTR ON, XMIT 8 BITS
SIOLN	=	.-TBLSIO
;
;	 PRTR PORT
;
	.BYTE	SPRTR	;MODES
	.BYTE	SIPLN
TBLSIP:	.BYTE	0	;REG 0
	.BYTE	0,0D8H	;RESET
	.BYTE	4	;REG 4
	.BYTE	44H	;X16 CLOCK, 1 STOP, ASYNC
	.BYTE	1	;REG 1
	.BYTE	60H	;NO INTERRUPT, DMA READY
	.BYTE	3	;REG 3
	.BYTE	0C1H	;RCV 8 BITS, ENABLE RCVR
	.BYTE	5	;REG 5
	.BYTE	0EAH	;DTR ON, XMIT 8 BITS
SIPLN	=	.-TBLSIP
;
;	TERMINATOR
;
	.BYTE	0FFH
;
;	KEYCODE TRANSLATION TABLE
;
	.RADIX 16
;
;	NO CTRL, SHIFT
;
KEYTBL:	.BYTE	08,09,0A,00,00,0D,00,0FE;BS TAB LF N/A N/A CR N/A LOCK
	.BYTE	20,00,00,1B,81,82,83,84	;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[\]_
;
;	CTRL
;
	.BYTE	08,09,86,00,00,0D,00,0FE;BS TAB LF N/A N/A CR N/A LOCK
	.BYTE	20,00,00,1B,81,82,83,84	;SP NA NA ESC LFT RT UP DN
	.BYTE	30,31,32,33,34,35,36,37	;01234567
	.BYTE	38,39,3A,3B,2C,3D,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,1E,1F	;CTRL-XYZ[\]_
;
;	NO SHIFT OR CTRL
;
       	.BYTE	08,09,0A,00,00,0D,00,0FE;BS TAB LF N/A N/A CR N/A LOCK
	.BYTE	20,00,00,1B,81,82,83,84	;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
;
	.RADIX 10
;
;|------------------------------|
;|	DISK OPERATION TABLES	|
;|------------------------------|
;
; ---- READ/WRITE TABLE ----
;
;  (SET UP FOR READ OF DRIVE 0, TRK0
;  MOVED TO RAM AND CHANGED AS NEEDED
;  FOR OTHER OPERATIONS)
;
FPYTBL:	.BYTE	39H	;TYPE
	.WORD	FILBUF	;DMAADD
	.WORD	DBL*256+255 ;BCNT
	.BYTE	DBL*40H+6 ;CMMD
	.BYTE	0	;UNIT
	.BYTE	0	;C
	.BYTE	0	;H
	.BYTE	1	;R
	.BYTE	DBL+1	;N
	.BYTE	SECS+9	;EOT
	.BYTE	37-(SECS*22);GP2
	.BYTE	0FFH	;DTL
;
; ---- RECALIBRATE ----
;
	.BYTE	22H
	.BYTE	7
	.BYTE	0
	.BYTE	23H
	.BYTE	0FH
	.BYTE	0
	.BYTE	5
;
; ---- SPECIFY ----
;
SPCTBL:	.BYTE	3
	.BYTE	3
	.BYTE	SRT*16+HUT
	.BYTE	HLT*2+ND
;
; ---- FORMAT A TRACK ----
;
FMTTBL:	.BYTE	76H
	.WORD	FILBUF
	.WORD	4*(9+SECS)-1
	.BYTE	40H*DBL+0DH
	.BYTE	0	;HD & DRIVE
	.BYTE	DBL+1	;SECTOR SIZE
	.BYTE	SECS+9	;SECTORS/CYL
	.BYTE	87-(SECS*57) ;GAP 3
	.BYTE	0E5H	;FILL DATA
;
;	BAUD RATE TABLE
;
TBLBAD:	.BYTE	174,128,64,32	;110,150,300,600
	.BYTE	16,8,4,2,1	;1200,2400,4800,9600,19.2K
;
;	ALTERNATE CHARACTER SET TRANSLATION TABLE
;
CHRTBL:	.BYTE	40H	;0 = STANDARD SET
	.BYTE	00H	;1 = FORMS RULING
	.BYTE	80H	;2 = GREEK & LANGUAGES
	.BYTE	0C0H	;3 = MATH & WORD PROCESSING
;
;	COMMONLY USED MEMORY MAPS
;
;  FORMAT: 8 NIBBLES CORRESPONDING IN ORDER
;  TO VIRTUAL BLOCKS 0-7. THE CONTENT OF EACH
;  NIBBLE REPRESENTS A REAL BLOCK VIA THE
;  FOLLOWING:
;		XXXX
;		|---
;		| |
;		| REAL SEGMENT #
;		0=DISABLE
;		1=ENABLE
;
TBLMAP:	.BYTE	089H,0ADH,0FBH,0ECH ;TEST BLK 0
	.BYTE	089H,0DBH,0EAH,0CFH ;TEST BLK 1
	.BYTE	08CH,0ABH,0D9H,0EFH ;TEST BLK 2
	.BYTE	0D9H,0ABH,0C8H,0EFH ;TEST BLK 3
REVMAP:	.BYTE	0FEH,0DCH,0BAH,098H ;ALL BLOCKS REVERSED
STDMAP:	.BYTE	089H,0ABH,0CDH,0EFH ;STANDARD MAPPING
;
;	STANDARD CONTINUOUS TEST
;
TCMD:	.ASCII	'NHQTMR1R2R3RZ1Z'
	.BYTE	0
;
;	ERROR MESSAGES
;
NOHOM:	.BYTE	0DH,0AH
	.ASCIS	'NO DISK OR DISK NOT READABLE'
NOCPM:	.BYTE	0DH,0AH
	.ASCIS	'NO SYSTEM ON DISK'
OPTON:	.BYTE	0DH,0AH
	.ASCII	'NOW IN TERMINAL MODE'
	.BYTE	0DH,0AH,8AH
;
;	SOUND TABLES
;
CLICK:	.BYTE	0,1,0,16,16,16,48,1
	.BYTE	0,0,0,0,1,128
;
BEEP:	.BYTE	2,12H,0,1FH,1FH,1FH,38H,0
	.BYTE	0,20H,0,40H,0,10H
;
SIZTST	=	.
;
;	INTERRUPT VECTORS
;
	.LOC	BASE+0FF4H
V60HZ:	.WORD	SRV60	;60 HZ
VFLPPY:	.WORD	SRVFPY	;FLOPPY
;
	.LIST
;
AVAIL	=	V60HZ-SIZTST
;
        .IFE	LSTRAM,[
	.XLIST
]
;
	.PAGE
;
;|----------------------|
;|	 RAM AREA	|
;|----------------------|
;
	.LOC	0FD00H
;
;	DISK VARIABLES
;
;	DISK COMMAND TABLES (LEAVE AS IS UP TO ERRCNT)
;
;	--- READ/WRITE/FORMAT ---
;
TYPE:	.BLKB	1	;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
;
DMAADR:	.BLKW	1	;ADDRESS TO START DATA XFER
BCNT:	.BLKW	1	;BYTE COUNT-1
CMMD:	.BLKB	1	;COMMAND TO 765
RDRV:	.BLKB	1	;UNIT #
RDCYL:	.BLKB	1	;CYLINDER #
RHD:	.BLKB	1	;HEAD #
RCRD:	.BLKB	1	;RECORD #
NSENT:	.BLKB	1	;BYTES/SECTOR
EOT:	.BLKB	1	;SECTORS/TRACK
GPL:	.BLKB	1	;GAP 2 LENGTH
DTL:	.BLKB	1	;DATA LENGTH
;
;	--- RECALIBRATE	---
;
RCLTBL:	.BLKB	1	;RECAL TYPE
	.BLKB	1	;RECAL COMMAND
HDRV:	.BLKB	1	;RECAL DRIVE
;
;	--- SEEK ---
;
SEKTBL:	.BLKB	1	;SEEK TYPE
	.BLKB	1	;SEEK COMMAND
SDRV:	.BLKB	1	;SEEK DRIVE
NCN:	.BLKB	1	;NEW CYLINDER NUMBER
;
;	READ BACK STATUS - MUST STAY IN ORDER
;
ST0:	.BLKB	1	;STO STATUS
ST1:	.BLKB	1	;ST1 STATUS
ST2:	.BLKB	1	;ST2 STATUS
CYL:	.BLKB	1	;CYLINDER STATUS
HD:	.BLKB	1	;HEAD STATUS
REC:	.BLKB	1	;RECORD STATUS
NUMB:	.BLKB	1	;NUMBER OF BYTES STATUS
ST3:	.BLKB	1	;DRIVE STATUS
;
;	OTHER FLOPPY VARIABLES
;
ERRCNT:	.BLKB	1	;DISK ERROR COUNTER
FPYFLG:	.BLKB	1	;FLOPPY FLAG(FF=INTERRUPT TAKEN)
HOMES:	.BLKB	1	;HOME FLAGS
MTRCNT:	.BLKW	1	;FLOPPY MOTOR TIMER
;
;	DISPLAY VARIABLES
;
CHRADR:	.BLKW	1	;CHARACTER ADDRESS
			;  H=CHAR POSITION (0=LEFT)
			;  L=LINE# (0=TOP, 23=BOTTOM)
CURATT:	.BLKB	1	;CURRENT ATTRIBUTE CODE
CURCHR:	.BLKB	1	;CURRENT CHARACTER SET
DSPBUF:	.BLKB	80	;BUFFER FOR MOVING LINES
DSPCYC:	.BLKB	1	;DISPLAY CYCLE COUNTER
			;	0 = NORMAL CHAR
			;	1 = ESC PENDING
			;	2 = LINE # PNDG.
			;	3 = CHAR # PNDG.
			;	4 = ATTRIBUTE PNDG.
			;	5 = CHARACTER SET PNDG.
 		        ;	6 = LEAD-IN PENDING
LINOFS:	.BLKB	1	;OFFSET DUE TO LINE FEEDS
;
;	KEYBOARD VARIABLES
;
KEYCOD:	.BLKB	1	;KEY CODE
KEYFLG:	.BLKB	1	;KEY FLAG (FF = KEY WAITING)
SHLOCK:	.BLKB	1	;SHIFT LOCK FLAG (FF = CAPS)
;
;	MISC. VARIABLES
;
FLAG86:	.BLKB	1	; 8086 FLAG; 0 = O.K.
BOOTRY:	.BLKB	1	;BOOT TRY COUNTER
BOTSTK:	.BLKW	1	;BOOT STACK STORAGE
CMDPTR:	.BLKW	1	;U COMMAND POINTER
FLGLOP: .BLKB	1	;LOOP PENDING FLAG
FLGCMD:	.BLKB	1	;MACRO FLAG
LSTATE:	.BLKB	1	;L0-L7 STATE
CMDSTT:	.BLKW	1	;START OF MACPTR
OUTSEL:	.BLKB	1	;OUTPUT SELECT STATUS
SAVDE:	.BLKW	1	;LOOP DE SAVE
SAVHL:	.BLKW	1	;LOOP HL SAVE
SAVCMD:	.BLKB	1	;LOOP COMMAND SAVE
SAVDE2:	.BLKW	1
SAVHL2:	.BLKW	1
SVCMD2:	.BLKB	1
CMDBUF:	.BLKB	20	;U COMMAND BUFFER
;
;
	.XSYM
        .END
