;********************************************************
;*							*
;*	BASIC HEX MONITOR FOR Z-80 PROCESSORS		*
;*							*
;********************************************************
;
;
;
;
PROMPT:	CALL	PNEXT
	DEFB	CR,LF,'* ',EOT
	LD	HL,LINBUF
	LD	C,LINSIZ
	CALL	GETLIN		;INPUT A BUFERED CONSOLE LINE
	JR	C,WHAT		;PRINT 'WHAT ?' IF INPUT ERROR

	CALL	CRLFS
	XOR	A
	LD	(BREAK),A	;CLEAR CONSOLE BREAK FLAG
	LD	A,(LINBUF)
	LD	IY,LINBUF+1
	LD	HL,CMDTAB	;SEARCH FOR A MATCHING CHARACTER
	LD	BC,CMDSIZ/3	; IN COMMAND SEARCH TABLE
	CALL	SEARCH
	CALL	NZ,EXTEND	;TRY EXTENDED FUNCTION JUMP IF NO MATCH
	JR	NZ,WHAT
	PUSH	HL
	CALL	PARAMS		;INPUT NUMERIC PARAMETERS FROM
	POP	IX		; LINE BUFFER AND TEST IF ERROR
	JR	C,WHAT
	LD	HL,(PARAM1)
	LD	DE,(PARAM2)
	LD	BC,(PARAM3)
	CALL	CALLX		;CALL SUBROUTINE @ IX
	JR	NC,PROMPT	;GO BACK TO PROMPT IF NO ERRORS

WHAT:	CALL	PNEXT
	DEFM	' what ?'
	DEFB	EOT
	JR	PROMPT
;
;
;
EXTEND:	LD	HL,(MONVEC)
	CALL	DISPATCH	;PROCESS EXTENDED MONITOR FUNCTION
EXT2:	RET
;
;
CALLX:	JP	(IX)		;CALL SUBROUTINE @ IX
;
;
;
CMDTAB:	DEFB	'V'
	DEFB	'R'
	DEFB	'O'
	DEFB	'I'
	DEFB	'G'
	DEFB	'T'
	DEFB	'F'
	DEFB	'M'
	DEFB	'C'
	DEFB	'B'
	DEFB	'D'
	DEFB	'X'
	DEFB	CR

	DEFW	DUMMY
	DEFW	BANKSW		;BANKSWITCH COMMAND
	DEFW	MEMDMP		;DUMP MEMORY IN HEX/ASCII
	DEFW	BOOT		;BOOT FROM FLOPPY
	DEFW	BLOCK		;MEMORY BLOCK MOVE
	DEFW	VIEW		;MEMORY EXAMINE/CHANGE
	DEFW	FILL		;FILL MEMORY
	DEFW	TEST		;RAM DIAGNOSTIC
	DEFW	GOTO		;JUMP TO MEMORY LOCATION
	DEFW	INCMD		;READ FROM INPUT PORT
	DEFW	OUTCMD		;WRITE TO OUTPUT PORT
	DEFW	DSKCMD		;DISPLAY DISK SECTOR DATA
	DEFW	VERCMD		;MEMORY BLOCK COMPARE

CMDSIZ	EQU	$-CMDTAB
;
;
;********************************************************
;*							*
;*	MONITOR COMMAND ACTION ROUTINES PACKAGE		*
;*							*
;********************************************************
;
;
;
;	-- DISK SECTOR READ COMMAND --
;
DSKCMD:	CP	3		;CHECK PARAMETER COUNT
	JR	Z,DSK1
	OR	A
	SCF
	RET	NZ
	LD	HL,SECTOR
	INC	(HL)		;BUMP LAST USED SECTOR NUMBER
	JR	DSK2B
