;QUMEHANA.68K	JAN-16-87	(ALSO SEE "INFOSTR")
;Console handler for Qume QVT-101 terminal
;Written by Loren Blaney
;This is based on 6502 code written by P.J.R. Boyle.
;
;REVISION HISTORY:
;MAR-15-86, Original, written for DFM Engineering
;MAY-22-86, Converted to ASM68K conventions
;SEP-15-86, Modified
;NOV-26-86, Output device 1 is second terminal plugged into port 1.
; Input device 1 is still the unbuffered keyboard on the first terminal.
;DEC-11-86, Fix device 1 cursor to appear on the first terminal, etc.
;FEB-16-87, Modified for Amiga, converted to a single Qume QVT-101.
;
;NOTES:
;This console handler is still lacking CHKUSR. It differs from the Apple
; handler in that a <CR> does not erase the rest of the line, control
; characters are not echoed to the screen (because of Wyse - not me),
; null characters are ignored, the cursor pins at the limits rather than
; wraps around, tabs are not deleted correctly when using the "<--" key,
; CURSORX and CURSORY are not correct for lines greater than 80
; characters. This handler does not the have the <ESC> cursor commands
; of the Apple, but it does have a cleaner line delete (CTRL-X) and it
; has an undelete command (CTRL-Z).

	NOLIST
	INCLUDE	SYSPAG		;GET THE SYSTEM DEFINITIONS
	LIST

	ORG	MEMTOP -$1700
START	EQU	@		;ADDRESS WHERE THIS HANDLER STARTS

