;
;	BYTE I/O
;
;	rev 02.20 krs 7/80	cp/m 2.0 et al
;	rev 02.31 rlr 10/22/80  esc eol problem
;	rev 02.32 rlr 11/13/80  no ctl-p on spool
;	rev 02.35 dew 10/81	macros
;	rev 02.36 rlr 12/30/81	C3 special
;	rev 02.37 krs 2/82	master version with fixes
;	REV 02.38 KRS 4/82	CONSOLE 7FH CHANGES
;	rev 02.39 sbw 8/5/82	Fix Z80 branch error
;       rev 02.41 blc 10/29/82  ROMable version
;                     12/15/82  fix control chars.
;
	icl	pdef		;02.39
	icl	df		;02.39
	df.dos			;02.39
	df.cpu			;02.39
	df.sys			;02.39
;
	NAM	BY238
	ENT	CSPIM,CWPIM,RDCNE
	ENT	SYC01,SYC02,SYC03,SYC04
	ENT	SYC05,SYC07,SYC08,SYC09
	ENT	SYC06,SYC10,SYC11
	ent	sycnul				;02.37
;
	EXT	URREG,SPLLST
	EXT	CSTAT,CIN,COUT,RIN,LOUT,POUT
	EXT	PRDY,LRDY,RSTAT
	EXT	DIV16,SAVAF,ABORT		;02.35
	EXT	SPLFG				;02.32
;
    ifc SYSUCB=SINGLE				;02.35
	EXT	?UDE,?UOPT,?UCHR,?UTAB		;02.37
    elsec
	EXT	RDUCB
    endc
;
;	CONTROL KEYS
;
LSTTG	EQU	'P'-'@'
PAUSE	EQU	'S'-'@'
ABTRQ	EQU	'C'-'@'
LSTON	EQU	'W'-'@'
LSTOF	EQU	'T'-'@'
DUMLN	EQU	'E'-'@'
REPEAT	EQU	'R'-'@'
CLRLN	EQU	'A'-'@'				;02.36
UNDER	EQU	5FH	; UNDERSCORE
CR	EQU	13
LF	EQU	10
TAB	EQU	9
ESC	EQU	1BH
SPC	EQU	20H
CANCL	EQU	'U'-'@'
RUBOT	EQU	7FH
BS	EQU	8
EOF	EQU	1AH	; ^Z
;02.31 - option byte flag values
OPTRAN	EQU	80H	; TRANSPARENT
OPNECHO	EQU	40H	; NO ECHO AT ALL
OPNRET	EQU	08	; NO RETURN
OPESC	EQU	4	; ESC AS TERM
OPCTLP	EQU	1	; CTL-P FLAG
;-- END 02.31 ADDS ---
;
;  CONSOLE STATUS PRIMATIVE
;	A=0 -NO CHAR, <>, THE CHAR
;	@HL= BUFFER (1 CHAR), DESTROYS D
;  TO CLEAR BUFF, FOLLOW WITH MVI M,0
;
CSPIM:	CALL	SPLLST	; CHECK FOR SPOOLER OUTPUT
	ADRUCB	CHR					;02.37
	PUSH	H	; IF CONSOLE STATUS=NO CHAR
	CALL	CSTAT
	POP	H
	PUSH	H
	ORA	A
	MOV	A,M	; THEN GET CHAR BUFFER
	BRZ	CSP0					;02.35
;
	CALL	CIN	; ELSE GET IT.
CSP0:	POP	H
	MVI	M,0	; CLEAR BUFFER IN CASE NOT USED
	ORA	A
	RZ		; NO CHAR
;
	MOV	D,A					;02.37
	PUSH	H
	ADRUCB	OPT					;02.37
	MOV	A,M	; GET OPTIONS			;02.37
	RLC		; 'TRANSPARENT' TO CARRY	 02.37
	BRC	CSP3	; BR IF ON			;02.37
	MOV	A,D					;02.37
	CPI	LSTTG
	BRNZ	CSP1					;02.35