;
DSK1:	LD	C,L		;USE FIRST ARG AS UNIT#
	CALL	SELECT
	JR	NZ,DSKERR
	LD	HL,PARAM2
	LD	C,(HL)		;USE SECOND ARG AS TRACK#
	CALL	SEEK
	JR	NZ,DSKERR
	LD	HL,PARAM3
DSK2B:	LD	C,(HL)		;USE THIRD ARG AS SECTOR#
	LD	HL,DSKBUF
	CALL	READ		;READ SECTOR INTO (BUFFER)
	JR	NZ,DSKERR
	INC	HL		;ADD 1 TO DMA BYTECOUNT RETURNED IN HL
	EX	DE,HL
	LD	B,4
DSK2C:	SRL	D
	RR	E		;DIVIDE BYTECOUNT BY 4
	DJNZ	DSK2C
	LD	HL,DSKBUF
	CALL	DUMP		;DUMP DISK READ BUFFER AND
	JR	DSKADR		; PRINT UNIT/TRACK/SECTOR
	
DSKERR:	PUSH	AF		;SAVE 1771 STATUS
	CALL	PNEXT
	DEFM	'disk error  '
	DEFB	EOT
	POP	AF
	CALL	PUT2HS		;PRINT ERROR STATUS IN HEX
DSKADR:	LD	A,(DSKTYP)
	BIT	0,A		;DETERMINE IF SINGLE/DOUBLE DENSITY
	LD	A,'S'
	JR	Z,DSKAD1
	LD	A,'D'
DSKAD1:	CALL	OUTPUT		;DISPLAY 'SD' OR 'DD'
	LD	HL,DADMSG
	CALL	PMSG
	LD	A,(UNIT)	;NOW DISPLAY UNIT/TRACK/SECTOR
	CALL	PUT2HS		;PRINT DRIVE UNIT#
	LD	A,'T'
	CALL	OUTPUT
	LD	A,(TRACK)
	CALL	PUT2HS		;PRINT TRACK# IN HEX
	LD	A,'S'
	CALL	OUTPUT
	LD	A,(SECTOR)
	CALL	PUT2HS		;PRINT SECTOR# IN HEX
DUMMY:	OR	A
	RET

DADMSG:	DEFB	'D  U',EOT
;
;
;
;
;	-- DISK BOOT LOADER COMMAND --
;
BOOT:	LD	C,0		;SELECT DRIVE 0 FOR BOOT LOAD
	CALL	SELECT
	JR	NZ,DSKERR
	CALL	HOME		;HOME HEAD TO TRACK 0
	JR	NZ,DSKERR	;ERROR IF CANNOT RESTORE
	LD	HL,DSKBUF	;POINT TO MONITOR'S SECTOR BUFFER
	LD	C,1		;SELECT SECTOR 1
	CALL	READ		;READ TRACK 0/ SECTOR 1
	JR	NZ,DSKERR

	LD	HL,CONFIG
	SET	0,(HL)		;SET CONFIG BYTE FOR RAM AT 0000H
	LD	HL,DSKBUF
	LD	DE,0080H
	LD	BC,128
	CALL	MOVE		;COPY BOOT CP/M STANDARD LOCATION
	DI
	LD	SP,STACK
	LD	HL,ROLLIN
	PUSH	HL		;PUSH ADDRESS IN CASE BOOT RETURNS
	LD	HL,0080H
	PUSH	HL		;PUSH TRANSFER ADDRESS FOR 'EXITMON'
	JP	EXITMON		;TURN OFF ROMS AND EXECUTE LOADER
;
;
;
;
;	-- MEMORY DUMP COMMAND --
;
MEMDMP:	DEC	A		;CHECK PARAMETER COUNT
	JR	Z,MDMP2
	DEC	A
	JR	Z,MDMP3
MDMP1:	LD	HL,(LAST)
MDMP2:	LD	DE,16
	JR	MDMP3B

MDMP3:	EX	DE,HL
	SBC	HL,DE		;DERRIVE BYTECOUNT FOR DUMP RANGE
	LD	B,4
