;
; CP/M on Vector MZ
;
; SYSTEM CONSOLE BIOS
; version (4.2) of 9/79
;
MSIZE	EQU	47			; memory size
;
USER:	ORG	MSIZE*1024+300H
;
TRUE	EQU	-1
FALSE	EQU	0
;
CENT	EQU	FALSE
DIAB	EQU	FALSE
TTY	EQU	TRUE
;
BBASE	EQU	4		; Bitstreamer base address
CPORT	EQU	BBASE+1		; Centronics parallel port
SDATA	EQU	BBASE+2		; serial data port
SSTAT	EQU	BBASE+3		; serial stat/cmd port
;
; the jump table
;
	JMP	COLDI		; cold initialization
	JMP	WARMI		; warm initialization
	JMP	STATI		; status input
	JMP	DATAI		; data input
	JMP	DATAO		; data output
	JMP	LISTO		; list output
	JMP	DATAO		; dummy punch output
	JMP	DATAI		; dummy reader input
;
; the cold initialization
;
COLDI:	XRA	A		; clear A
	STA	PRBYTE		; save in printer flag
	INR	A		; make initial i/o setting
	STA	IOBYTE		; save it too
;
; warm initialization
;
WARMI:
  IF DIAB OR TTY		; serial printers need init'ing
	XRA	A
	OUT	SSTAT		; send dummy chars
	OUT	SSTAT
	OUT	SSTAT
	MVI	A,40H
	OUT	SSTAT		; send reset cmd
	MVI	A,0CEH
	OUT	SSTAT		; send mode word
	MVI	A,27H
	OUT	SSTAT		; send cmd byte
  ENDIF
	RET			; return
;
; console status check
;
STATI:	LDA	LSTAT		; get last status
	ORA	A		; determine contents
	MVI	A,255		; set ready just in case
	RNZ			; return if ready
	CALL	XI		; get status/byte
	STA	LSTAT		; save status
	RZ			; return as is if not
	STA	LCHAR		; store as last character
	CMA			; else indicate available
	ORA	A		; set flags
	RET			; and return
;
; console input
;
DATAI:	CALL	STATI		; get status
	JZ	DATAI		; wait till char ready
	XRA	A		; set not ready
	STA	LSTAT		; in lstat
	LDA	LCHAR		; get character
	ANI	127		; make legible
	CPI	16		; ctl-P?
	JZ	ECHD		; handle
	CPI	11		; ^K ?
	JZ	OUTK		; handle
	CPI	08		; backspace?
	RNZ			; return if not
	MVI	A,7FH		; fake DEL
	RET
ECHD:	MOV	C,A		; set up for print
	CALL	DATAO		; console if not
	JMP	DATAI		; and ignor
OUTK:	CALL	LOUT1
	JMP	DATAI
;
; console output
;
DATAO:	MOV	A,C		; get character
	CPI	127		; DEL?
	RZ			; forget if so
	LDA	LCHAR		; get last character
	CPI	8		; backspace?
	JZ	CHKOTH		; leave there
	MOV	A,C		; else get char back
CHKOTH:	CPI	16		; ^P ?
	JZ	PROO
	CALL	XO		; send it
	LDA	PRBYTE		; get flag
	ANI	1		; printer on?
	MOV	A,C		; get char back
	RZ			; return if off
LNOTK:	CALL	LISTO		; output character
	RNZ			; return if not end-of-page
	MVI	C,12		; get formfeed
	CALL	LISTCH		; print it
	JMP	LSETL		; and continue
;
LOUT1:	MVI	C,12
LISTO:	CALL	LISTCH		; print character
	CPI	10		; linefeed?
	JZ	LFEED		; handle
	CPI	12		; formfeed?
	RNZ			; return if not
LSETL:	MVI	A,56		; l/p
	STA	LCT		; reset line counter
	MOV	A,C		; get char
	RET			; return
LFEED:
  IF DIAB			; only Diablo needs etx/ack
	MVI	C,3		; ETX char
	CALL	LISTCH		; send
LWAIT:	IN	SSTAT		; get status
	ANI	2		; RDA?
	JZ	LWAIT		; not yet
	IN	SDATA		; get character
	ANI	127		; zap bit 7
	CPI	6		; ack char?
	JZ	GOT6		; skip if so
	STA	LSTAT		; save 'char avail' status
	STA	LCHAR		; this is the char
	JMP	LWAIT		; and keep looping
GOT6:
  ENDIF
	LDA	LCT		; now get counter
	DCR	A		; shrink it
	STA	LCT		; resave it
	MOV	A,C		; get original character
	RET
;
PROO:	LDA	PRBYTE		; get flags
	XRI	1		; toggle printer
	STA	PRBYTE		; save
	MOV	A,C		; get character
	RET			; return
;
; list output
;
LISTCH:
  IF DIAB OR TTY		; this is for serial ptr
	IN	SSTAT		; get status
	ANI	1		; check ready bit
	JZ	LISTCH		; wait till ready
	MOV	A,C		; get character
	OUT	SDATA		; print it
  ENDIF
  IF CENT			; this is for Centronics
	IN	CPORT		; get status
	ANI	1		; busy?
	JNZ	LISTCH		; loop till not
	MOV	A,C		; get our character
	ORI	128		; set strobe
	OUT	CPORT		; output it
	ANI	127		; strobe off
	OUT	CPORT		; output
	ORI	128		; back on (pulsed)
	OUT	CPORT		; output
  ENDIF
	RET			; that's that
;
;
XI	EQU	0C0DCH		; input routine
XO	EQU	0C098H		; output routine
IOBYTE	EQU	3		; i/o control byte
PRBYTE:	DB	0		; printer flags
LCT:	DB	56		; line counter
LSTAT:	DB	0		; last status
LCHAR:	DB	0		; last character
;