;======================================================================
;BUFFERED CONSOLE HANDLER (DEVICE #0)
;
CONHAN0	DC.L	OPENI0		;0 = OPENI
	DC.L	OPENO0		;1 = OPENO
	DC.L	CHIN0		;2 = CHIN
	DC.L	CHOUT0		;3 = CHOUT
	DC.L	CLOSE0		;4 = CLOSE
	DC.L	GETINFO		;5 = GETINFO
	DC.L	DUMMY		;6 = SPARE
	DC.L	CURSOR1		;7 = POSITION CURSOR OF CURRENT DEVICE
	DC.L	DUMMY		;8
	DC.L	DUMMY		;9
	DC.L	DUMMY		;10
	DC.L	SHOCUR		;11 = TURNS THE CURSOR ON/OFF FOR DEVICE
	DC.L	BUTES		;12 = SET DISPLAY ATTRIBUTES FOR DEVICE

;----------------------------------------------------------------------
;OPEN (INITIALIZE) THE BUFFERED KEYBOARD FOR INPUT.
; THIS WILL DISCARD ANY CHARACTERS IN THE BUFFER AND ANY PENDING
;  CHARACTERS FROM THE KEYBOARD.
;
OPENI0	MOVE.L	#LINBUF,LINPTRF	;RESET LINE BUFFER FILL & EMPTY POINTERS
	MOVE.L	#LINBUF,LINPTRE
	BRA	OPENI1		;(PBRA) ALSO OPEN UNBUFFERED KEYBOARD

;----------------------------------------------------------------------
;OPEN (INITIALIZE) BUFFERED TERMINAL FOR OUTPUT
;
OPENO0	BSR	OPEN
	BRA	CRLF1		;(PBRA)

;----------------------------------------------------------------------
;GET A CHARACTER FROM THE BUFFERED KEYBOARD AND RETURN IT IN D0.
;THE BUFFERED KEYBOARD HANDLES THE FOLLOWING CONTROL CHARACTERS:
; <-- (CTRL-H):	DELETE BACK ONE CHARACTER
; --> (CTRL-U): MOVE CURSOR FORWARD ONE CHARACTER
; DEL:		DELETE BACK ONE CHARACTER (SAME AS CTRL-H)
; CTRL-X:	DELETE THE ENTIRE LINE
; CTRL-Z:	UNDELETE THE LINE
; WARNING: THE "<--" AND "DEL" KEYS WILL NOT HANDLE TABS CORRECTLY.
;
CHIN0	MOVEM.L	A0/A1,-(SP)	;SAVE REGISTERS
	MOVEA.L	LINPTRF,A0	;GET THE LINE BUFFER POINTERS
	MOVEA.L	LINPTRE,A1

	CMPA.L	A0,A1		;DOES FILL POINTER = EMPTY POINTER?
	BNE.S	CHIN010		;BRANCH IF NOT
	BSR.S	FILLBUF		;GET A LINE OF CHARACTERS FROM KEYBOARD
CHIN010	CLR.L	D0
	MOVE.B	(A1)+,D0	;GET CHARACTER AT EMPTY POINTER

	MOVE.L	A0,LINPTRF	;SAVE THE POINTERS
	MOVE.L	A1,LINPTRE
	MOVEM.L	(SP)+,A0/A1	;RESTORE REGISTERS
	RTS

;----------------------------------------------------------------------
;GET A LINE OF CHARACTERS FROM THE KEYBOARD AND PUT THEM INTO "LINBUF".
; REGISTERS D0, A0, AND A1 ARE DESTROYED.
;
FILLBUF	MOVEA.L	#LINBUF,A0	;RESET THE POINTERS TO THE START OF
	MOVEA.L	A0,A1		; THE LINE BUFFER

FB00	BSR	GETKEYX		;GET CHARACTER FROM KEYBOARD
				; (CHECK CTRL-C, ETC.)
	CMPI.B	#DEL,D0		;IS IT A DELETE CHARACTER?
	BEQ.S	FB05		;BRANCH IF IT IS
	CMPI.B	#BS,D0		;IS IT A BACKSPACE (BACK ARROW)?
	BNE.S	FB10		;BRANCH IF NOT
FB05	CMPA.L	#LINBUF,A0	;ARE WE AT THE BEGINNING OF THE BUFFER?
	BEQ.S	FB00		;BRANCH IF SO (DON'T DELETE ANYTHING)
	SUBQ.L	#1,A0		;BACK UP 1 CHARACTER IN THE LINE BUFFER
	MOVEQ	#BS,D0		;DELETE THE CHARACTER ON THE SCREEN
	BSR	CHOUT1		;BACK UP
	MOVEQ	#SPACE,D0	;SPACE IT OUT
	BSR	CHOUT1
	MOVEQ	#BS,D0		;BACK UP
	BSR	CHOUT1
	BRA	FB00		;GO GET NEXT KEYSTROKE

FB10	CMPI.B	#FWDSP,D0	;FORWARD (RIGHT) ARROW?
	BNE.S	FB20		;BRANCH IF NOT
	CMPI.B	#CR,(A0)	;ARE WE AT THE END OF THE INPUT LINE?
	BEQ.S	FB00		;BRANCH IF WE ARE (IGNORE IT)
	CMPA.L	#LINBUFE,A0	;ARE WE BEYOND THE END OF THE BUFFER?
	BHS.S	FB00		;BRANCH IF WE ARE (IGNORE IT)
	MOVE.B	(A0)+,D0	;ECHO CHAR TO MOVE FORWARD ON SCREEN
	BSR	CHOUT1
	BRA.S	FB00		;GO GET NEXT KEYSTROKE

FB20	CMPI.B	#'X'-CTRL,D0	;CTRL-X (LINE DELETE)?
	BNE.S	FB30		;BRANCH IF NOT
	BSR	DELLINE		;DELETE THE LINE
	BRA.S	FB00

FB30	CMPI.B	#'Z'-CTRL,D0	;CTRL-Z (REGURGE PREVIOUS LINE BUFFER)?
	BNE.S	FB50		;BRANCH IF NOT
	BSR	DELLINE		;DELETE ANYTHING ON THE LINE & RESET A0
FB35	MOVE.B	(A0),D0		;GET CHARACTER FROM PREVIOUS BUFFER
	CMPI.B	#CR,D0		;IS IT A CARRIAGE RETURN?
	BEQ.S	FB00		;BRANCH IF YES, WE'RE DONE
	BSR	CHOUT1		;ECHO THIS CHARACTER
	CMPA.L	#LINBUFE,A0	;ARE WE BEYOND THE END OF THE BUFFER?
	BHS.S	FB00		;BRANCH IF YES, WE'RE DONE
	ADDQ.L	#1,A0		;INCREMENT FILL POINTER
	BRA.S	FB35		;LOOP UNTIL DONE

;THE LAST CHARACTER IN THE LINE BUFFER MAY BE A <CR> BUT ANYTHING ELSE
; IS AN ERROR.
FB50	MOVE.B	D0,(A0)+	;ALWAYS STORE THE CHARACTER
	CMPI.B	#CR,D0		;WAS IT A CARRIAGE RETURN?
	BEQ.S	FB90		;EXIT IF IT WAS
	CMPA.L	#LINBUFE-1,A0	;IS THE BUFFER FULL? (LEAVE ROOM FOR CR)
	BLO.S	FB85		;BRANCH IF IT IS NOT - GO ECHO CHAR
FB80	SUBQ.L	#1,A0		;MOVE FILL POINTER BACK
	MOVEQ	#BEL,D0		;BUFFER IS FULL SO JUST BEEP
FB85	BSR	CHOUT1
	BRA	FB00		;LOOP UNTIL CARRIAGE RETURN

FB90	BSR	CHOUT1		;ECHO THE CARRIAGE RETURN
	RTS

;----------------------------------------------------------------------
;DELETE THE LINE BUFFER.
; THIS DELETES IT FROM THE SCREEN AND RESETS THE FILL POINTER (A0) TO
; THE BEGINNING OF THE BUFFER.
; REGISTER D0 IS DESTROYED.
;
DELLINE	CMPA.L	#LINBUF,A0	;ARE WE AT THE BEGINNING OF THE BUFFER?
	BEQ.S	DELL90		;BRANCH IF WE ARE - WE'RE ALL DONE
	SUBQ.L	#1,A0		;BACKUP ONE CHARACTER IN THE LINE BUFFER
	MOVEQ	#BS,D0		;DELETE THE CHARACTER ON THE SCREEN:
	BSR	CHOUT1		; BACK UP
	MOVEQ	#SPACE,D0	; SPACE IT OUT
	BSR	CHOUT1
	MOVEQ	#BS,D0		; BACK UP
	BSR	CHOUT1
	BRA.S	DELLINE		;LOOP FOR ALL CHARACTERS

DELL90	RTS

;----------------------------------------------------------------------
;OUTPUT CHARACTER IN D0 TO THE TERMINAL
;
CHOUT0	BRA	CHOUT1		;(PBRA) SAME AS FOR DEVICE # 1

;----------------------------------------------------------------------
;CLOSE THE TERMINAL
;
CLOSE0	BRA	CLOSE1		;(PBRA) SAME AS FOR DEVICE # 1

;======================================================================
;UNBUFFERED CONSOLE HANDLER (DEVICE #1)
;
CONHAN1	DC.L	OPENI1		;0 = OPENI
	DC.L	OPENO1		;1 = OPENO
	DC.L	CHIN1		;2 = CHIN
	DC.L	CHOUT1		;3 = CHOUT
	DC.L	CLOSE1		;4 = CLOSE
	DC.L	GETINFO		;5 = GET INFO
	DC.L	DUMMY		;6 = SPARE
	DC.L	CURSOR1		;7 = POSITION CURSOR
	DC.L	CHKUSR		;8 = CHECK FOR CTRL-C, CTRL-S, CTRL-P
	DC.L	GETKEYZ		;9 = WAIT FOR AND RETURN A KEY'S VALUE
	DC.L	KEYHIT		;10 = D0 = 'TRUE' IF KEY WAS HIT
	DC.L	SHOCUR		;11 = TURNS THE CURSOR ON/OFF
	DC.L	BUTES		;12 = SET DISPLAY ATTRIBUTES

;----------------------------------------------------------------------
;OPEN (INITIALIZE) KEYBOARD FOR INPUT.
; THIS WILL DISCARD ANY PENDING CHARACTERS FROM THE TERMINAL
;
OPENI1	BSR	OPEN
	MOVE.L	D0,-(SP)	;SAVE D0
	MOVE.B	DEVICE,-(SP)	;SAVE DEVICE NUMBER

	CLR.B	DEVICE		;CURSOR SHOULD ONLY APPEAR ON DEVICE 0
	MOVEQ	#FALSE,D0	;TURN OFF THE CURSOR FLASHER
	BSR	SHOCUR

OPI105	BSR	KEYHIT		;IS A KEY PRESSED?
	BEQ.S	OPI110		;BRANCH IF NOT
	BSR	GETKEYX		;IF SO, EAT IT (CHECK FOR CTRL-C, ETC)
	BRA.S	OPI105		;LOOP UNITL ALL CHARACTERS ARE FLUSHED

OPI110	MOVE.B	(SP)+,DEVICE	;RESTORE DEVICE NUMBER
	MOVE.L	(SP)+,D0	;RESTORE D0
DUMMY	RTS

;----------------------------------------------------------------------
;OPEN (INITIALIZE) TERMINAL SCREEN FOR OUTPUT.
;
OPENO1	MOVE.L	D0,-(SP)	;SAVE D0

	BSR	OPEN
	MOVEQ	#FALSE,D0	;TURN OFF THE CURSOR FLASHER
	BSR	SHOCUR
	BSR	CRLF1

	MOVE.L	(SP)+,D0	;RESTORE D0
	RTS

;----------------------------------------------------------------------
;GET A CHARACTER FROM THE KEYBOARD, ECHO IT, AND RETURN IT IN D0.
;
CHIN1	MOVE.B	DEVICE,-(SP)	;SAVE DEVICE NUMBER
	CLR.B	DEVICE		;ECHO ON THE FIRST TERMINAL
	BSR	GETKEYX		;GET THE CHAR (CHECK FOR CTRL-C, ETC.)
	BSR.S	CHOUT1		;ECHO IT
	MOVE.B	(SP)+,DEVICE	;RESTORE DEVICE NUMBER
	RTS

;----------------------------------------------------------------------
;OUTPUT THE CHARACTER IN D0 TO THE SELECTED TERMINAL (DEVICE # 0 OR 1).
; HANDLE SOME SPECIAL CHARACTERS: NUL, TAB, CR, & FF.
;
CHOUT1	CMPI.B	#$20,D0
	BHS.S	CHO170

	CMPI.B	#NUL,D0		;IS IT A NULL CHARACTER?
	BNE.S	CHO110		;BRANCH IF NOT
	RTS			;IGNORE NULLS

CHO110	CMPI.B	#TAB,D0		;IS IT A TAB CHARACTER?
	BNE.S	CHO120		;BRANCH IF NOT
	BRA	DOTAB		;(PBRA) DO TAB AND RETURN

CHO120	CMPI.B	#CR,D0		;IS IT A CARRIAGE RETURN?
	BNE.S	CHO130		;BRANCH IF NOT
	BRA	CRLF1		;(PBRA) START A NEW LINE

CHO130	CMPI.B	#FF,D0		;IS IT A FORM FEED?
	BNE.S	CHO150		;BRANCH IF NOT
	BRA	HOMER		;(PBRA) DO HOME ERASE AND RETURN

CHO150	CMPI.B	#LF,D0		;IS IT A LINE FEED?
	BNE.S	CHO155		;BRANCH IF NOT
	RTS			;IGNORE IT (THESE ARE STILL A PROBLEM)

CHO155	CMPI.B	#'Z'-CTRL,D0	;IS IT A CTRL-Z?
	BNE.S	CHO160		;BRANCH IF NOT
	MOVEQ	#'#',D0		;CHANGE IT TO A POUND SIGN BECAUSE
	BRA.S	CHO170		; A CTRL-Z WILL BLANK THE SCREEN

CHO160	CMPI.B	#BS,D0		;IS IT A BACKSPACE?
	BNE.S	CHO170		;BRANCH IF NOT
	MOVE.L	A6,-(SP)	;SAVE A6
	MOVEA.W	DEVICE-1,A6	;DEVICE NUMBER IS AN INDEX
	SUBQ.B	#1,CURSORX(A6)	;DECREMENT X POSITION FOR CURRENT DEVICE
	MOVEA.L	(SP)+,A6	;RESTORE A6
	BRA	BYTEOUT		;(PBRA) OUTPUT THE CHARACTER AND RETURN

CHO170	MOVE.L	A6,-(SP)	;SAVE A6
	MOVEA.W	DEVICE-1,A6	;DEVICE NUMBER IS AN INDEX
	ADDQ.B	#1,CURSORX(A6)	;BUMP X POSITION FOR CURRENT DEVICE
	MOVEA.L	(SP)+,A6	;RESTORE A6
	BRA	BYTEOUT		;(PBRA) OUTPUT THE CHARACTER AND RETURN

;----------------------------------------------------------------------
;CLOSE THE TERMINAL (NOTHING REQUIRED)
;
CLOSE1	RTS

;----------------------------------------------------------------------
;RETURN THE ADDRESS OF THE INFORMATION ARRAY IN D0
;
GETINFO	MOVE.L	#INFO,D0
	RTS

INFO	DC.L	START		;STARTING AND ENDING ADDRESSES OF
	DC.L	END		; THIS HANDLER
	DC.L	INFOSTR		;DESCRIPTION
	DC.L	80		;COLUMNS
	DC.L	24		;LINES
INFOSTR	ASCII	'QUMEHANA  FEB-16-87  Qume QVT-101 terminal, 9600 bau'
	DC.B	'd' + $80

;----------------------------------------------------------------------
;POSITION THE CURSOR TO X,Y FOR THE CURRENT DEVICE (0 OR 1)
; X = COLUMN =	HIGH BYTE OF D0
; Y = LINE =	LOW BYTE OF D0
;
CURSOR1	MOVEM.L	D0/A6,-(SP)	;SAVE REGISTERS
	MOVEA.W	DEVICE-1,A6	;DEVICE NUMBER IS AN INDEX

	CMPI.B	#24,D0		;UNPACK X AND Y COORDINATES
	BLO.S	CUR10		;HANDLE OUT OF RANGE VALUES
	MOVE.B	#23,D0		;MAX LINE = 23
CUR10	MOVE.B	D0,CURSORY(A6)	;GET LINE NUMBER (DON'T USE MOVEQ)
	LSR.W	#8,D0		;GET X COORDINATE
	CMPI.B	#80,D0		;OUT OF RANGE?
	BLO.S	CUR20		;BRANCH IF NOT
	MOVE.B	#79,D0		;SET MAXIMUM X VALUE
CUR20	MOVE.B	D0,CURSORX(A6)
	MOVEQ	#ESC,D0		;SEND COMMAND TO WYSE (LINE, COLUMN):
	BSR	BYTEOUT		; <ESC> = (Y+$20) (X+$20)
	MOVEQ	#'=',D0
	BSR	BYTEOUT
	MOVEQ	#$20,D0
	ADD.B	CURSORY(A6),D0
	BSR	BYTEOUT
	MOVEQ	#$20,D0
	ADD.B	CURSORX(A6),D0
	BSR	BYTEOUT

	MOVEM.L	(SP)+,D0/A6	;RESTORE REGISTERS
	RTS

;----------------------------------------------------------------------
;CHECK FOR AND HANDLE CTRL-S, CTRL-P, AND CTRL-C
;
CHKUSR	BSR	KEYHIT		;WAS A KEY PRESSED?
	BEQ.S	CU90		;BRANCH IF NOT (EXIT)
;SAMPLE KEYSTROKE SUCH THAT IT MAY BE RE-READ LATER	????
	ANDI.B	#$7F,D0		;MAKE SURE MSB IS CLEAR
	CMPI.B	#'C'-CTRL,D0	;EXIT PROGRAM IF IT'S A CTRL-C
	BEQ.S	XVEXIT
	CMPI.B	#'P'-CTRL,D0	;ABORT IF IT'S A CTRL-P
	BEQ.S	XVABORT
CU90	RTS

XVEXIT	JMP	VEXIT
XVABORT	JMP	VABORT

;----------------------------------------------------------------------
;GET A CHARACTER FROM THE KEYBOARD (OR COMMAND FILE) AND RETURN IT IN D0
; CHECK FOR CTRL-C, ETC. "DEVICE" MUST BE 0.
;
GETKEYX	MOVEQ	#TRUE,D0	;TURN ON THE CURSOR FLASHER
	BSR	SHOCUR

	BSR	GETKEYZ		;GET THE CHARACTER (FROM THE KEYBOARD
				; OR FROM A .CMD FILE)
	MOVE.L	D0,-(SP)
	MOVEQ	#FALSE,D0	;TURN OFF THE CURSOR FLASHER
	BSR	SHOCUR
	MOVE.L	(SP)+,D0

	CMPI.B	#'C'-CTRL,D0	;EXIT PROGRAM IF IT'S A CTRL-C
	BEQ.S	XVEXIT
	CMPI.B	#'P'-CTRL,D0	;ABORT IF IT'S A CTRL-P
	BEQ.S	XVABORT
	RTS

;----------------------------------------------------------------------
;GET A CHARACTER FROM THE KEYBOARD OR COMMAND FILE AND RETURN IT IN D0.
; COMMAND (.CMD) FILES ARE INITIATED BY APEX.XPL (DOCMD), WHICH FILLS
; THE COMMAND BUFFER (CMDBUF) WITH THE CHARACTERS AND SETS THE "CMDMOD" 
; FLAG. THE COMMAND BUFFER PHYSICALLY OCCUPIES THE SAME SPACE AS THE
; KEYBOARD BUFFER, BUT THEY ARE LOGICALLY TWO SEPARATE BUFFERS.
;
GETKEYZ	TST.B	CMDMOD		;ARE WE IN COMMAND MODE?
	BEQ.S	GKZ20		;BRANCH IF NOT

	MOVE.L	A6,-(SP)	;GET CHARACTER FROM COMMAND BUFFER
	MOVEA.L	CMDPTR,A6	; AT "CMDPTR"
	MOVEQ	#0,D0
	MOVE.B	(A6)+,D0	;BUMP POINTER AND SAVE IT
	MOVE.L	A6,CMDPTR
	MOVEA.L	(SP)+,A6
	CMPI.B	#EOF,D0		;IS THIS THE END OF THE COMMAND FILE?
	BNE.S	GKZ90		;BRANCH IF NOT -- EXIT WITH CHAR IN D0
	MOVE.B	FALSE,CMDMOD	;TURN OFF COMMAND MODE

GKZ20	BSR	BYTEIN		;GET THE CHARACTER FROM KEYBOARD
GKZ90	RTS

;----------------------------------------------------------------------
;SPACE OVER TO NEXT TAB STOP
;
DOTAB	MOVEM.L	D0/A6,-(SP)	;SAVE REGISTERS
	MOVEA.W	DEVICE-1,A6	;DEVICE NUMBER IS AN INDEX

DOTAB10	MOVEQ	#SPACE,D0	;OUTPUT A SPACE CHARACTER
	BSR	BYTEOUT
	ADDQ.B	#1,CURSORX(A6)	;BUMP X POSITION
	MOVE.B	CURSORX(A6),D0	;ARE WE AT THE NEXT TAB STOP?
	ANDI.B	#$07,D0
	BNE.S	DOTAB10		;BRANCH IF NOT

	MOVEM.L	(SP)+,D0/A6	;RESTORE REGISTERS
	RTS

;----------------------------------------------------------------------
;CLEAR SCREEN AND HOME TO UPPER LEFT CORNER
;
HOMER	MOVEM.L	D0/A6,-(SP)	;SAVE REGISTERS
	MOVEA.W	DEVICE-1,A6	;DEVICE NUMBER IS AN INDEX

	MOVEQ	#'Z'-CTRL,D0	;THE WYSE USES CTRL-Z TO DO A CTRL-L
	BSR	BYTEOUT
	CLR.B	CURSORX(A6)	;RESET POSITION TO 0,0
	CLR.B	CURSORY(A6)

	MOVEM.L	(SP)+,D0/A6	;RESTORE REGISTERS
	RTS

;----------------------------------------------------------------------
;START A NEW LINE ON THE TERMINAL
;
CRLF1	MOVEM.L	D0/A6,-(SP)	;SAVE REGISTERS
	MOVEA.W	DEVICE-1,A6	;DEVICE NUMBER IS AN INDEX

	MOVEQ	#CR,D0		;OUTPUT A CARRIAGE RETURN
	BSR	BYTEOUT
	CLR.B	CURSORX(A6)	;RESET X POSITION TO 0
	MOVEQ	#LF,D0		;OUTPUT A LINE FEED
	BSR	BYTEOUT
	MOVE.B	CURSORY(A6),D0	;ARE WE ON THE BOTTOM LINE?
	CMPI.B	#23,D0
	BHS.S	CRLF110		;BRANCH IF WE ARE (WE SCROLL)
	ADDQ.B	#1,CURSORY(A6)	;ELSE, MOVE DOWN A LINE

CRLF110	MOVEM.L	(SP)+,D0/A6	;RESTORE REGISTERS
	RTS

;----------------------------------------------------------------------
;ROUTINE TURN THE CURSOR INDICATOR ON OR OFF FOR THE CURRENT DEVICE.
; IF D0 # 0 (TRUE), THE CURSOR IS TURNED ON
;
SHOCUR	MOVE.L	D0,-(SP)	;SAVE D0

	MOVEQ	#ESC,D0		;SEND <ESC>"."
	BSR	BYTEOUT
	MOVEQ	#".",D0
	BSR	BYTEOUT

	MOVEQ	#'0',D0		;ASSUME IT IS OFF
	TST.L	(SP)		;CHECK FLAG
	BEQ.S	SHC10		;BRANCH IF OFF
	MOVEQ	#'1',D0		;TURN IT ON
SHC10	BSR	BYTEOUT

	MOVE.L	(SP)+,D0	;RESTORE D0
	RTS

;----------------------------------------------------------------------
;SET THE DISPLAY ATTRIBUTES FOR THE CURRENT DEVICE ACCORDING TO D0.
; D0 CONTAINS A 4-BIT ARRAY
; (THE TERMINAL SHOULD BE SET UP SO THAT ATTRIBUTES ARE ACTIVE TO THE
; END OF THE PAGE.)
;WARNING: THIS DOESN'T WORK VERY WELL BECAUSE THE BRAIN-DAMAGED TERMINAL
; INSERTS A SPACE CHARACTER WHENEVER CHANGING THE DISPLAY ATTRIBUTE.
;
BUTES	MOVE.L	D0,-(SP)	;SAVE D0

	MOVEQ	#ESC,D0		;SEND <ESC>"G"
	BSR	BYTEOUT
	MOVEQ	#'G',D0
	BSR	BYTEOUT

	MOVE.L	(SP),D0		;GET ARGUMENT
	MOVE.B	BUTETBL-@-2(PC,D0),D0 ;GET ATTRIBUTE CODE FROM TABLE
	BSR	BYTEOUT		;SEND IT

	MOVE.L	(SP)+,D0	;RESTORE D0
	RTS

;TABLE OF ATTRIBUTE CODES:
; D = DIM (NOT BOLD), U = UNDERLINE, I = INVERSE VIDEO, F = FLASHING
BUTETBL	DC.B	$70		;- - - D
	DC.B	$30		;- - - -
	DC.B	$78		;- - U D
	DC.B	$38		;- - U -
	DC.B	$74		;- I - D
	DC.B	$34		;- I - -
	DC.B	$7C		;- I U D	:-)
	DC.B	$3C		;- I U -
	DC.B	$72		;F - - D
	DC.B	$32		;F - - -
	DC.B	$7A		;F - U D
	DC.B	$3A		;F - U -
	DC.B	$76		;F I - D
	DC.B	$36		;F I - -
	DC.B	$7E		;F I U D
	DC.B	$3E		;F I U -

;======================================================================
;LOWEST LEVEL I/O ROUTINES:
;
SERDATR	EQU	$DFF018		;Serial port data and status register
SERDAT	EQU	$DFF030		;Serial port data register (write)
SERPER	EQU	$DFF032		;Serial port period and control register
INTREQ	EQU	$DFF09C		;Interrupt request (status) bits

;----------------------------------------------------------------------
;Routine to initialize RS-232 I/O.
;
OPEN	MOVE.W	#$0174,SERPER.L	;Set 8 bits, 9600 baud
	MOVE.W	#$0800,INTREQ.L	;Clear "receive buffer full" status bit
	RTS

;----------------------------------------------------------------------
;Routine to wait for then return the value of a byte in D0.
;
BYTEIN	MOVE.W	SERDATR.L,D0	;Read status and data
	ADDQ.L	#1,HASH		;Spin the randomizer while we wait
	BTST	#14,D0		;Receive buffer full
	BEQ.S	BYTEIN		;Loop if not
	MOVE.W	#$0800,INTREQ.L	;Clear "receive buffer full" status bit
		
	ANDI.L	#$000000FF,D0	;Return byte in D0
	RTS

;----------------------------------------------------------------------
;Routine to output the byte in D0 to an RS-232 port.
;
BYTEOUT	MOVEM.W	D0-D1,-(SP)	;Save low word of registers

BYO10	MOVE.W	SERDATR.L,D1	;Get serial port status
	BTST	#13,D1		;Test transmitter buffer empty
	BEQ.S	BYO10		;Branch if it is not empty
	ANDI.W	#$00FF,D0	;Add start and stop bits to the
	ORI.W	#$0100,D0	; data byte
	MOVE.W	D0,SERDAT.L	;Output data

	MOVEM.W	(SP)+,D0-D1	;Restore registers
	RTS

;----------------------------------------------------------------------
;Routine to check if a key was struck. This returns with "NE" status if
; it was struck. A boolean is also returned in D0 since this may be
; called by an intrinsic.
;
KEYHIT	MOVE.W	SERDATR.L,D0	;Read status and data
	BTST	#14,D0		;Receive buffer full
	SNE	D0
	EXT.W	D0
	EXT.L	D0
	RTS

END	EQU	@		;ADDRESS WHERE THIS HANDLER ENDS +1
	IF	END > START +$600
	ERROR -- FILE IS TOO LONG
	ENDIF

;----------------------------------------------------------------------
;HOOK THESE HANDLERS INTO THE DEVICE HANDLER TABLE AS DEVICES 0 AND 1
;
	ORG	DEVTBL
	DC.L	CONHAN0
	DC.L	CONHAN1

	END

;HOOK THESE H