MDMP3A:	SRL	H		;DIVIDE BYTECOUNT BY 16
	RR	L
	DJNZ	MDMP3A
	INC	HL
	EX	DE,HL
MDMP3B:	CALL	DUMP		;DUMP DE*16 BYTES STRTING AT HL
	LD	(LAST),HL
	RET	
;
;
;
DUMP:	PUSH	HL		;SAVE STARTING ADDRESS
	CALL	PUT4HS		;PRINT STARTING ADDRESS IN HEX
	CALL	SPACE
	LD	B,16
DUMP2:	CALL	LOAD		;GET A DATA BYTE @ HL
	LD	A,C
	INC	HL
	CALL	PUT2HS		;PRINT THE DATA IN HEX
	DJNZ	DUMP2		;REPEAT 16 TIMES
	POP	HL		;RESTORE STARTING ADDRESS
	LD	B,16
DUMP3:	CALL	LOAD		;GET BACK DATA BYTE @ HL
	LD	A,C
	INC	HL
	RES	7,A
	CP	20H
	JR	C,DUMP4
	CP	7FH
	JR	C,DUMP5
DUMP4:	LD	A,'.'		;PRINT A DOT IF DATA < 20 OR > 7F
DUMP5:	CALL	OUTPUT		;PRINT ASCII CHARACTER IN A
	DJNZ	DUMP3
	CALL	CRLFS
	RET	NZ		;EXIT IF ESCAPE REQUEST IS INDICATED
	DEC	DE
	LD	A,D
	OR	E
	JR	NZ,DUMP
	RET
;
;
;	-- READ FROM INPUT PORT COMMAND --
;
INCMD:	DEC	A		;CHECK IF PARAMETER COUNT=1
	SCF
	RET	NZ
	LD	C,L		;POINT C TO INPUT PORT
IN1:	CALL	CRLFS
	LD	A,C
	CALL	PUT2HS
	IN	A,(C)
	CALL	PUT2HS
	CALL	ECHO
	CP	CR
	JR	Z,IN2
	CP	'-'
	JR	Z,IN3
	OR	A
	RET
 
IN2:	INC	C
	INC	C
IN3:	DEC	C
	JR	IN1
;
;
;
;	-- WRITE TO OUTPUT PORT COMMAND --
;
OUTCMD:	CP	2		;CHECK IF PARAMETER COUNT=2
	SCF
	RET	NZ
	LD	C,L		;POINT C TO OUTPUT PORT
	OUT	(C),E		;OUTPUT DATA PASSED IN E
	OR	A
	RET
;
;
;
;	-- MEMORY EXAMINE COMMAND --
;
VIEW:	CALL	MDATA
	CALL	ECHO
	CP	CR
	JR	Z,VIEW4
	CP	'-'
	JR	Z,VIEW5
	CP	','
	JR	NZ,VIEW2
	CALL	ECHO
	JR	VIEW3

VIEW2:	CALL	ASCHEX
	CCF	
	RET	NC
	RLCA	
	RLCA	
	RLCA	
	RLCA	
	LD	C,A
	CALL	ECHO
	CALL	ASCHEX
	CCF	
	RET	NC
	OR	C
VIEW3:	LD	C,A
	CALL	STORE
VIEW4:	INC	HL
	INC	HL
VIEW5:	DEC	HL
	JR	VIEW
;
;
;
;	-- JUMP TO MEMORY LOCATION COMMAND --
;
GOTO:	OR	A		;CHECK IF PARAMETER COUNT <> ZERO
	SCF
	RET	Z

	DI
	LD	SP,STACK
	LD	DE,ROLLIN
	PUSH	DE		;PUSH MONITOR ENTRY ADDRESS FOR RETURN
	PUSH	HL		;PUSH TRANSFER ADDRESS AFTER THAT
	LD	A,(PARAM2)
	LD	HL,(PARAM3)
	LD	DE,(PARAM4)
	LD	BC,(PARAM5)	;PUT REST OF PARAMS IN REGISTERS
	JP	EXITMON		;SET D/S BANKSWITCH AND EXIT MONITOR