;	(CTL-P):LIST-TOGGLE:TOGGLE LIST FLAG
	MOV	A,M					;02.20
	XRI	OPCTLP		; TOGLE IT		 02.31
	MOV	M,A		; PUT BAK		 02.20
	XRA	A	;RETURN NOT RDY
	POP	H
	RET
;
CSP1:	CPI	PAUSE
	BRNZ	CSP3					;02.35
;	(CTL-S): PAUSE
CSP2:	CALL	CIN	;WAIT FOR ANOTHER CHAR
	CPI	ABTRQ
	CZ	ABORT
	XRA	A
	POP	H
	RET
;
;	ELSE:	PUT CAR IN BUFFER @HL
CSP3:	POP	H
	MOV	M,D					;02.37
	MOV	A,D					;02.37
	RET
;
;  CONSOLE WRITE PRIMATIVE
;  DOES TAB EXPANSION/ALLOWS PAUSE
;  A=CHAR ON INPUT
;  SAVES HL,DE
CWPIM:	PUSH	H
	PUSH	D
;			'ANI 7FH' REMOVED		;02.38
	PUSH	PSW
	CALL	CSPIM	;HANDLE STATUS/PAUSE/ABORT
;
	ADRUCB	OPT					;02.37
	MOV	A,M					;02.30
	RLC		; 'TRANSPARANT' BIT TO CARRY	 02.30
	BRC	CWPTRS	; YES, GOON		02.30	;02.35
	POP	PSW	; LINE MOVED DOWN=====		 02.30
	CPI	LSTON
	BRNZ	CWP1					;02.35
;
	MVI	A,OPCTLP				;02.31
	ORA	M	;FORCE THE BIT ON		 02.20
	MOV	M,A	;AND BACK TO MEMORY		 02.20
	POP	D
	POP	H
	RET
;			ELSE
CWP1:	CPI	LSTOF	;IF CAR=LISTOFF
	BRNZ	CWP2					;02.35
	MOV	A,M	;GET THE BYTE			 02.20
	ANI	0FEH	;FORCE THE BIT OFF		 02.20
	MOV	M,A	;AND PUT BACK			 02.20
	POP	D
	POP	H
	RET	
;			ELSE OUTPUT CHAR
;
CWP2:	CPI	TAB	;ELSE IF CHAR=TAB		;02.37
	BRNZ	CWP3					;02.37
	ADRUCB	TAB					;02.37
;
;  THEN EXPAND TABULATION
;
	MOV	A,M	;GET LINE POSITION
	CMA
	ANI	7	;MOD 8
	INR	A	;0=MOVE 8, 7=MOVE 1
	MOV	E,A
CWP4:
	MVI	A,SPC
	CALL	COUTX
	DCR	E
	BRNZ	CWP4					;02.35
	POP	D
	POP	H
	RET
;
CWPTRS:	POP	PSW	; TRANSPARENT!			 02.30
CWP3:	ADRUCB	TAB					;02.37
	CPI	CR	;IF CHAR=RETURN
	BRNZ	CWPX	;THEN				;02.35
	MVI	M,0	;TABCT:=0
;	ELSE COUTX(CHAR)
CWPX:	CALL	COUTX
	POP	D
	POP	H
	RET
;
;  CONSOLE OUTPUT/TO LIST IF NESC.
;  ENTRY:  @HL=TAB COUNTER(CHAR POSITION)
;  SAVES HL,DE
;
COUTX0:	ADRUCB	TAB					;02.37
COUTX:	PUSH	D
	PUSH	H
	PUSH	PSW
	CALL	COUT	;COUT(CHR)
;
	LDA	SPLFG	;02.32 IF SPOOLING
	ORA	A	;02.32 THEN INHIBIT CTL-P
	BRNZ	COUTY					;02.35