;
;
;
;	-- MEMORY READ/WRITE DIAGNOSTIC COMMAND --
;
TEST:	CP	2		;CHECK PARAMETER COUNT
	SCF
	RET	NZ
	INC	DE
	LD	E,D		;GET ENDING PAGE ADDRESS INTO E
	LD	D,H		;GET STARTING PAGE ADDRESS INTO D
	LD	B,0		;INITIALIZE PASS COUNTER
TEST1:	LD	H,D		;POINT HL TO START OF BLOCK
	LD	L,0
TEST2:	CALL	MEMTEST		;CALL BANK-SWITCH MEMORY TEST ROUTINE
	JR	Z,TEST4		;DO ANOTHER PASS IF NO ERRORS
TEST3:	CALL	LOAD		;LOAD C WITH ERROR BYTE
	LD	A,L
	XOR	H
	XOR	B		;RE-GENERATE BYTE IN ERROR
	CALL	CHECK		;GO PRINT RESULT
	RET	NZ		;EXIT ROUTINE IF BREAK REQUESTED

	INC	HL
	LD	A,H
	CP	E
	JR	NZ,TEST3	;CHECK REST OF BLOCK FOR ERRORS
TEST4:	INC	B		;BUMP PASS COUNT
	LD	A,'+'
	CALL	OUTPUT		;PRINT '+' AND ALLOW FOR EXIT
	JR	Z,TEST1		;DO ANOTHER PASS IF NO ESCAPE
	RET
;
;
;
CHECK:	CP	C
	RET	Z		;RETURN IF C=A

	PUSH	AF
	CALL	MDATA		;PRINT WHAT WAS ACTUALLY READ
	CALL	PNEXT
	DEFM	'should='
	DEFB	EOT
	POP	AF
	CALL	PUT2HS		;PRINT WHAT SHOULD HAVE BEEN READ
	RET	
;
;
MDATA:	CALL	CRLFS
	CALL	PUT4HS
	CALL	LOAD
	LD	A,C
	CALL	PUT2HS
	RET	
;
;
;
;	-- FILL MEMORY WITH CONSTANT COMMAND --
;
FILL:	CP	3		;CHECK IF PARAMETER COUNT=3
	SCF	
	RET	NZ

	EX	DE,HL
	OR	A
	SBC	HL,DE		;END-START EQUALS BYTECOUNT
	EX	DE,HL
	RET	C
	RET	Z		;RETURN IF START => END ADDRESS

	CALL	STORE		;STORE C AT (HL) IN PROPER BANK
	LD	B,D
	LD	C,E		;PUT BYTECOUNT IN BC FROM DE
	LD	D,H
	LD	E,L
	INC	DE		;PUT START+1 IN DE
	CALL	MOVE		;FILL BLOCK USING LDIR TRICK
	OR	A
	RET
;
;
;
;
;	-- MEMORY BLOCK MOVE COMMAND --
;
BLOCK:	CP	3		;CHECK IF PARAMETER COUNT=3
	SCF	
	RET	NZ
	CALL	BLOCAD
	LD	A,C
	OR	B
	RET	Z		;EXIT NOW IF BC=0

	CALL	MOVE		;MOVE BLOCK WITH BANK SWITCH
	OR	A
	RET
;
;
;
BLOCAD:	EX	DE,HL
	OR	A		;CLEAR CARRY
	SBC	HL,DE		;GET DIFFRENCE BETWEEN
	EX	DE,HL		;HL & DE FOR BYTECOUNT
	PUSH	DE
	PUSH	BC
	POP	DE		;GET OLD BC INTO DE
	POP	BC
	INC	BC		;GET COUNT+1 INTO BC
	RET	
;
;
;
;	-- MEMORY BLOCK COMPARE COMMAND --
;
VERCMD:	CP	3		;CHECK IF PARAMETER COUNT=3
	SCF
	RET	NZ
	CALL	BLOCAD
	JR	VERF2

VERF1:	PUSH	BC
	EX	DE,HL
	CALL	LOAD		;READ BYTE @DE IN CURRENT BANK
	EX	DE,HL
	LD	B,C
	CALL	LOAD		;NOW READ BYTE @HL
	LD	A,B
	CALL	CHECK		;COMPARE DATA @DE AND @HL
	POP	BC
	RET	NZ		;EXIT IF ESCAPE REQUEST IS INDICATED
	INC	HL
	INC	DE
	DEC	BC
VERF2:	LD	A,B
	OR	C
	JR	NZ,VERF1
	RET
;
;
;
;	-- MEMORY BANK SWITCH COMMAND --
;
;
BANKSW:	CP	2
	CCF
	RET	C		;ERROR IF NOT PARAM COUNT NOT 0 OR 1
	OR	A
	JR	NZ,BANK2	;JUMP IF NEW PARAM ENTERED

	LD	A,(CONFIG)
	CALL	PUT2HS		;DISPLAY CURRENT 'CONFIG' BYTE
	OR	A
	RET
;
BANK2:	LD	A,L
	LD	HL,CONFIG
	XOR	(HL)		;COMPARE NEW CONFIG TO OLD SETTING
	BIT	1,A		;TEST IF STD/BB BIT IS DIFFERENT
	JR	Z,BANK2A	;EXIT IF NO CHANGE IN RAM BANK SWITCH

	DI			;NO INTERRUPTS WHILE COPYING MEMORY
	LD	A,(STDCPY)
	LD	E,A		;E=SOURCE BANK CONTROL BYTE
	XOR	00001000B
	LD	D,A		;OPPOSITE BANK GOES IN D
	LD	HL,MONITR	;ELSE MAKE SHADOOW COPY OF UPPER 4K
	LD	BC,4096		; OF RAM BEFORE SWITCHING BANKS
	CALL	SHADOW
	JR	NZ,BANK3	;JUMP IF BLOCK NOT COPIED CORRECTLY
	LD	A,D
	OUT	(PORT3),A	;SWITCH TO OPPOSITE BANK AND STAY
	LD	(STDCPY),A
	EI
BANK2A:	LD	A,(PARAM1)
	AND	00000011B
	LD	(CONFIG),A	;STORE NEW CONFIGURATION BITS
	RET
;
BANK3:	EI
	CALL	PNEXT
	DEFB	'ERR AT ',EOT
	CALL	PUT4HS
	OR	A
	RET
;
;
;
;
;	HL ... BLOCK POINTER
;	BC ... BYTECOUNT
;	 D ... DEST BANK CONTROL BYTE
;	 E ... SOURCE BANK CONTROL BYTE
;
SHADOW:
	LD	A,(HL)		;GET MEMORY BYTE FROM SOURCE BANK
	EX	AF,AF'
	LD	A,D
	OUT	(PORT3),A	;SWITCH TO DESTINATION MEMORY BANK
	EX	AF,AF'
	LD	(HL),A		;STORE DATA BYTE INTO DEST BANK
	CP	(HL)		;READ BACK FROM DEST AND COMPARE
	LD	A,E
	OUT	(PORT3),A	;SWITCH BACK TO SOURCE MEMORY BANK
	RET	NZ		;ABORT IF SOURCE <> DEST
	INC	HL
	DEC	BC
	LD	A,B
	OR	C
	JR	NZ,SHADOW
	RET