;
COUTX1:	ADRUCB	OPT					;02.37
	MOV	A,M	; GET THE BYTE			 02.20
	ANI	OPCTLP	; TEST THE CTL-P BIT		 02.31
	BRZ	COUTY					;02.35
	CALL	CSPIM	;CHECK STATUS
	CALL	LRDY	; WAIT
	ORA	A	; UNTIL PRT RDY
	BRZ	COUTX1					;02.35
	POP	PSW	;THEN LOUT(CHAR)
	PUSH	PSW
	CALL	LOUT
;
COUTY:	POP	PSW
	POP	H
	POP	D
	CPI	SPC
	RM		; IF PRINTABLE
	INR	M	; THEN CHAR POSN:=*+1
	RET
;
;	SYSTEM CALLS (SYC #)
;
; 	READ CHAR/ NO ECHO (80H)
;
RDCNE:	CALL	CRPIM
	JMP	SAVAF					;02.37
;
;	READ CONSOLE /ECHO(1)
;
SYC01:	CALL	CRPIM
	CALL	SAVAF
; ECHO PRINTABLES & SPECIAL CONTROLS
	CPI	7
	BRZ	SY01A	; BELL				;02.35
	ORA	A
	BRZ	SY01A	; NUL				;02.35
	CPI	CR
	BRZ	SY01A	; CR				;02.35
	CPI	LF
	BRZ	SY01A					;02.35
	CPI	TAB
	BRZ	SY01A	; IF CHR=TAB			;02.35
	CPI	SPC
	RM		; OR CHR>=SPC
SY01A:	ADRUCB	OPT					;02.37
	MOV	C,A				;02.20
	CPI	CR				;02.20
	MOV	A,M				;02.20
	BRNZ	SY01A1				;02.20	;02.35
	ANI	OPNRET	; FLAG FOR NE OF CR	;02.31
	RNZ					;02.20
	MOV	A,M				;02.37
SY01A1:	ANI	OPNECHO	; ? NO ECHO		;02.31
	MOV	A,C				;02.20
	JZ	CWPIM	; THEN ECHO		;02.37
	RET
;
;	WRITE CONSOLE (2)
;
SYC02:	MOV	A,E
	JMP	CWPIM				;02.37
;
;	READ RDR (3)
;	WRITE PUN (4)
;	WRITE LIST (5)
; DEVICE STATUS CALLS PREVENT LOCKUP
;
SYC03:	CALL	CSPIM	;CHECK STATUS
	MOV	A,M
	CPI	DUMLN
	MVI	A,EOF	; LOOK LIKE EOF
	REQ		; FAKE RDY
	CALL	RSTAT	; WAIT UNTIL
	ORA	A	; READER RDY
	BRZ	SYC03					;02.35
	CALL	RIN
	JMP	SAVAF	;UR.AF:=GET(RDR)
;
SYC04:	PUSH	D	;*
SYC04A:	CALL	CSPIM	;* CHECK STATUS
	MOV	A,M
	CPI	DUMLN
	BREQ	SYC0X	; FAKE RDY			;02.35
	CALL	PRDY	; WAIT
	ORA	A	; UNTIL RDY
	BRZ	SYC04A					;02.35
	POP	D	;PUT(PUN):=UR.E
	MOV	A,E
	JMP	POUT
;
SYC05:	PUSH	D
SYC05A:	CALL	CSPIM	;CHECK STATUS
	MOV	A,M
	CPI	DUMLN
	BREQ	SYC0X	; FAKE RDY			;02.35
	CALL	LRDY	; WAIT
	ORA	A	; UNTIL PRT RDY
	BRZ	SYC05A					;02.35
	POP	D
	MOV	A,E
	JMP	LOUT
;
syc06:		; direct console i/o			 02.20
;		  e =  -2 then test ready		;02.37
;		  e =  -1 then read			;02.37
;			  else write			;02.37
	mov	a,e					;02.20
	cpi	-2					;02.37
	jlt	coutx0	; do write			;02.37
	push	d	; save request			;02.37
	call	cstat	; test ready			 02.20
	pop	d	; request back			;02.37
	ora	a					;02.20
	jz	sy11a	; 0, return not ready		 02.20
	mov	a,e					;02.37
	cpi	-2	; if -2, only return status	;02.37
	jeq	sy11b	; return ready			;02.37
	call	cin	; read data			;02.37
	jmp	savaf					;02.37
;
; DUMMY RDY LINE
SYC0X:	POP	D
	RET
;
;	READ I/O BYTE (7)
;	SET I/O BYTE (8)
;
IOBYT:	EQU	3
;
SYC07:	LDA	IOBYT
	CALL	SAVAF	;UR.AF:=IOBYTE
	RET
;
SYC08:	MOV	A,E
	STA	IOBYT	;IOBYTE:=UR.AF
	RET
;
;	PUT CONSOLE BUFFER (9)
;  ENTRY:  @DE=USER BUFFER
;  TERMINATED '$' OR NULL
;
SYCNUL:	MVI	L,0					;02.37
	BR	SYC9X					;02.37
;
SYC09:	MVI	L,'$'					;02.37
SYC9X:	LDAX	D
	CMP	L					;02.37
	RZ
	CALL	CWPIM
	INX	D
	BR	SYC9X					;02.37
;
;  READ CONSOLE BUFFER (10)
;  DELETE CHAR - RUBOUT (ECHO LAST CHAR)
;              - BS     (TRUE BACKSPACE)
;  CANCEL LINE - CONROL-U
;  ABORT       - CONTROL-C
;  ENTRY:  @DE=BUFFER (MAX,ACTUAL LENGTH)/DATA
;  EXIT:  ACTUAL SET/DATA TERMINATED BY NUL
;         IF TOO LONG, NO NUL/DON'T WAIT FORCR
;  NO LF AFTER CR ECHO'D (EVER)
;
SYC10:	XCHG
	SHLD	S10PTR	;SAVE LINE PTR			;02.36
SY10A:	MOV	E,M	;MAXCNT:=BUFFER SIZE
	MVI	D,0	;CNT:=0
	INX	H
	MOV	M,E	;BUFF.ACTUAL:=MAXCNT
	INX	H	;PTR=1ST DATA CHAR
;		MASTER LOOP
SY10B:	CALL	DOCRP					;02.38
SY10P:	MOV	B,A	;* A,B=GET CONSOLE
	CPI	DUMLN
	BRNZ	SY10K					;02.35
; FORCE NEW LINE (NO OTHER ACTION)
	CALL	CRLF
	BR	SY10B					;02.35
;
DOCRP:	PUSH	H		; CRPIM NO LONGER	 02.38
	PUSH	D		; SAVES REGISTERS	 02.38
	CALL	CRPIM					;02.38
	POP	D					;02.38
	POP	H					;02.38
	RET						;02.38
;
;  CONSOLE READ PRIMATIVE
;  A=CHAR
;  FOR TERMINALS WITH TRUE STATUS PORTS,
;  IF A CHAR ISN'T READY
;  CSPIM IS CALLED UNTIL A CHAR IN RECVD
;
CRPIM:	
CRP1:	CALL	CSPIM	;WAIT FOR
	ORA	A
	JZ	CRP1	;CHAR IN A
;
CRP2:	MVI	M,0	;CLEAR BUFFER
;		'ANI 7FH REMOVED	02.38
	RET
;
;	END
;
SY10K:	CPI	REPEAT
	BRNZ	SY10L					;02.35
; IF REPEAT REQ.
	CALL	SY10J	; SHOW REQ.
	CALL	CRLF	; NEW LINE
;
	MOV	A,D
	ORA	A
	BRZ	SY10B	; IF ANY TO REPEAT		;02.35
	PUSH	D
;
	LHLD	S10PTR	; THEN HL:=USER BUFFER		;02.36
	INX	H
	INX	H	; SKIP CNTR'S
;
SY10M:	MOV	A,M	; AND WHILE D>0
	CALL	SY10J	; DO PRINT (@HL)
;			PRINT CONTROL CHARS AS ^('@'+CHAR)
	INX	H	; HL+1
	DCR	D	; DE-1
	BRNZ	SY10M	; LEAVE HL@NEXT CHAR		;02.35
	POP	D	; RECOVER CNT
	BR	SY10B	; NEXT CHAR			;02.35
;
SY10L:	CPI	ABTRQ
	BRNZ	SY10C					;02.35
	CALL	SY10J	; ECHO ^C
	CALL	ABORT	;CTL-C=ABORT
	BR	SY10B					;02.35
;
SY10C:	CPI	CANCL
	BRNZ	SY10D					;02.35
;	CANCEL LINE
	CALL	SY10J	; ECHO ^U
	CALL	CRLF
;
	LHLD	S10PTR	;HL:=USER BUFFER		;02.36
	BR	SY10A	;RESTART			;02.35
;
SY10D:	MVI	C,1	; SINGLE CHAR BS		02.36
	CPI	'X'-'@'	;* Q, CONTROL-X
	BRZ	SY10E					;02.35
	CPI	UNDER
	BRZ	SY10E	; UNDERSCORE SAME AS BS		;02.35
	CPI	RUBOT	;* Q, RUBOUT
	BRZ	SY10E	;* YES				;02.35
	CPI	BS
	BREQ	SY10E	;BS				02.36
	CPI	CLRLN					;02.36
	BRNZ	SY10F					;02.35
	MVI	C,255	; CLR LINE (BACK TO PROMPT)	02.36
;	CHARACTER BACKSPACE
SY10E:
	MOV	A,D	;IF CNT>0
	ORA	A
	BRZ	SY10B					;02.35
	DCR	D	; CNT-1
	DCX	H	; PTR-1
;  THEN BACK UP
	MOV	A,B	;IF CHR=RUBOUT
	CPI	'X'-'@'	;*
	BRZ	SY10G	; THEN PUT(@PTR)		;02.35
;
	PUSH	B	; SAVE C=BS COUNT		02.36
	CALL	SY10Q	;* BACK UP 1 CHARACTER
	MOV	A,M	;* GET DELETED CHARACTER
	CPI	SPC	;* Q, IS IT A CONTROL CHAR
	CM	SY10Q	;* YES, BACK UP 1 MORE TIME     02.41
	POP	B	; GET C = BS COUNT		02.36
	DCR	C	; LOOP UNTIL C=0		02.36
	BRNZ	SY10E	;	OR START OF LINE	02.36
	JMP	SY10B	;* GO GET NEXT CHARCTER			;02.39
;
SY10G:	CALL	SY10R	;* PRINT '\\\'
SY10U:	MOV	A,M	;* GET CHARACTER
	CALL	SY10J	;* ECHO CHARACTER
SY10T:	CALL	DOCRP	;* GET NEXT INPUT CHAR		;02.38
	CPI	'X'-'@'	;* Q, CONTROL-X
	CNZ	SY10S	;* NO, PRINT '///'
	JNZ	SY10P	;* GO AWAY			;02.35
	MOV	A,D	;* Q, ANY MORE CHARACTERS
	ORA	A	;*
	BRZ	SY10T	;* NO, GET NEXT CHARACTER	;02.35
	DCR	D	;* COUNT DOWN
	DCX	H	;* DEC PTR
	BR	SY10U	;* GO ECHO CHARACTER		;02.35
;
SY10F:	CPI	CR
	BRZ	SY10F1				;02.20	;02.35
	CPI	LF				;02.20
	BRZ	SY10F1				;02.20	;02.35
	CPI	ESC				;02.20
	BRNZ	SY10H					;02.35
;02.31 check if ESC as eol is active
	PUSH	H				;02.20
	ADRUCB	OPT				;02.37
	MOV	A,M				;02.20
	POP	H				;02.20
	ANI	OPESC	;02.31 ESC AS EOL?
	BRNZ	SY10F1	;02.31 yes - do eol		;02.35
	MVI	B,ESC	;02.31 no - pass esc to normal
	BR	SY10H				;02.20	;02.35
;
;	LINE DONE
;
SY10F1:	PUSH	D	;02.31
	PUSH	H	;02.31
	ADRUCB	OPT				;02.37
	MOV	A,M	;02.31
	ANI	OPNRET	;02.31 IF NOT (FLAGGED FOR NE OF CR)
	MVI	A,CR	;02.31
	CZ	CWPIM	;02.31  THEN PUT (CR)
	POP	H	;02.31
	POP	D	;02.31
;
	MOV	A,D
	CMP	E	;IF FULL LINE
	RZ		;THEN DONE
	MVI	M,0	;ELSE TERMINATOR
;
	LHLD	S10PTR	; THEN HL:=USER BUFFER		;02.36
	INX	H
	MOV	M,D	;BUFF.ACT:=CNT
	RET		;DONE
;
        RAM                                           ; 02.41
S10PTR:	DW	0	;SAVE USER BUFFER PTR		02.36
;
;	VALID CHAR
;
        ROG
SY10H:
	MOV	A,E
	CMP	D
	RZ		;LINE TOO LONG
	MOV	M,B	;ELSE @PTR:=CHR
	INX	H	;PTR+1
	INR	D	;CNT+1
	MOV	A,B
	CALL	SY10J	; SHOW CHAR
	JMP	SY10B
;
;	PRINT CHAR ,IF COTROL SHOW '^'
;
SY10J:	PUSH	H					;02.20
	ADRUCB	OPT					;02.37
	MOV	C,A					;02.20
	MOV	A,M					;02.20
	ANI	OPNECHO					;02.31
	POP	H					;02.20
	MOV	A,C					;02.20
	RNZ						;02.20
	CPI	SPC
	JP	SY10I					;02.35
	PUSH	PSW
	MVI	A,'^'	; SHOW CONTROLS CHARS AS ^X
	CALL	CWPIM
	POP	PSW
	ORI	'@'	; SET TO PRINTABLE
SY10I:	JMP	CWPIM	; ECHO CHAR
;*
SY10Q:	MVI	A,BS	;* OUTPUT BACK SPACE
	CALL	CWPIM	;*
	MVI	A,SPC	;* OUTPUT A SPACE
	CALL	CWPIM	;*
	MVI	A,BS	;* OUTPUT BACKSPACE
	JMP	CWPIM	;*
;*
SY10R:	PUSH	PSW	;* SAVE PSW
	MVI	A,'\'	;* OUTPUT BACK SLASH
	BR	SY10X	;*				;02.35
;*
SY10S:	PUSH	PSW	;* SAVE PSW
	MVI	A,'/'	;* OUTPUT SLASH
SY10X:	CALL	CWPIM	;* OUTPUT CHARACTER
	CALL	CWPIM	;*
	CALL	CWPIM	;*
	POP	PSW	;* RESTORE PSW
	RET		;*
;
; RETURN/LINE FEED
;
CRLF:	MVI	A,CR
	CALL	CWPIM
	MVI	A,LF
	JMP	CWPIM					;02.35
;
;
;	CONSOLE STATUS (11)
;  EXIT:  UR.AF=0-BUSY, -1-RDY
SYC11:	CALL	CSPIM
	ORA	A
	BRZ	SY11A					;02.35
sy11b:	XRA	A					;02.37
	DCR	A					;02.37
SY11A:	JMP	SAVAF
;
	END