;
;
;
;********************************************************
;*							*
;*	CONSOLE I/O PACKAGE AND UTILITY ROUTINES	*
;*							*
;********************************************************
;
;
;
GETLIN:	LD	B,C		;SAVE MAX LINE LENGTH PARAMETER IN B
GLIN1:	CALL	ECHO		;GET A CHARACTER FROM THE CONSOLE
	CP	CR		;CHECK FOR CARRIAGE RETURN
	JR	Z,GLIN2
	CP	'H'-64		;CHECK FOR CTL-H BACKSPACE
	JR	Z,GLIN4
	CP	' '
	RET	C		;OTHER CONTROL CHARACTERS ARE ILLEGAL
	LD	(HL),A
	INC	HL		;STORE CHARACTER IN BUFFER
	DEC	C
	JR	NZ,GLIN1	;GET ANOTHER IF THERE'S MORE ROOM
	SCF	
	RET			;RETURN WITH CARRY=1 IF TOO
				;MANY CHARACTERS ARE ENTERED
GLIN2:	LD	(HL),A		;PUT CARRIAGE RETURN ON END OF LINE
	RET			;RETURN WITH CARRY BIT=0
 
GLIN4:	DEC	HL		;DELETE LAST CHARACTER FROM BUFFER
	CALL	PNEXT
	DEFB	' ','H'-64	;PRINT A SPACE TO OVERWRITE THE
	DEFB	EOT		; LAST CHARACTER, THEN DO A BACKSPACE
	INC	C
	LD	A,B		;MAKE SURE YOU'RE NOT TRYING TO
	SUB	C		;BACKSPACE PAST THE START OF THE LINE
	JR	NC,GLIN1
	RET	
;
;
;
SEARCH:	CPIR			;SEARCH TABLE @HL FOR MATCH WITH A
	RET	NZ		;EXIT NOW IF SEARCH FAILS
	ADD	HL,BC
	ADD	HL,BC		;ADD RESIDUE FROM CPIR BYTECOUNT
	ADD	HL,BC		; TO HL 3 TIMES TO GET POINTER
	LD	A,(HL)		; TO ADDRESS PART OF TABLE ENTRY
	INC	HL
	LD	H,(HL)
	LD	L,A
	RET			;EXIT WITH Z=1 TO INDICATE MATCH
;
;
;
;
PARAMS:	LD	BC,0
	LD	A,(IY+0)
	CP	CR		;CHECK IF LINE TERMINATES
	JR	NZ,PARA2	; IMMEDIATELY WITH A RETURN
	XOR	A
	RET			;RETURN WITH PARAM COUNT=0 IF SO
 
PARA1:	INC	C		;ADD 2 TO PARAM BUFFER INDEX IN BC
	INC	C
	LD	A,C
	CP	10
	CCF
	RET	C		;ERROR IF > 5 NUMBERS ENTERED
PARA2:	PUSH	BC		;SAVE PARAMETER COUNT
	CALL	GETHEX		;READ A NUMBER FROM LINE BUFFER
	POP	BC
	RET	C		;ERROR IF RESULT OVER 16 BITS
	LD	IX,PARAM1	;POINT TO PARAMETER STORAGE AREA
	ADD	IX,BC		;ADD PARAMETER COUNT IN BC
	LD	(IX+0),L
	LD	(IX+1),H	;STORE DATA RETURNED FROM 'GETHEX'
	CP	' '
	JR	Z,PARA1		;GET ANOTHER ITEM IF SPACE
	CP	','
	JR	Z,PARA1		;GET ANOTHER ITEM IF COMMA

	CP	CR
	SCF			;ELSE CHECK FOR CARRIAGE RETURN
	RET	NZ		; AND EXIT WITH CY=1 IF NOT
	LD	A,C
	SRL	A		;A=COUNT OF NUMBERS ENTERED
	INC	A
	RET
;
;
;
;
GETHEX:	LD	HL,0
	JR	GNUM3
	
GNUM1:	LD	B,4
GNUM2:	ADD	HL,HL		;MULTIPLY RESULT BY 16
	RET	C		;RETURN IF IT OVERFLOWS 16 BITS
	DJNZ	GNUM2
	LD	E,A		;APPEND NEW LOW ORDER DIGIT
	LD	D,0		;AND GET RESULT BACK INTO DE
	ADD	HL,DE
	RET	C		;RETURN IF OVERFLOW
GNUM3:	LD	A,(IY+0)	;GET A CHARACTER FROM LINE INPUT
	INC	IY		; BUFFER @ IY AND BUMP IY
	LD	C,A
	CALL	ASCHEX		;CONVERT ASCII TO NUMERIC
	JR	NC,GNUM1
	LD	A,C
	OR	A
	RET
;
;
ASCHEX:	SUB	'0'
	RET	C
	CP	10
	CCF
	RET	NC
	SUB	7
	CP	10
	RET	C
	CP	16
	CCF
	RET
;
;
;
PUT4HS:	LD	A,H
	CALL	PUT2HX
	LD	A,L
PUT2HS:	CALL	PUT2HX
	CALL	SPACE
	RET
;
;
PUT2HX:	PUSH	AF
	RRA	
	RRA	
	RRA	
	RRA	
	CALL	PUTNIB
	POP	AF
PUTNIB:	AND	00001111B
	ADD	A,90H
	DAA
	ADC	A,40H
	DAA
	CALL	OUTPUT
	RET	
;
;
;	PMSG PRINTS THE STRING OF ASCII CHARACTERS
;	POINTED TO BY THE RELATIVE ADDRESS IN DE
;	UNTIL AN EOT IS ENCOUNTERED IN THE STRING.
;
EOT	EQU	04H
CR	EQU	0DH
LF	EQU	0AH
;
	
PNEXT:	EX	(SP),HL
	CALL	PMSG
	EX	(SP),HL
	RET
;
PMSG:	LD	A,(HL)
	INC	HL
	CP	EOT
	RET	Z
	CALL	OUTPUT
	JR	PMSG
;
;
;
;	CRLFS OUTPUTS A RETURN-LINEFEED-SPACE
;	TO THE CONSOLE DEVICE
;
CRLFS:	CALL	PNEXT
	DEFB	CR,LF,EOT
SPACE:	LD	A,' '
	CALL	OUTPUT
	RET
;
;
;
;	ECHO INPUTS ONE CHARACTER FROM THE CONSOLE
;	DEVICE, PRINTS IT ON THE CONSOLE OUTPUT AND
;	THEN RETURNS IT IN REGISTER A WITH BIT 7 RESET
;
;	OUTPUT PRINTS THE CHARACTER IN REGISTER A ON
;	THE CONSOLE OUTPUT DEVICE AND THEN DOES A CHECK
;	FOR CONSOLE INPUT TO FREEZE OR ABORT OUTPUT.
;

ECHO:	CALL	CONIN		;INPUT A CHARACTER AND ECHO IT
	PUSH	AF
	CALL	CONOUT	
	POP	AF
	CP	'Z'+1
	RET	C
	SUB	32		;CONVERT UPPER CASE TO LOWER CASE
	RET
;
;
;
OUTPUT:	CALL	CONOUT
	CALL	CONST		;SEE IF CONSOLE INPUT IS PENDING
	JR	Z,OUTP2
	CALL	CONIN
	CP	CR		;SEE IF CARRIAGE RETURN WAS TYPED
	JR	Z,OUTP1
	CALL	CONIN		;WAIT FOR ANOTHER INPUT CHARACTER
	JR	OUTP2		; THEN RETURN TO CALLING ROUTINE

OUTP1:	LD	(BREAK),A	;SET ESCAPE FLAG TO NON-ZERO VALUE
OUTP2:	LD	A,(BREAK)
	OR	A		;RETURN CURRENT STATUS OF ESCAPE
	RET			; FLAG TO CALLING ROUTINE
;
;
;
;
