Google
 

Trailing-Edge - PDP-10 Archives - decuslib10-07 - 43,50446/gidus.p11
There are 2 other files named gidus.p11 in the archive. Click here to see a list.
	.NLIST	TTM,CND
	.TITLE	GIDUS GT40 INTERACTIVE DISPLAY UTILITY SYSTEM
	.SBTTL	GENERAL PARAMETER DEFINITIONS
	.ENABL	AMA
	.MCALL	GRAPHIC
	GRAPHIC
	;
	; REGISTER DEFINITIONS
R0=%0
R1=%1
R2=%2
R3=%3
R4=%4
R5=%5
SP=%6
PC=%7
SWR=177570				; SWITCH REGISTER
PSW=177776				; PROCESSOR STATUS WORD
STACK=37700				; LOWER STACK BOUND
	;
	; DEVICE REGISTERS
	;
IS.GT=175610				; GT40 INPUT STATUS REGISTER
IB.GT=175612				; GT40 INPUT BUFFER REGISTER
OS.GT=175614				; GT40 OUTPUT STATUS REGISTER
OB.GT=175616				; GT40 OUTPUT BUFFER REGISTER
	;
IS.KB=177560				; KEYBOARD INPUT STATUS REGISTER
IB.KB=177562				; KEYBOARD INPUT BUFFER REGISTER
	;
LKS.CL=177546				; CLOCK STATUS REGISTER
	;
	; SCREEN AND SCROLLING PARAMETERS
	;
	.RADIX	10
LST.SC=23				; Y POSITION OF LAST LINE (RASTER UNITS)
CHR.SC=72				; NUMBER OF CHARACTERS PER LINE
LSZ.SC=CHR.SC+8				; NUMBER OF BYTES PER LINE
DST.SC=24				; VERTICAL DISTANCE BETWEEN CHARACTERS
	.PAGE
	.SBTTL	SPECIAL CHARACTERS
	.RADIX	8
	;
CR.CH=15				; CARRIAGE RETURN
LF.CH=12				; LINE FEED
EOS.CH=37				; CLEAR SCREEN
CRS.CH=137				; CURSOR IS UNDERSCORE
BEL.CH=7				; BELL
LFT.CH=10				; LEFT ARROW (BACK SPACE)
RT.CH=30				; RIGHT ARROW (CTRL X)
UP.CH=32				; UP ARROW (CTRL Z)
DWN.CH=13				; DOWN ARROW (VT)
HME.CH=35				; HOME UP (GIDUS COMMAND)
SP.CH=40				; SPACE
RUB.CH=177				; RUBOUT
SO.CH=16				; SHIFT-OUT
SI.CH=17				; SHIFT-IN
CMD.CH=1				; COMMAND SIGNAL (^A)
ADD.CH=2				; ADD FILE SIGNAL (^B)
	.PAGE
	.SBTTL	DISPLAY RESTART
	;
	; ALLOW DISPLAY RE-START FROM 0
	;
	.=0
	;
	; RE-START THE DISPLAY FILE IF TEMPORARY
	; DJMP LANDS HERE
	;
	DJMP,FIRST.
	.PAGE
	.SBTTL	INTERRUPT VECTORS
	.=4
	.WORD	$BSINT,000		; BUS ERROR, LEVEL 0
	.=60
KB$VEC:	.WORD	$KBINT,200		; KEYBOARD INTERRUPT, LEVEL 4
	.=100
	.WORD	$CLINT,300		; CLOCK INTERRUPT, LEVEL 6
	.=300
DL$VEC:	.WORD	$DLINT,340		; DL-11 INTERRUPT, LEVEL 7 
	.=320
	.WORD	$STINT,200		; STOP INTERRUPT, LEVEL 4
	.WORD	$LPINT,200		; L.P. INTERRUPT, LEVEL 4
	.WORD	$TMINT,340		; TIME-OUT INTERRUPT, LEVEL 7
	.PAGE
	.SBTTL	LOCAL MACROS
	;
	.MACRO	CALL 	..ROUT		; MACRO TO CALL A ROUTINE
	JSR	PC,..ROUT		; VIA THE PC
	.ENDM
	;
	.MACRO	RETURN			; MACRO TO DO A RETURN
	RTS	PC			; VIA THE PC
	.ENDM
	;
	.MACRO	SAVREG			; MACRO TO SAVE REGISTERS
	JSR	R0,$SAVRG		; SAVE THE REGISTERS
	.ENDM
	;
	.MACRO	RESREG			; MACRO TO RESTORE REGISTERS
	JSR	R0,$RESRG		; RESTORE THE REGISTERS
	.ENDM
	;
	.MACRO	PUSH 	..		; MACRO TO
	MOV	..,-(SP)		; PUSH ONTO STACK
	.ENDM
	;
	.MACRO	POP 	..		; MACRO TO POP
	MOV	(SP)+,..		; OFF STACK
	.ENDM
	;
	.MACRO	SOB 	..R,..DEST	; MACRO TO SIMULATE SOB INSTRUCTION
	DEC	..R			; DECREMENT THE REGISTER
	BGT	..DEST			; BRANCH BACK IF GREATER
	.ENDM
	;
	.MACRO	ENABLE	..DN		; MACRO TO ENABLE A DISPLAY FILE
	MOV	#..DN,R5		; GET DISPLAY NUMBER
	CALL	$ENABL			; AND ENABLE IT
	.ENDM
	;
	.MACRO	DISABL	..DN		; MACRO TO DISABLE A DISPLAY FILE
	MOV	#..DN,R5		; GET THE DISPLAY NUMBER
	CALL	$DSABL			; AND DISABLE IT
	.ENDM
	.PAGE
	; OCTAL FORMAT MACRO
	;
	; THIS MACRO IS USED TO SET UP A CALL TO
	; THE OCTAL FORMATTING ROUTINE
	;
	.MACRO	FORMAT	..WORD,..AREA,..SIZE
	SAVREG				; SAVE ALL REGISTERS
	MOV	..WORD,R5		; GET WORD TO BE FORMATTED
	MOV	#'..AREA,R1		; GET POINTER TO OUTPUT
	MOV	#'..SIZE,R2		; GET NUMBER OF DIGITS
	CALL 	$FRMAT			; FORMAT THE NUMBER
	RESREG				; RESTORE THE REGISTERS
	.ENDM
	.PAGE
	; STATS$ - STATUS MACRO
	;
	; THIS MACRO IS USED TO SET UP THE STATUS/POINTER WORD
	; IN THE DISPLAY FILE TABLE. ALL ARGUMENTS SHOULD BE
	; PRESENT AND (WITH THE EXCEPTION OF ..PT) HAVE A VALUE OF
	; OF 1(ON) OR 0(OFF)
	;
	; ..EX	1 = DISPLAY FILE EXISTS
	; ..EN	1 = DISPLAY FILE ENABLED
	; ..WP	1 = WRITE PROTECTED (DISPLAY FILE CANNOT BE DELETED)
	; ..ND	1 = NO DISABLE (DISPLAY FILE CANNOT BE DISABLED)
	; ..LP	1 = LIGHT PEN INTERRUPTS ALLOWED
	; ..RL	1 = DISPLAY FILE MAY BE MOVED
	; ..PT	POINTER TO NEXT DISPLAY FILE
	;
	.MACRO	STATS$	..EX,..EN,..WP,..ND,..LP,..RL,..PT
	..=000000
	.IF	GT,..EX
	..=100000			; DISPLAY FILE EXISTS
	.ENDC
	.IF	GT,..EN
	..=..!40000			; DISPLAY FILE IS ENABLED
	.ENDC
	.IF	GT,..WP
	..=..!20000			; DISPLAY FILE IS WRITE PROTECTED
	.ENDC
	.IF	GT,..ND
	..=..!10000			; DISPLAY FILE MAY NOT BE DISABLED
	.ENDC
	.IF	GT,..LP
	..=..!4000			; L.P. INTERRUPTS ALLOWED
	.ENDC
	.IF	GT,..RL
	..=..!2000			; DISPLAY FILE MAY BE MOVED
	.ENDC
	..=..!..PT			; POINTER
	.WORD	..			; STATUS WORD
	.ENDM
	.PAGE
	.SBTTL	GIDUS DISPLAY FILE TABLE
	;
	; GIDUS DISPLAY FILE TABLE
	;
	; 64(10) ENTRIES - ONE PER DISPLAY FILE
	; 3 WORDS PER ENTRY - START/LAST/STATUS-POINTER
	;
	; STATUS WORD IS AS FOLLOWS:
	;
	; BITS		MEANING
	;
	;  15		DISPLAY FILE EXISTS
	;  14		DISPLAY FILE ENABLED
	;  13		DISPLAY FILE WRITE PROTECTED
	;  12		DISPLAY FILE CANNOT BE DISABLED
	;  11		L.P. INTERRUPTS ALLOWED
	;  10		DISPLAY FILE MAY BE MOVED
	; 9-6		RESERVED
	; 5-0		POINTER TO NEXT DISPLAY FILE IN LIST
	;
	; MASK BITS
	;
EX.BIT=100000				; EXISTS BIT
EN.BIT=40000				; ENABLED BIT
WP.BIT=20000				; WRITE-PROTECT BIT
ND.BIT=10000				; NO DISABLE BIT
RL.BIT=2000				; RELOCATION BIT
PT.BIT=77				; POINTER BITS
	;
$$DFT:	.WORD	FIRST.,STATS.-2		; FIRST DISPLAY FILE
DF$FIR:	STATS$	1,1,1,1,0,0,1
	.WORD	CDF.,0			; CHARACTER DISPLAY FILE
DF$CDF:	STATS$	1,1,1,0,0,0,2
	.WORD	STATS.,MESAG.-4		; STATUS DISPLAY FILE
DF$STA:	STATS$	1,1,1,0,0,0,3
	.WORD	MESAG.,MP.-2		; MESSAGE DISPLAY FILE
DF$MSG:	STATS$	1,1,1,1,0,0,4
	.WORD	MP.,AP.-2		; MAIN POINTER
DF$MP:	STATS$	1,1,1,0,0,1,5
	.WORD	AP.,OMSG.-2		; AUXILLARY POINTER
DF$AP:	STATS$	1,1,1,0,0,1,77
	.WORD	OMSG.,GCMND.-2		; OPTION MESSAGE FILE
DF$OMS:	STATS$	1,0,1,0,0,0,0
	.WORD	GCMND.,OPTR.-2		; GIDUS COMMAND DISPLAY FILE
DF$CMD:	STATS$	1,0,1,0,0,0,0
	.WORD	OPTR.,LAST.-2		; OPTION POINTER
DF$OPT:	STATS$	1,0,1,0,0,1,0
	;
	; USER DISPLAY FILES
	;
DF$USR:
	.REPT	54.
	.WORD	0,0
	STATS$	0,0,0,0,0,0,0
	.ENDR
	;
	.WORD	LAST.,DHALT.-2		; LAST DISPLAY FILE
	STATS$	1,1,1,1,0,0,0
DF$TOP:	.WORD	0			; FIRST FREE WORD OF CORE
	.PAGE
	.SBTTL	PROGRAM MAINLINE
$START:	RESET				;
	RESET				; FIX THINGS
	RESET				;
	MOV	#37776,SP		; SET STACK TO TOP OF CORE
	MOV	#STACK,R1		; GET UPPER MEMORY BOUND
	CALL 	$CDINI			; INITIALIZE CHARACTER DISPLAY FILE
	SUB	DF$TOP,R1		; SUBTRACT LOWER BOUND
	ASR	R1			; FORM WORD COUNT
	FORMAT	R1,ST.FRE,5		; FORMAT INTO STATUS DISPLAY
	MOV	#100,@#IS.KB		; ENABLE KEYBOARD INTERRUPTS
	MOV	#100,@#IS.GT		; ENABLE DL-11 INTERRUPTS
	MOV	#100,@#LKS.CL		; ENABLE CLOCK INTERRUPTS
	MOV	#FIRST.,@#DPC		; START THE DISPLAY
ST.NUL:	WAIT				; WAIT FOR INTERRUPT
	TST	GC$TRC			; TEST TRACE ADDRESS
	BEQ	ST.NUL			; IF ZERO NO TRACE
	FORMAT	@GC$TRC,ST.TRC,6	; OTHERWISE FORMAT LOCATION
	BR	ST.NUL			; WAIT FOR NEXT INTERRUPT
	.PAGE
	.SBTTL	CHARACTER DISPLAY FILE INITIALIZATION
	; THIS SUBROUTINE INITIALIZES THE CHARACTER
	; DISPLAY FILE, AND CREATES CHARACTER POINTERS
	;
CD$FST:	.WORD	0			; Y POSITION OF FIRST LINE
CD$OLD:	.WORD	0			; PREVIOUS # OF LINES IN USE
CD$NEW:	.WORD	8.			; DESIRED # OF LINES (DEFAULT 8)
	;
$CDINI:	SAVREG				; SAVE THE REGISTERS
	CMP	CD$OLD,CD$NEW		; SHOULD A SETUP BE DONE ?
	BEQ	CD.1			; NO, SIMPLY CLEAR EXISTING FILE
	CALL 	$CDSET			; YES, CREATE THE DISPLAY FILE
CD.1:	MOV	CD$FST,R2		; GET Y POSITION OF FIRST LINE
	MOV	CD$NEW,R0		; GET NUMBER OF LINES
	MOV	#CDF.+12.,R1		; R1 IS CDF. POINTER
CD.2:	TST	(R1)+			; POINT PAST FIRST WORD
	CLR	(R1)+			; CLEAR X POSITION
	MOV	R2,(R1)+		; INSERT Y POSITION
	SUB	#DST.SC,R2		; UPDATE Y POSITION
	TST	(R1)+			; POINT PAST CHAR INST.
	MOV	#CHR.SC/2,R3		; NUMBER OF WORDS PER LINE
CD.3:	CLR	(R1)+			; BLANK OUT THE LINE
	SOB 	R3,CD.3			; LOOP FOR ALL WORDS
	SOB 	R0,CD.2			; LOOP FOR ALL LINES
	CLR	CDF.X			; RESET CURSOR POSITION
	CLR	DL$CNT			; CLEAR CHARACTER COUNT
	SUB	#CHR.SC,R1		; BACK UP POINTER TO FIRST CHAR
	MOV	R1,DL$PNT		; AND SAVE POINTER
	RESREG				; RESTORE THE REGISTERS
	RETURN				; AND RETURN
	.PAGE
	; THIS ROUTINE IS USED TO CREATE THE CHARACTER DISPLAY FILE
	; WHICH BEGINS AT ADDRESS CDF. + 12. AND USES AS MUCH FREE
	; CORE AS IS NECESSARY IN ORDER TO SET UP THE DESIRED NUMBER
	; OF LINES USED FOR SCROLLING. EACH LINE OF THIS DISPLAY
	; FILE STARTS WITH A POINT INSTRUCTION, FOLLOWED BY A 0
	; X CO-ORDINATE, AND A Y CO-ORDINATE THAT VARIES WITH THE
	; VERTICAL POSITION OF THE LINE. NEXT IS THE CHAR INSTRUCTION
	; WHICH IS FOLLOWED BY CHR.SC NUMBER OF BYTES
	;
CD$END:	.WORD	0			; LAST WORD + 2 OF DISPLAY FILE
	;
$CDSET:	CMP	CD$NEW,#31.		; TOO MANY LINES ?
	BLE	CD.4			; NO, CONTINUE
	MOV	#31.,CD$NEW		; YES, SO SET 31 MAXIMUM
CD.4:	TST	CD$NEW			; ARE THERE ENOUGH LINES ?
	BGT	CD.5			; YES, CONTINUE
	MOV	#1,CD$NEW		; NO, SO SET 1 MINIMUM
CD.5:	MOV	CD$NEW,CD$OLD		; SAVE NUMBER OF LINES
	CLR	CD$FST			; WHERE DOES TOP LINE BELONG ?
	MOV	#CDF.+12.,R0		; R0 POINTS TO CDF
	MOV	CD$NEW,R1		; NUMBER OF LINES IN R1
CD.6:	ADD	#DST.SC,CD$FST		; FIND TOP LINE POSITION BY ADDING
	MOV	#POINT!INT2!BLKOFF,(R0)+; FIRST WORD OF EACH LINE
	CLR	(R0)+			; CLEAR X POSITION
	CLR	(R0)+			; AND Y POSITION
	MOV	#CHAR,(R0)+		; INSERT CHAR INST.
	MOV	#CHR.SC/2,R2		; # OF WORDS PER LINE
CD.7:	CLR	(R0)+			; BLANK OUT LINE
	SOB 	R2,CD.7			; LOOP FOR ALL WORDS
	SOB 	R1,CD.6			; LOOP FOR ALL LINES
	MOV	#DJMP,(R0)+		; DISPLAY FILE ENDS WITH
	MOV	#STATS.,(R0)+		; A DJMP TO NEXT FILE
	MOV	R0,CD$END		; FIRST FREE WORD
	MOV	R0,DF$TOP		; OF CORE
	TST	-(R0)			; SUBTRACT 2 FROM R0
	MOV	R0,DF$CDF-2		; AND SAVE IN DISPLAY TABLE
	DEC	CD$FST			; FIXUP TOP LINE POSITION
	RETURN				; AND RETURN
	.PAGE
	.SBTTL	BUS ERROR INTERRUPT ROUTINES
	; TIME-OUT INTERRUPT ROUTINE
	;
	; RESTART THE DISPLAY IMMEDIATELY
	;
$TMINT:	BIT	#100,@#DSR		; IS THIS A SHIFT INTERRUPT ?
	BNE	TM.OUT			; NO, IT IS A TIME-OUT
	MOV	#1,@#DPC		; IF SHIFT THEN RESUME DISPLAY
	RTI				; AND RETURN FROM INTERRUPT
	;
TM.OUT:	MOV	#FIRST.,@#DPC		; IF TIME-OUT, THEN RE-START
	RTI				; AND RETURN FROM INTERRUPT
	;
	; $BSINT - BUS ERROR
	;          MOST LIKELY ODD ADDRESS REFERENCE
	;
$BSINT:	MOV	#ER$ADD,R4		; FATAL "? ODD ADDRESS REFERENCE ?"
	CALL 	$ERROR			; PRINT THE ERROR
	INC	@#DSR			; RING THE BELL
	BR	.			; AND HANG UP
	.PAGE
	.SBTTL	KEYBOARD INTERRUPT ROUTINE
	;
	; THIS ROUTINE INPUTS ONE CHARACTER FROM THE LK40
	; KEYBOARD AND SENDS IT TO THE 10. IF THE CHARACTER
	; IS "EOS.CH" (ASCII 37) THE CHARACTER DISPLAY FILE
	; IS CLEARED
	;
$KBINT:	SAVREG				; SAVE THE REGISTERS
	MOVB	@#IB.KB,R0		; GET THE KEYBOARD CHARACTER
	BIC	#177600,R0		; CLEAR THE TOP BYTE AND PARITY
	CMP	R0,#HME.CH		; GIDUS COMMAND ?
	BNE	KB.0			; NO, CONTINUE
	CALL 	GC.SET			; YES DO SETUP
	BR	KB.RET			; AND RETURN
KB.0:	CMP	R0,#LFT.CH		; LEFT ARROW ?
	BNE	KB.1			; NO, CONTINUE
	COMB	CL$LFT			; YES, CHANGE STATE
	CLRB	CL$RT			; DISABLE MOVEMENT TO RIGHT
	BR	KB.RET			; AND RETURN
KB.1:	CMP	R0,#RT.CH		; RIGHT ARROW ?
	BNE	KB.2			; NO, CONTINUE
	COMB	CL$RT			; YES, CHANGE STATE
	CLRB	CL$LFT			; DISABLE MOVEMENT TO LEFT
	BR	KB.RET			; AND RETURN
KB.2:	CMP	R0,#UP.CH		; UP ARROW ?
	BNE	KB.3			; NO, CONTINUE
	COMB	CL$UP			; YES, CHANGE STATE
	CLRB	CL$DWN			; DISABLE MOVEMENT DOWN
	BR	KB.RET			; AND RETURN
KB.3:	CMP	R0,#DWN.CH		; DOWN ARROW ?
	BNE	KB.4			; NO, CONTINUE
	COMB	CL$DWN			; YES, CHANGE STATE
	CLRB	CL$UP			; DISABLE MOVEMENT UP
	BR	KB.RET			; AND RETURN
KB.4:	CMP	R0,#EOS.CH		; CLEAR SCREEN ?
	BNE	KB.SND			; NO SEND THE CHARACTER
	CALL 	$CDINI			; YES - INITIALIZE THE SCREEN
	BR	KB.RET			; AND RETURN FROM INTERRUPT
KB.SND:	TST	$IO$			; WAS I/O IN PROGRESS
	BEQ	KB.5			; NO, SEND THE CHARACTER
	CMP	R0,#3			; WAS IT A CTRL/C ?
	BNE	KB.RET			; NO SO DON'T SEND IT
	MOV	#$DLINT,@#DL$VEC	; YES, RESTORE CHARACTER MODE
	CLR	$IO$			; CLEAR THE I/O FLAG
	MOV	#"CH,ST.DL		; DL-11 IN CHARACTER MODE
	MOV	#"TI,ST.ATE		; RESTORE GIDUS-STATE
KB.5:	TSTB	@#OS.GT			; IS THE 10 READY
	BPL	KB.5			; WAIT IF NOT READY
	MOVB	R0,@#OB.GT		; SEND THE CHARACTER
KB.RET:	RESREG				; RESTORE THE REGISTERS
	RTI				; RETURN FROM INTERRUPT
	.PAGE
	.SBTTL	DL-11 INTERRUPT ROUTINE
	;
	; THIS ROUTINE INPUTS ONE CHARACTER FROM THE 10
	; AND ADDS IT TO THE DISPLAY FILE. IF NECESSARY
	; THE DISPLAY FILE IS SCROLLED
	;
DL$CNT:	.WORD	0			; CHARACTER COUNT
DL$PNT:	.WORD	0			; CHARACTER POINTER
	;
$DLINT:	SAVREG				; SAVE THE REGISTERS
	MOVB	@#IB.GT,R0		; GET THE CHARACTER
	BIC	#177600,R0		; CLEAR TOP BYTE AND PARITY
	CMP	R0,#CMD.CH		; ENTER COMMAND MODE ?
	BNE	DL.0			; NO, PROCESS CHARACTER
	MOV	#"CO,ST.DL		; YES, INDICATE IN STATUS DISPLAY
	INC	$IO$			; SET THE I/O FLAG
	MOV	#$RCINT,@#DL$VEC	; TRAP INTERRUPTS AT $RCINT
	MOV	ST.ATE,ST.OLD		; SAVE GIDUS STATE
	MOV	#"RC,ST.ATE		; INDICATE GIDUS STATE
	MOV	#9.,RC$CNT		; SET COMMAND BYTE COUNT
	MOV	#RC$CMD,RC$PNT		; SET COMMAND BUFFER POINTER
	CLR	RC$SUM			; CLEAR CHECKSUM
	BR	DL.RET			; AND RETURN
DL.0:	CMP	R0,#ADD.CH		; ENTER ADDFILE MODE ?
	BNE	DL.1			; NO, PROCESS CHARACTER
	TST	AD$ABF			; CAN NEXT BLOCK BE ACCEPTED ?
	BNE	DL.RET			; NO, DO NOT ACCEPT
	MOV	#"AD,ST.DL		; ADDING, INDICATE IN STATUS DISPLAY
	INC	$IO$			; SET I/O FLAG
	MOV	#$ADINT,@#DL$VEC	; TRAP INTERRUPTS AT $ADINT
	MOV	ST.ATE,ST.OLD		; SAVE GIDUS STATE
	MOV	#"RC,ST.ATE		; INDICATE RECEIVING
	BR	DL.RET			; AND RETURN
DL.1:	CMP	R0,#BEL.CH		; IS THIS A BELL ?
	BNE	DL.NOB			; NO SO CONTINUE
	INC	@#DSR			; YES SO RING
	BR	DL.RET			; AND RETURN
DL.NOB:	CMP	R0,#CR.CH		; CARRIAGE RETURN ?
	BEQ	DL.RET			; YES, SO IGNORE
	CMP	R0,#RUB.CH		; FILLER ?
	BEQ	DL.RET			; YES, SO IGNORE IT
	CMP	R0,#LF.CH		; LINE FEED ?
	BNE	DL.CHR			; NO, SO PRINT CHARACTER
	CALL 	$SCROL			; <LF>, SO SCROLL
	BR	DL.RET			; AND RETURN
	;
DL.CHR:	CMP	DL$CNT,#CHR.SC		; ENOUGH ROOM ON LINE ?
	BGE	DL.RET			; NO, SO IGNORE
	CMP	R0,#40			; PRINTABLE CHARACTER ?
	BLT	DL.RET			; NO, SO IGNORE
	MOVB	R0,@DL$PNT		; INSERT THE CHARACTER
	INC	DL$PNT			; INCREMENT POINTER
	INC	DL$CNT			; INCREMENT CHARACTER COUNT
	ADD	#14.,CDF.X		; MOVE CURSOR
DL.RET:	RESREG				; RESTORE THE REGISTERS
	RTI				; RETURN FROM INTERRUPT
	.PAGE
	.SBTTL	SCROLLING ROUTINE
	;
	; THIS ROUTINE IS CALLED WHENEVER THE 10
	; OUTPUTS A LINE FEED. EVERY LINE IS
	; SHIFTED UP ONE POSITION, AND THE BOTTOM
	; LINE BECOMES AVAILABLE FOR OUTPUT
	;
$SCROL:	MOV	CD$NEW,R0		; NUMBER OF LINES
	MOV	#CDF.+12.,R1		; CDF. POINTER
SC.LUP:	ADD	#DST.SC,4(R1)		; SHIFT LINE UP
	CMP	4(R1),CD$FST		; IS THIS LINE AVAILABLE
	BLE	SC.SNT			; NO, CONTINUE SHIFTING
	MOV	#LST.SC,4(R1)		; MAKE THIS THE LAST LINE
	MOV	R1,DL$PNT		; GET POINTER
	ADD	#8.,DL$PNT		; AND FIX IT UP
	CLR	DL$CNT			; CLEAR CHARACTER COUNT
	CLR	CDF.X			; RESET CURSOR
	MOV	DL$PNT,R2		; POINTER TO LINE
	MOV	#CHR.SC/2,R3		; NUMBER OF WORDS PER LINE
SC.1:	CLR	(R2)+			; BLANK OUT LINE
	SOB 	R3,SC.1			; LOOP FOR ALL WORDS
	;
SC.SNT:	ADD	#LSZ.SC,R1		; POINT TO NEXT LINE
	SOB 	R0,SC.LUP		; LOOP FOR ALL LINES
	RETURN				; RETURN
	.PAGE
	.SBTTL	STOP INTERRUPT ROUTINE
	;
	; THIS ROUTINE IS EXECUTED EACH TIME THE DISPLAY
	; STOPS. IF THERE IS NOTHING TO DO THE DISPLAY
	; RESUMES IMMEDIATELY, ELSE A DISPATCH TO THE
	; APPROPRIATE ROUTINE IS MADE.
ST$FNC:	.WORD	0			; FUNCTION CODE
	;
	; STOP INTERRUPT DISPATCH TABLE
	;
ST$DIS:	ST.RES				; FUNCT = 0 - RESUME
	ST.STP				; FUNCT = 1 - STOP DISPLAY
	;
$STINT:	SAVREG				; SAVE THE REGISTERS
	MOV	ST$FNC,R0		; GET THE FUNCTION CODE
	ASL	R0			; FORM WORD OFFSET
	CALL 	@ST$DIS(R0)		; DISPATCH TO ROUTINE
	RESREG				; RESTORE THE REGISTERS
	CLR	ST$FNC			; INDICATE NOTHING PENDING
	MOV	#1,@#DPC		; RESUME THE DISPLAY
	RTI				; RETURN FROM INTERRUPT
	;
	;
	;
	;
	;
	;
ST.RES:	RETURN				; RETURN IMMEDIATELY
	;
ST.STP:	TST	(SP)+			; IGNORE RETURN ADDRESS
	RESREG				; RESTORE THE REGISTERS
	CLR	ST$FNC			; CLEAR FUNCTION CODE
	RTI				; AND RETURN FROM INTERRUPT
	.PAGE
	.SBTTL	LIGHT PEN INTERRUPT ROUTINE
	;
LP$FLG:	.WORD	0			; ENABLED/DISABLED FLAG
LP$HIT:	.WORD	0			; WAIT FOR HIT FLAG
LP$DPC:	.WORD	0			; DPC AT TIME OF HIT
	;
LP$X:	.WORD	0			; X POSITION OF HIT
LP$Y:	.WORD	0			; Y POSITION OF HIT
LP$DIS:	.WORD	0			; DISPLAY NUMBER LAST HIT
	;
$LPINT:	TST	LP$FLG			; IS LIGHT PEN ENABLED ?
	BEQ	LP.1			; YES, PROCESS INFORMATION
	MOV	#1,@#DPC		; ELSE RESUME THE DISPLAY
	RTI				; AND RETURN IMMEDIATELY
	;
LP.1:	SAVREG				; SAVE THE REGISTERS
	INC	LP$FLG			; DISABLE LIGHT PEN (FOR A MOMENT)
	CLR	LP$HIT			; CLEAR THE WAIT CONDITION
	MOV	@#DPC,LP$DPC		; SAVE THE DPC OF HIT
	MOV	@#XSTAT,LP$X		; SAVE X POSITION
	MOV	@#YSTAT,LP$Y		; SAVE Y POSITION
	MOV	#1,@#DPC		; RESUME THE DISPLAY
	MOV	#$$DFT,R0		; R0 POINTS TO DISPLAY TABLE
	CLR	R1			; R1 CONTAINS DISPLAY NUMBER
LP.2:	CMP	@R0,LP$DPC		; HIT IN THIS DISPLAY ?
	BHI	LP.3			; NO IT OCCURRED BEFORE
	CMP	2(R0),LP$DPC		; HIT IN THIS DISPLAY ?
	BHIS	LP.FND			; YES, RETURN DISPLAY NUMBER
LP.3:	ADD	#6,R0			; NO, POINT TO NEXT DISPLAY
	INC	R1			; GET NEXT DISPLAY NUMBER
	CMP	R1,#77			; ARE WE THROUGH
	BLE	LP.2			; NO CONTINUE CHECKING
	CLR	R1			; ELSE 0 = BAD HIT
LP.FND:	MOV	R1,LP$DIS		; SET UP DISPLAY NUMBER
	CLR	LP$FLG			; RE-ENABLE LIGHT PEN
	MOV	#"LE,ST.LP		; RESET STATUS DISPLAY
	RESREG				; RESTORE THE REGISTERS
	RTI				; RETURN FROM INTERRUPT
	.PAGE
	.SBTTL	CLOCK INTERRUPT ROUTINE
	;
	; THIS ROUTINE COUNTS OFF A SPECIFIED NUMBER OF
	; CLOCK TICS. WHEN THE COUNT REACHES ZERO THE
	; ROUTINE CHECKS WHETHER ANY MOVEMENT ARROWS
	; ARE ENABLED. IF SO THE ROUTINE CHECKS WHETHER
	; MP. IS ENABLED (BIT 15 OF SWR) OR AP. ENABLED
	; (BIT 1 OF SWR). NOTE THAT ONLY ONE POINTER MAY
	; BE ENABLED IN THIS MANNER AND THE MAIN POINTER
	; ALWAYS HAS PRECEDENCE OVER THE AUXILLARY POINTER.
	;
CL$RT:	.BYTE	0			; 1 = MOVE TO RIGHT
CL$LFT:	.BYTE	0			; 1 = MOVE TO LEFT
CL$UP:	.BYTE	0			; 1 = MOVE UP
CL$DWN:	.BYTE	0			; 1 = MOVE DOWN
	;
CL$CNT:	.WORD	2			; NUMBER OF TICS TO WAIT
					; BETWEEN MOVES
CL$TIC:	.WORD	2			; RE-INITIALIZING VALUE FOR CL$CNT
	;
$CLINT:	DEC	CL$CNT			; DECREMENT COUNT
	BLE	CL.0			; CLOCK HAS TICKED AWAY
	JMP	CL.RET			; ELSE RETURN
CL.0:	MOV	CL$TIC,CL$CNT		; RESET COUNT
	BIT	#100000,@#SWR		; MP. ENABLED ?
	BEQ	CL.AP			; NO, SO CHECK AP.
	TSTB	CL$RT			; MOVE RIGHT ?
	BEQ	CL.1			; NO, CONTINUE
	CMP	MP.X,#MAXX		; CAN GO RIGHT ?
	BGE	CL.1			; NO, CONTINUE
	INC	MP.X			; MOVE TO THE RIGHT
CL.1:	TSTB	CL$LFT			; MOVE LEFT ?
	BEQ	CL.2			; NO, CONTINUE
	TST	MP.X			; CAN GO LEFT ?
	BLE	CL.2			; NO, CONTINUE
	DEC	MP.X			; MOVE TO LEFT
CL.2:	TSTB	CL$UP			; MOVE UP ?
	BEQ	CL.3			; NO, CONTINUE
	CMP	MP.Y,#MAXY		; CAN GO UP ?
	BGE	CL.3			; NO CONTINUE
	INC	MP.Y			; MOVE UP
CL.3:	TSTB	CL$DWN			; MOVE DOWN ?
	BEQ	CL.FRM			; NO, CONTINUE
	TST	MP.Y			; CAN GO DOWN ?
	BLE	CL.FRM			; NO, CONTINUE
	DEC	MP.Y			; MOVE DOWN
CL.FRM:	FORMAT	MP.Y,ST.MPY,4		; FORMAT THE NEW
	FORMAT	MP.X,ST.MPX,4		; X & Y POSITION
	BR	CL.RET			; AND RETURN
	.PAGE
	;
CL.AP:	BIT	#1,@#SWR		; AP. ENABLED ?
	BEQ	CL.RET			; NO, SO RETURN
	TSTB	CL$RT			; YES, MOVE RIGHT ?
	BEQ	CL.4			; NO, CONTINUE
	CMP	AP.X,#MAXX		; YES, CAN MOVE RIGHT ?
	BGE	CL.4			; NO, SO CONTINUE
	INC	AP.X			; MOVE TO RIGHT
CL.4:	TSTB	CL$LFT			; MOVE LEFT ?
	BEQ	CL.5			; BO, CONTINUE
	TST	AP.X			; CAN MOVE LEFT ?
	BLE	CL.5			; NO, CONTINUE
	DEC	AP.X			; MOVE TO LEFT
CL.5:	TSTB	CL$UP			; MOVE UP ?
	BEQ	CL.6			; NO, CONTINUE
	CMP	AP.Y,#MAXY		; CAN MOVE UP ?
	BGE	CL.6			; NO, CONTINUE
	INC	AP.Y			; MOVE UP
CL.6:	TSTB	CL$DWN			; MOVE DOWN ?
	BEQ	CL.FRA			; NO, CONTINUE
	TST	AP.Y			; CAN MOVE DOWN ?
	BLE	CL.FRA			; NO, CONTINUE
	DEC	AP.Y			; MOVE DOWN
CL.FRA:	FORMAT	AP.Y,ST.APY,4		; FORMAT X & Y POSITION
	FORMAT	AP.X,ST.APX,4		; INTO STATUS DISPLAY
CL.RET:	RTI				; RETURN FROM INTERRUPT
	.PAGE
	.SBTTL	GIDUS COMMAND INTERPRETER
	;
	; THIS SET OF ROUTINES ARE USED TO ACCEPT KEYBOARD
	; COMMANDS AND PROCESS THEM. NOTE THAT $GCINT IS
	; AN ALTERNATE INTERRUPT ROUTINE FOR THE GT40
	; KEYBOARD. INTERRUPTS ARE PROCESSED HERE WHEN IN
	; "GIDUS MODE", AND ARE PROCESSED BY $KBINT
	; WHEN IN "HOST MODE"
	;
GC$TRC:	.WORD	0			; TRACE VARIABLE
GC$ADR:	.WORD	0			; EXAMINE/MODIFY ADDRESS
GC$ARG:	.WORD	0			; COMMAND ARGUMENT
GC$PNT:	.WORD	0			; COMMAND CHARACTER POINTER
	;
	; COMMAND DISPATCH TABLE
	;
GC$DIS:	.WORD	"DI,GC.DI		; DISABLE COMMAND
	.WORD	"EN,GC.EN		; ENABLE COMMAND
	.WORD	"SP,GC.SP		; SPEED COMMAND
	.WORD	"EX,GC.EX		; EXAMINE COMMAND
	.WORD	"MO,GC.MO		; MODIFY COMMAND
	.WORD	"TR,GC.TR		; TRACE COMMAND
	.WORD	"DE,GC.DE		; DELETE COMMAND
	.WORD	"HE,GC.HE		; HELP COMMAND
	.WORD	"OF,GC.OF		; OFF COMMAND
	.WORD	"LE,GC.LE		; ENABLE L.P. COMMAND
	.WORD	"LD,GC.LD		; DISABLE L.P. COMMAND
	.WORD	"RE,GC.RE		; RESET COMMAND
	.PAGE
	; GIDUS COMMAND SET UP ROUTINE
	;
	; THIS ROUTINE IS CALLED TO ENABLE GIDUS COMMANDS
	; WHEN "HOME" IS HIT DURING "HOST MODE"
	;
GC.SET:	MOV	#GC.END,GC.HLP		; DISABLE HELP SUB-FILE
	MOV	#"  ,R0			; PREPARE TO BLANK
	MOV	#7,R1			; OUT COMMAND LINE
	MOV	#GC.LNE,R2
GC.CLR:	MOV	R0,(R2)+		; BLANK OUT 7 WORDS
	SOB 	R1,GC.CLR		; FOR A TOTAL OF 14 CHARACTERS
	MOV	#7,R5			; ENABLE GIDUS COMMAND
	CALL 	$ENABL			; DISPLAY FILE
	MOV	#GC.LNE,GC$PNT		; SET UP CHARACTER POINTER
	CLR	GC$ADR			; CLEAR INPUT ADDRESS
	CLR	GC$ARG			; AND INPUT ARGUMENT
	MOV	#$GCINT,@#KB$VEC	; TRAP FURTHER KB INTERRUPTS
	MOV	#"GI,ST.ATE		; CHANGE GIDUS STATE
	RETURN				; RETURN TO $KBINT
	.PAGE
	; $GCINT - GIDUS COMMAND INTERRUPT ROUTINE
	;
$GCINT:	SAVREG				; SAVE THE REGISTERS
	MOVB	@#IB.KB,R0		; GET THE INPUT CHARACTER
	BIC	#177600,R0		; CLEAR TOP BYTE AND PARITY
	CMP	R0,#HME.CH		; IS THIS A HOME?
	BNE	GC.1			; NO, CONTINUE
	MOV	#7,R5			; YES, DISABLE COMMAND
	CALL 	$DSABL			; DISPLAY FILE
	MOV	#$KBINT,@#KB$VEC	; RESET INTERRUPT VECTOR (HOST)
	MOV	#"TI,ST.ATE		; CHANGE GIDUS STATE
	BR	GC.RET			; AND RETURN
GC.1:	CMP	R0,#CR.CH		; CARRIAGE RETURN ?
	BEQ	GC.PRC			; YES, PROCESS COMMAND
	MOV	GC$PNT,R1		; NO, R1 BECOMES CHAR. POINTER
	CMP	R0,#RUB.CH		; IS THIS A RUBOUT?
	BNE	GC.2			; NO, CONTINUE
	CMP	R1,#GC.LNE		; YES, IS THERE ANYTHING TO ZAP
	BLOS	GC.2			; NO, CONTINUE
	MOVB	#' ,-(R1)		; ABRA CADABRA - DISAPPEAR
	MOV	R1,GC$PNT		; RESET POINTER
	BR	GC.RET			; AND RETURN
GC.2:	CMP	R0,#SP.CH		; IS THIS A PRINTING CHARACTER ?
	BLT	GC.RET			; NO, RETURN
	CMP	R0,#'Z			; IS IT UPPER CASE ?
	BLE	GC.2.5			; NO, SO GOOD CHARACTER
	SUB	#32.,R0			; YES, SO FORCE UPPER CASE
GC.2.5:	CMP	R1,#GC.LNE+14.		; GOOD CHAR, IS THERE ROOM ?
	BHIS	GC.RET			; NO, IGNORE AND RETURN
	MOVB	R0,(R1)+		; YES, ADD THE CHARACTER
	MOV	R1,GC$PNT		; RESET THE POINTER
GC.RET:	RESREG				; RESTORE THE REGISTERS
	RTI				; RETURN FROM INTERRUPT
	.PAGE
	.SBTTL	GIDUS COMMAND PROCESSING ROUTINE
	;
	; THIS ROUTINE IS CALLED WHEN A GIDUS COMMAND
	; IS TERMINATED BY A CARRIAGE RETURN
	;
GC.PRC:	MOV	#"  ,R0			; R0 IS USED TO
	MOV	#GC.ANS,R1		; BLANK OUT COMMAND REPLY
	MOV	R0,(R1)+		;
	MOV	R0,(R1)+		; CLEAR SIX CHARACTERS
	MOV	R0,(R1)+		;
	MOV	#GC.END,GC.HLP		; DISABLE HELP SUB-FILE
	MOV	#GC.LNE,R0		; R0 POINTS TO START OF COMMAND
	MOV	GC$PNT,R1		; R1 POINTS AT END OF COMMAND
	CALL 	GC.NUM			; GET THE NUMBER
	MOV	#GC.LNE,R0		; R0 POINTS TO START OF COMMAND
	MOV	#12.,R1			; 12 COMMANDS IN TOTAL
	MOV	#GC$DIS,R2		; R2 POINTS TO DISPATCH TABLE
GC.LUK:	CMP	@R0,(R2)+		; IS THIS THE COMMAND ?
	BNE	GC.3			; NO, CONTINUE LOOKING
	JMP	@0(R2)			; YES, EXECUTE THAT COMMAND
GC.3:	TST	(R2)+			; NO, POINT TO NEXT COMMAND
	SOB 	R1,GC.LUK		; AND TRY AGAIN
	;
GC.FIN:	MOV	#7,R1			; INVALID COMMAND OR THROUGH
	MOV	#"  ,R0			; BLANK OUT THE COMMAND
	MOV	#GC.LNE,R2		; LINE
GC.4:	MOV	R0,(R2)+		; 7 WORDS = 14 CHARACTERS
	SOB 	R1,GC.4
	MOV	#GC.LNE,GC$PNT		; RESET THE CHARACTER POINTER
	BR	GC.RET			; AND RETURN
	.PAGE
	; GC.NUM - RETURNS COMMAND ARGUMENT IN GC$ARG
	;
GC.NUM:	CLR	R5			; CLEAR WORD TO BE FORMED
GC.LUP:	CMP	R0,R1			; ARE WE THROUGH LINE ?
	BLO	GC.5			; NO, CONTINUE
	MOV	R5,GC$ARG		; YES, SAVE ARGUMENT
	RETURN				; AND RETURN
GC.5:	MOVB	(R0)+,R2		; GET NEXT CHARACTER
	CMP	R2,#'0			; IS IT A DIGIT ?
	BLT	GC.LUP			; NO, CONTINUE
	CMP	R2,#'7			; IS IT AN OCTAL DIGIT ?
	BGT	GC.LUP			; NO CONTINUE
	SUB	#60,R2			; YES, CONVERT TO BINARY
	ASL	R5			;
	ASL	R5			; SHIFT ONE OCTAL DIGIT
	ASL	R5			;
	BIS	R2,R5			; INSERT THE DIGIT
	BR	GC.LUP			; CONTINUE TIL THROUGH
	.PAGE
GC.DI:	MOV	GC$ARG,R5		; GET DISPLAY FILE NUMBER
	CALL 	$DSABL			; DISABLE THAT DISPLAY FILE
	BR	GC.FIN
	;
GC.EN:	MOV	GC$ARG,R5		; GET DISPLAY FILE NUMBER
	CALL 	$ENABL			; ENABLE THAT DISPLAY FILE
	BR	GC.FIN
	;
GC.SP:	MOV	#12,R5			; SET SPEED = 12 - SPEED
	SUB	GC$ARG,R5
	MOV	R5,CL$TIC		; AND SAVE AS NUMBER OF TICS
	BR	GC.FIN
	;
GC.EX:	MOV	GC$ARG,GC$ADR		; SAVE ARGUMENT AS ADDRESS
	FORMAT	@GC$ADR,GC.ANS,6	; PRINT THAT LOCATION
	BR	GC.FIN
	;
GC.MO:	MOV	GC$ARG,@GC$ADR		; MOVE ARGUMENT @ADDRESS
	BR	GC.FIN
	;
GC.TR:	MOV	GC$ARG,GC$TRC		; SAVE ARGUMENT AS TRACE ADDRESS
	MOV	GC$ARG,GC$ADR		; AND EXAMINE ADDRESS
	BR	GC.FIN
	;
GC.DE:	MOV	GC$ARG,R5		; GET DISPLAY NUMBER
	CALL 	$DELET			; AND DELETE IT
	BR	GC.FIN
	;
GC.HE:	MOV	#GC.HLP,R0		; ALTER THE DJMP
	MOV	#GC.HLP+2,@R0		; TO POINT TO NEXT WORD
	BR	GC.FIN
	;
GC.OF:	MOV	#ME.END,ME.ON		; TURN OFF ERROR MESSAGE
	BR	GC.FIN
	;
GC.LE:	CLR	LP$FLG			; INDICATE L.P. ENABLED
	MOV	#"LE,ST.LP		; SHOW ENABLED IN STATUS DISPLAY
	BR	GC.FIN
	;
GC.LD:	INC	LP$FLG			; INDICATE L.P. DISABLED
	MOV	#"LD,ST.LP		; SHOW DISABLED IN STATUS DISPLAY
	BR	GC.FIN
	;
GC.RE:	TST	GC$ARG			; HOW MANY LINES ?
	BEQ	GC.RE1			; IF ZERO THEN DON'T CHANGE
	MOV	GC$ARG,CD$NEW		; ELSE SAVE
GC.RE1:	CALL 	$RESET			; DO THE RESET
	BR	GC.FIN			; AND RETURN
	.PAGE
	.SBTTL	RECEIVE COMMAND ROUTINE
	; $RCINT - RECEIVE INTERRUPT ROUTINE TO FILL COMMAND BUFFER
	;
	; RECEIVER BUFFER
	;
RC$CMD:	.WORD	0			; COMMAND WORD
RC$BCT:
RC$DIS:	.WORD	0			; BLOCK COUNT OR DISPLAY #
RC$STA:
RC$X:	.WORD	0			; BLOCK #, STATUS, OR XPOS
RC$Y:	.WORD	0			; Y POSITION
RC$SUM:	.WORD	0			; CHECKSUM
	;
RC$PNT:	.WORD	0			; BUFFER POINTER
RC$CNT:	.WORD	0			; BUFFER BYTE COUNT
	;
$IO$:	.WORD	0			; I/O FLAG
RC$OPT:	.WORD	0			; REQUESTING OPTION FLAG
	;
$RCINT:	SAVREG				; SAVE THE REGISTERS
	MOVB	@#IB.GT,R0		; GET THE INCOMING BYTE
	BIC	#177400,R0		; CLEAR TOP BYTE
	ADD	R0,RC$SUM		; ADD INTO CHECKSUM
	DEC	RC$CNT			; DECREMENT THE BYTE COUNT
	BLE	RC.CMD			; PROCESS THE COMMAND IF THROUGH
	MOVB	R0,@RC$PNT		; ELSE BUFFER THIS BYTE
	INC	RC$PNT			; AND BUMP THE POINTER
RC.RET:	RESREG				; RESTORE THE REGISTERS
	RTI				; AND RETURN FROM INTERRUPT
	.PAGE
	; RECEIVE COMMAND DISPATCH TABLE
	;
RC$DSP:	.WORD	RC.NC			;  [0] INVALID COMMAND
	.WORD	RC.EN			;  [1] ENABLE DISPLAY FILE
	.WORD	RC.DS			;  [2] DISABLE DISPLAY FILE
	.WORD	RC.MOV			;  [3] MOVE DISPLAY FILE
	.WORD	RC.RMP			;  [4] REQUEST MAIN POINTER
	.WORD	RC.RAP			;  [5] REQUEST AUX. POINTER
	.WORD	RC.DL			;  [6] DISABLE LIGHT PEN
	.WORD	RC.EL			;  [7] ENABLE LIGHT PEN
	.WORD	RC.RLH			;  [8] REQUEST LAST L.P. HIT
	.WORD	RC.RNH			;  [9] REQUEST NEW L.P. HIT
	.WORD	RC.RAD			; [10] REQUEST TO ADD DISPLAY
	.WORD	RC.ANB			; [11] ADD NEXT BLOCK
	.WORD	RC.DEL			; [12] DELETE DISPLAY FILE
	.WORD	RC.SND			; [13] RE-SEND LAST TRANSMISSION
	.WORD	RC.CLR			; [14] CLEAR CDF.
	.WORD	RC.RST			; [15] RESET GIDUS
	.WORD	RC.OPT			; [16] REQUEST OPTION HIT
	;
	;
RC.CMD:	MOV	14.(SP),@#PSW		; RESTORE PSW (ALLOW INTERRUPTS)
	TSTB	RC$SUM			; TEST CHECKSUM - WAS IT GOOD ?
	BEQ	RC.1			; YES, CONTINUE WITH PROCESSING
	MOVB	#66,TR$STA		; STATUS = "CHECKSUM ERROR"
	JMP	$TRMIT			; TRANSMIT
	;
RC.1:	MOV	RC$CMD,R0		; GET COMMAND WORD
	BLT	RC.NC			; IF NEGATIVE THEN NO COMMAND
	CMP	R0,#16.			; VALID COMMAND ?
	BGT	RC.NC			; > 13, NO SUCH COMMAND
	MOVB	TR$STA,TR$OLD		; SAVE LAST STATUS
	CLRB	TR$STA			; DEFAULT STATUS IS GOOD
	ASL	R0			; FORM BYTE OFFSET
	JMP	@RC$DSP(R0)		; EXECUTE THE COMMAND
	.PAGE
	.SBTTL	COMMAND UTILTY ROUTINES
	;
RC.NC:	MOVB	#9.,TR$STA		; STATUS = "NO COMMAND"
	JMP	$TRMIT			; TRANSMIT
	;
RC.EN:	MOV	RC$DIS,R5		; GET DISPLAY NUMBER
	CALL 	$ENABL			; AND ENABLE IT ($ENABL SETS STATUS)
	JMP	$TRMIT			; TRANSMIT
	;
RC.DS:	MOV	RC$DIS,R5		; GET DISPLAY NUMBER
	CALL 	$DSABL			; AND DISABLE IT ($DSABL SETS STATUS)
	JMP	$TRMIT			; TRANSMIT
	;
RC.MOV:	MOV	RC$DIS,R5		; GET DISPLAY NUMBER
	CLR	SE$MOD			; DIRECT SEARCH MODE
	CALL 	$SERCH			; GET DISPLAY STATUS
	BIT	#EX.BIT,4(R4)		; DOES THIS DISPLAY EXIST ?
	BNE	RC.M1			; YES, CONTINUE CHECKING
	INCB	TR$STA			; NO, STATUS = "NO SUCH DISPLAY"
	JMP	$TRMIT			; TRANSMIT
RC.M1:	BIT	#RL.BIT,4(R4)		; CAN DISPLAY BE MOVED ?
	BNE	RC.M2			; YES, MOVE IT
	MOVB	#4,TR$STA		; STATUS = "CANNOT MOVE DISPLAY"
	JMP	$TRMIT			; TRANSMIT
RC.M2:	MOV	@R4,R4			; GET ADDRESS OF FIRST WORD
	TST	(R4)+			; POINT TO X POSITION
	MOV	RC$X,(R4)+		; INSERT X AND Y
	MOV	RC$Y,(R4)+		; POSITION FROM COMMAND
	CMP	R5,#4			; MAIN POINTER MOVED ?
	BNE	RC.M3			; NO, CONTINUE
	FORMAT	MP.X,ST.MPX,4		; YES, SO FORMAT X
	FORMAT	MP.Y,ST.MPY,4		; AND Y POSITION
RC.M3:	CMP	R5,#5			; AUXILLARY POINTER MOVED ?
	BNE	RC.M4			; NO, CONTINUE
	FORMAT	AP.X,ST.APX,4		; YES, SO FORMAT X
	FORMAT	AP.Y,ST.APY,4		; AND Y POSITION
RC.M4:	JMP	$TRMIT			; TRANSMIT
	;
RC.RMP:	MOV	MP.Y,R0			; GET MAIN POINTER(Y)
	CALL 	TR.Y			; AND BUFFER IT
	MOV	MP.X,R0			; GET MAIN POINTER(X)
	CALL 	TR.X			; AND BUFFER IT
	JMP	$TRMIT			; TRANSMIT
	;
RC.RAP:	MOV	AP.Y,R0			; GET AUX. POINTER(Y)
	CALL 	TR.Y			; AND BUFFER IT
	MOV	AP.X,R0			; GET AUX. POINTER(X)
	CALL 	TR.X			; AND BUFFER IT
	JMP	$TRMIT			; TRANSMIT
	.PAGE
	; COMMAND UTILITY ROUTINES (CONTINUED)
	;
RC.DL:	MOV	#1,LP$FLG		; DISABLE THE LIGHT PEN
	MOV	#"LD,ST.LP		; INDICATE IN STATUS DISPLAY
	JMP	$TRMIT			; TRANSMIT
	;
RC.EL:	CLR	LP$FLG			; ENABLE THE LIGHT PEN
	MOV	#"LE,ST.LP		; INDICATE IN STATUS DISPLAY
	JMP	$TRMIT			; TRANSMIT
	;
RC.RLH:	MOV	LP$Y,R0			; GET LAST HIT(Y)
	CALL 	TR.Y			; AND BUFFER IT
	MOV	LP$X,R0			; GET LAST HIT(X)
	CALL 	TR.X			; AND BUFFER IT
	MOVB	LP$DIS,TR$DIS		; GET LAST FILE HIT
	TST	RC$OPT			; IS THIS AN OPTION ?
	BNE	RC.OP1			; YES, SO PROCESS THE REMAINING
	JMP	$TRMIT			; TRANSMIT
	;
RC.RNH:	TST	LP$FLG			; IS LIGHT PEN ENABLED ?
	BEQ	RC.R1			; YES, WAIT FOR HIT
	MOVB	#5,TR$STA		; ELSE STATUS = "L.P. DISABLED"
	JMP	$TRMIT			; TRANSMIT
RC.R1:	MOV	#1,LP$HIT		; SET WAIT FLAG
	MOV	#"LW,ST.LP		; AND SHOW IN STATUS
RC.R2:	TST	LP$HIT			; AND TWIDDLE THUMBS
	BNE	RC.R2			; UNTIL WE GET A HIT
	BR	RC.RLH			; PROCESS THE HIT
	;
RC.DEL:	MOV	RC$DIS,R5		; GET DISPLAY NUMBER
	CALL 	$DELET			; AND DELETE IT
	JMP	$TRMIT			; TRANSMIT
	;
RC.SND:	MOVB	TR$OLD,TR$STA		; RESET STATUS
	JMP	$TRMIT			; AND RE-TRANSMIT LAST BLOCK
	;
RC.CLR:	CALL 	$CDINI			; INITIALIZE CDF.
	JMP	$TRMIT			; TRANSMIT
	;
RC.RST:	MOV	RC$DIS,CD$NEW		; GET DESIRED NUMBER OF LINES
	CALL 	$RESET			; AND RESET GIDUS
	JMP	$TRMIT			; TRANSMIT
	;
RC.OPT:	DISABL	10			; DISABLE THE POINTER
	ENABLE	6			; ENABLE THE PROMPT
	INC	RC$OPT			; INDICATE AN OPTION HIT
	BR	RC.RNH			; GET LIGHT PEN HIT
RC.OP1:	DISABL	6			; DISABLE THE PROMPT
	MOV	#740.,OP$X		; MOVE THE OPTION POINTER
	MOV	LP$Y,OP$Y
	ENABLE	10			; AND ENABLE THE POINTER
	JMP	$TRMIT			; AND TRANSMIT
	.PAGE
	.SBTTL	REQUEST TO ADD
	;
	; THIS ROUTINE PERFORMS THE FOLLOWING FUNCTIONS:
	;
	; [1] CHECKS IF THERE IS A FREE DISPLAY SLOT FOR FILE
	; [2] CHECKS IF THERE IS ENOUGH CORE FOR THE FILE
	; [3] SETS A MEMORY LIMIT BEYOND WHICH THE ADDITION CANNOT GO
	; [4] SETS UP MEMORY AREA FOR ADDITION
	;
RC.RAD:	MOV	#1,AD$FLG		; INDICATE ADDITION NOT ALLOWED
	CMP	DU$CNT,#77		; IS THERE A DISPLAY SLOT ?
	BLE	RC.R3			; YES, CONTINUE CHECKING
	MOVB	#7,TR$STA		; NO, STATUS = "NO DISPLAY SLOT"
	JMP	$TRMIT			; TRANSMIT STATUS
RC.R3:	MOV	RC$BCT,R0		; GET FILE SIZE
	ADD	#10.,R0			; ADD SAFETY FACTOR
	MOV	#STACK,R1		; GET UPPER MEMORY BOUND
	SUB	DF$TOP,R1		; SUBTRACT LOWER MEMORY BOUND
	CMP	R0,R1			; IS THERE ENOUGH CORE ?
	BLT	RC.R4			; YES, ALLOW THE ADDITION
	MOVB	#6,TR$STA		; NO, STATUS ="NOT ENOUGH CORE"
	JMP	$TRMIT			; TRANSMIT
RC.R4:	MOV	R0,AD$LIM		; SAVE SIZE FOR CHECK
	ADD	DF$TOP,AD$LIM		; DON'T ALLOW ADDITION PAST
	MOV	DF$TOP,AD$RST		; GET RESET POINTER
	MOV	DF$TOP,AD$PNT		; AND ACTIVE POINTER
	CLR	AD$FLG			; ALLOW ADDITION
	MOVB	#11.,TR$STA		; STATUS = "SEND NEXT BLOCK"
	JMP	$TRMIT			; TRANSMIT
	.PAGE
	.SBTTL	ADD NEXT BLOCK COMMAND
	;
	; THIS ROUTINE PERFORMS THE FOLLOWING FUNCTION
	;
	; [1] CHECK FOR NULL BLOCK (I.E. DISPLAY FILE SENT)
	; [2] CHECK FOR VALID BYTE COUNT
	; [3] CHECK IF LIMIT EXCEEDED
	; [4] UPDATE FILE POINTERS
	; [5] TELL 10 TO SEND BLOCK
	;
RC.ANB:	MOV	#1,AD$ABF		; DON'T ALLOW BLOCK
	MOV	RC$BCT,R0		; GET BYTE COUNT
	BLE	RC.LST			; IF ZERO THEN LAST BLOCK
	CMP	R0,#200			; VALID BYTE COUNT ?
	BLE	RC.A1			; YES
	MOVB	#12.,TR$STA		; NO, STATUS = "BAD BLOCK SIZE"
	JMP	$TRMIT			; TRANSMIT
RC.A1:	MOV	AD$RST,R1		; GET START ADDRESS
	ADD	R0,R1			; ADD BYTE COUNT
	CMP	R1,AD$LIM		; DOES IT EXCEED LIMIT ?
	BLO	RC.A2			; NO
	MOVB	#6,TR$STA		; STATUS = "NOT ENOUGH CORE"
	JMP	$TRMIT			; TRANSMIT
RC.A2:	TST	AD$FLG			; ADDITONS ALLOWED ?
	BEQ	RC.A3			; YES
	MOVB	#14.,TR$STA		; NO, STATUS = "ADDITION NOT ALLOWED"
	JMP	$TRMIT			; TRANSMIT
RC.A3:	MOV	AD$RST,AD$PNT		; UPDATE ACTIVE POINTER
	CLR	AD$SUM			; CLEAR THE CHECKSUM
	MOV	R0,AD$CNT		; CLEAR THE BYTE COUNT
	MOVB	#11.,TR$STA		; STATUS = "SEND NEXT BLOCK"
	CLR	AD$ABF			; CLEAR THE ALLOW BLOCK FLAG
	JMP	$TRMIT			; TRANSMIT
	.PAGE
	.SBTTL	LAST BLOCK ROUTINE
	;
	; THIS ROUTINE PERFORMS THE FOLLOWING FUNCTIONS
	;
	; [1] INSERTS DISPLAY INFORMATION INTO THE FIRST
	;     AVAILABLE DISPLAY SLOT
	; [2] INFORMS 10 OF THE DISPLAY SLOT CHOSEN
	; [3] UPDATE STATUS DISPLAY WITH
	;     NUMBER OF DISPLAYS, NUMBER DISABLED, AND FREE CORE
	;
RC.LST:	MOV	#$$DFT,R0		; R0 POINTS TO DISPLAY TABLE
	CLR	R1			; R1 IS DISPLAY NUMBER
RC.L1:	BIT	#EX.BIT,4(R0)		; IS THIS SLOT IN USE
	BEQ	RC.L2			; NO, SO USE IT
	ADD	#6,R0			; ELSE POINT TO NEXT SLOT
	INC	R1			; AND BUMP DISPLAY NUMBER
	CMP	R1,#77			; ARE WE THROUGH ?
	BLT	RC.L1			; NO, SO CONTINUE
RC.L2:	MOV	DF$TOP,(R0)+		; INSERT FIRST ADDRESS
	MOV	AD$RST,@R0		; AND LAST ADDRESS
	SUB	#2,(R0)+		; POINT TO LAST WORD
	MOV	RC$STA,@R0		; INSERT THE STATUS WORD
	BIS	#EX.BIT,@R0		; SET THE EXIST BIT
	BIC	#EN.BIT,@R0		; CLEAR THE ENABLED BIT
	MOVB	R1,TR$DIS		; BUFFER THE DISPLAY NUMBER
	FORMAT	R1,ST.LST,2		; AND SHOW IN STATUS DISPLAY
	INC	DU$CNT			; INCREMENT THE USED COUNT
	FORMAT	DU$CNT,ST.USE,2		; AND FORMAT INTO STATUS DISPLAY
	INC	DS$CNT			; INCREMENT THE DISABLED COUNT
	FORMAT	DS$CNT,ST.DIS,2		; AND FORMAT INTO STATUS DISPLAY
	MOV	AD$RST,DF$TOP		; UPDATE LOWER MEMORY BOUND
	MOV	#STACK,R1		; GET UPPER MEMORY BOUND
	SUB	DF$TOP,R1		; SUBTRACT LOWER BOUND
	ASR	R1			; FORM WORD COUNT
	FORMAT	R1,ST.FRE,5		; FORMAT THE FREE CORE
	CLRB	TR$STA			; ADDITION COMPLETED
	JMP	$TRMIT			; TRANSMIT
	.PAGE
	.SBTTL	ADD FILE INTERRUPT ROUTINE
	;
	; STATUS WORDS
	;
AD$LIM:	.WORD	0			; ADDITION CAN'T GO BEYOND
AD$CNT:	.WORD	0			; BYTE COUNT
AD$SUM:	.WORD	0			; CHECKSUM
AD$PNT:	.WORD	0			; ACTIVE POINTER
AD$RST:	.WORD	0			; RESET POINTER
AD$FLG:	.WORD	0			; ALLOW FLAG
AD$ABF:	.WORD	0			; ALLOW NEXT BLOCK FLAG
	;
$ADINT:	SAVREG				; SAVE THE REGISTERS
	MOVB	@#IB.GT,R0		; GET THE LAST CHARACTER
	BIC	#177400,R0		; CLEAR THE TOP BYTE
	ADD	R0,AD$SUM		; ADD INTO CHECKSUM
	DEC	AD$CNT			; DECREMENT THE BYTE COUNT
	BLE	AD.1			; IF ZERO THEN THROUGH
	MOVB	R0,@AD$PNT		; ELSE BUFFER THE BYTE
	INC	AD$PNT			; BUMP THE POINTER
AD.RET:	RESREG				; RESTORE THE REGISTERS
	RTI				; RETURN FROM INTERRUPT
	;
AD.1:	MOV	14.(SP),@#PSW		; ALLOW INTERRUPTS
	TSTB	AD$SUM			; IS THE CHECKSUM GOOD ?
	BNE	AD.2			; NO
	BIC	#1,AD$PNT		; YES MAKE THE LAST BYTE EVEN
	MOV	AD$PNT,AD$RST		; UPDATE RESET ADDRESS
	MOVB	#15.,TR$STA		; INDICATE BLOCK RECEIVED
	JMP	$TRMIT
	;
AD.2:	MOV	AD$RST,AD$PNT		; RESET ACTIVE POINTER
	MOVB	#66,TR$STA		; INDICATE CHECKSUM ERROR
	JMP	$TRMIT			; TRANSMIT
	.PAGE
	.SBTTL	TRANSMISSION ROUTINE
	;
	; TRANSMIT BUFFER
	;
TR$STA:	.BYTE	0			; STATUS BYTE
TR$XL:	.BYTE	0			; X POSITION
TR$XH:	.BYTE	0
TR$YL:	.BYTE	0			; Y POSITION
TR$YH:	.BYTE	0
TR$DIS:	.BYTE	0			; DISPLAY NUMBER
TR$SUM:	.BYTE	0			; CHECK SUM
	.BYTE	0			; FILLER
	;
TR$OLD:	.BYTE	0			; LAST STATUS
	;
	.EVEN
$TRMIT:	MOV	#"TR,ST.ATE		; INDICATE "TRANSMITTING"
	CLR	TR$SUM			; CLEAR THE CHECKSUM
	CLR	RC$OPT			; TURN OFF OPTION FLAG
	MOV	#TR$STA,R4		; R4 IS BUFFER POINTER
	MOV	#6,R3			; BYTE COUNT
TR.LUP:	MOVB	(R4)+,R5		; GET THE NEXT BYTE
	ADD	R5,TR$SUM		; ADD INTO CHECKSUM
	CMP	R5,#74			; IS IT A SPECIAL CHARACTER
	BGE	TR.1			; YES, SO BYPASS
	BIS	#100,R5			; ELSE MAKE PRINTABLE
TR.1:	CALL 	$SEND			; AND SEND IT
	SOB 	R3,TR.LUP		; DO SO FOR ALL CHARACTERS
	CLR	R5			; GET READY TO GET LOW BYTE
	BISB	TR$SUM,R5		; GET CHECKSUM
	ASR	R5			;
	ASR	R5			; SHIFT R5 FOUR PLACES
	ASR	R5			; IN ORDER TO GET HIGH 4 BITS
	ASR	R5			;
	BIS	#100,R5			; MAKE IT PRINTABLE
	CALL 	$SEND			; SEND FIRST HALF OF CSUM
	MOVB	TR$SUM,R5		; GET CHECKSUM
	BIC	#177760,R5		; CLEAR ALL EXCEPT LOW 4 BITS
	BIS	#100,R5			; MAKE PRINTABLE
	CALL 	$SEND			; SEND LAST HALF OF CHECKSUM
	MOV	#$DLINT,DL$VEC		; RESET INTERRUPT VECTOR
	CLR	$IO$			; CLEAR I/O FLAG
	MOV	ST.OLD,ST.ATE		; RESTORE GIDUS STATE
	RESREG				; RESTORE THE REGISTERS
	MOV	#"CH,ST.DL		; RESTORE DL-11 STATE
	RTI				; RETURN FROM INTERRUPT
	;
TR.X:	MOVB	R0,TR$XL		; GET LOW BYTE
	BICB	#340,TR$XL		; ONLY WANT FIVE BITS
	ASL	R0			; SHIFT R0 UP
	ASL	R0			;
	ASL	R0			; THREE BITS
	SWAB	R0			; SWAP THE BYTES
	MOVB	R0,TR$XH		; GET HIGH BYTE
	BICB	#340,TR$XH		; ONLY WANT FIVE BITS
	RETURN				; RETURN
	;
	BICB	#340,TR$YL		; ONLY WANT FIVE BITS
	ASL	R0			; SHIFT R0 UP
	ASL	R0			;
	ASL	R0			; THREE BITS
	SWAB	R0			; SWAP THE BYTES
	MOVB	R0,TR$YH		; GET HIGH BYTE
	BICB	#340,TR$YH		; ONLY WANT FIVE BITS
	RETURN				; RETURN
	;
TR.Y:	CALL 	TR.X			; FORMAT INTO X FIELD
	MOVB	TR$XL,TR$YL		; AND MOVE INTO
	MOVB	TR$XH,TR$YH		; Y FIELD
	RETURN				; AND RETURN
	.PAGE
$SEND:	TSTB	@#OS.GT			; IS 10 READY
	BPL	$SEND			; WAIT UNTIL READY
	MOVB	R5,@#OB.GT		; SEND THE CHARACTER
	RETURN				; RETURN
	.PAGE
	.SBTTL	ENABLE A DISPLAY FILE
	;
	; UPON ENTRY R5 CONTAINS DISPLAY FILE
	; NUMBER TO BE ENABLED
	;
$ENABL:	SAVREG				; SAVE THE REGISTERS
	CLRB	TR$STA			; INDICATE GOOD ENABLE
	TST	R5			; IS DISPLAY NUMBER NEGATIVE ?
	BLT	EN.BN			; YES, ERROR
	CMP	R5,#77			; IS DISPLAY NUMBER IN RANGE
	BLE	EN.GN			; YES, GOOD NUMBER
EN.BN:	MOV	#ER$BDN,R4		; R4 IS ERROR POINTER
	CALL 	$ERROR			; WARNING "% BAD DISPLAY NUMBER"
	MOVB	#3,TR$STA		; INDICATE ERROR CONDITION
	BR	EN.RET			; RETURN
EN.GN:	CLR	SE$MOD			; INDICATE DIRECT SEARCH MODE
	CALL 	$SERCH			; GET THIS DISPLAY STATUS
	BIT	#EX.BIT,4(R4)		; DOES THE DISPLAY EXIST ?
	BNE	EN.1			; YES, CONTINUE
	MOV	#ER$DDE,R4		; R4 IS ERROR POINTER
	CALL 	$ERROR			; WARNING "%DISPLAY DOES NOT EXIST"
	INCB	TR$STA			; LET 10 KNOW THE ERROR
	BR	EN.RET			; AND RETURN
EN.1:	BIT	#EN.BIT,4(R4)		; IS THE DISPLAY ENABLED ?
	BNE	EN.RET			; YES, RETURN
	MOV	R4,R3			; SAVE POINTER TO THIS ENTRY
	INC	SE$MOD			; INDICATE INDIRECT SEARCH MODE
	CALL 	$SERCH			; FIND A DISPLAY POINTING PAST
	TST	R4			; WAS THE DISPLAY FOUND ?
	BGT	EN.FND			; YES, CONTINUE
	MOV	#ER$FNF,R4		; R4 IS ERROR POINTER
	CALL 	$ERROR			; FATAL "? DISPLAY TABLE CORRUPT"
	BR	EN.RET			; RETURN
	;
EN.FND:	CALL 	$DSTOP			; POLITELY STOP THE DISPLAY
	MOV	2(R4),R0		; GET ADDR. OF LAST WORD OF PREV. DISP.
	MOV	2(R3),R1		; GET ADDR. OF LAST WORD OF THIS DISP.
	MOV	@R0,@R1			; NEW DISPLAY DJMPS TO NEXT IN LIST
	CLR	@R0			; RESET PREV. DISP. TO POINT
	BIS	@R3,@R0			; TO NEW DISPLAY
	MOV	4(R4),R0		; GET STATUS POINTER OF PREV. DISP.
	BIC	#177700,R0		; MASK OUT ALL BUT POINTER
	BIS	R0,4(R3)		; COPY POINTER TO NEW DISP.
	BIC	#PT.BIT,4(R4)		; CLEAR POINTER OF PREV. DISP.
	BIS	R5,4(R4)		; INSERT NEW DISPLAY NUMBER
	DEC	DS$CNT			; DECREMENT THE DISABLED COUNT
	FORMAT	DS$CNT,ST.DIS,2		; AND FORMAT INTO STATUS DISPLAY
	BIS	#EN.BIT,4(R3)		; INDICATE DISPLAY IS ENABLED
	MOV	#FIRST.,@#DPC		; RESTART THE DISPLAY
EN.RET:	RESREG				; RESTORE THE REGISTERS
	RETURN				; AND RETURN
	.PAGE
	.SBTTL	DISABLE A DISPLAY FILE
	;
	; UPON ENTRY R5 CONTAINS DISPLAY NUMBER
	; TO BE DISABLED
	;
DU$CNT:	.WORD	12			; NUMBER OF DISPLAY FILES USED
DS$CNT:	.WORD	3			; NUMBER OF DISABLED DISPLAY FILES
	;
$DSABL:	SAVREG				; SAVE THE REGISTERS
	CLRB	TR$STA			; INDICATE GOOD DISABLE
	TST	R5			; IS DISPLAY NUMBER NEGATIVE
	BLT	DS.BN			; YES, ERROR
	CMP	R5,#77			; IS DISPLAY NUMBER IN RANGE ?
	BLE	DS.GN			; YES, WE HAVE A GOOD NUMBER
DS.BN:	MOV	#ER$BDN,R4		; R4 IS ERROR POINTER
	CALL 	$ERROR			; WARNING "% BAD DISPLAY NUMBER"
	MOVB	#3,TR$STA		; INDICATE ERROR CONDITION
	BR	DS.RET			; RETURN
DS.GN:	CLR	SE$MOD			; INDICATE DIRECT SEARCH MODE
	CALL 	$SERCH			; GET THIS DISPLAY STATUS
	BIT	#EN.BIT,4(R4)		; IS DISPLAY DISABLED ?
	BEQ	DS.RET			; YES, RETURN
	BIT	#ND.BIT,4(R4)		; CAN DISPLAY BE DISABLED ?
	BEQ	DS.1			; YES, DO SO
	MOV	#ER$ND,R4		; R4 IS #ERROR POINTER
	CALL 	$ERROR			; WARNING "% CANNOT DISABLE"
	MOVB	#2,TR$STA		; INDICATE ERROR CONDITION
	BR	DS.RET			; RETURN
DS.1:	MOV	R4,R3			; SAVE POINTER TO THIS ENTRY
	DEC	SE$MOD			; INDICATE INDIRECT SEARCH MODE
	CALL 	$SERCH			; FIND THE PREVIOUS DISPLAY
	TST	R4			; WAS THE DISPLAY FOUND ?
	BGT	DS.FND			; YES, CONTINUE
	MOV	#ER$FNF,R4		; R4 IS ERROR POINTER
	CALL 	$ERROR			; FATAL "? DISPLAY TABLE CORRUPT"
	BR	DS.RET			; RETURN
	;
DS.FND:	CALL 	$DSTOP			; STOP THE DISPLAY
	MOV	2(R4),R0		; GET ADDR. OF LAST WORD OF PREV. DISP.
	MOV	2(R3),R1		; GET ADDR. OF LAST WORD OF THIS DISP.
	CLR	@R0			; RESET PREVIOUS DISPLAY
	BIS	@R1,@R0			; TO POINT TO NEXT DISPLAY
	MOV	4(R3),R0		; R0 GETS POINTER WORD
	BIC	#177700,R0		; CLEAR ALL EXCEPT POINTER
	BIC	#PT.BIT,4(R4)		; CLEAR PREV. POINTER
	BIS	R0,4(R4)		; CHANGE TO NEW POINTER
	BIC	#PT.BIT,4(R3)		; DISABLE THIS POINTER
	BIC	#EN.BIT,4(R3)		; TURN OFF ENABLED BIT
	INC	DS$CNT			; INCREMENT DISABLED COUNT
	FORMAT	DS$CNT,ST.DIS,2		; FORMAT INTO STATUS DISPLAY
	MOV	#FIRST.,@#DPC		; RESTART THE DISPLAY
DS.RET:	RESREG				; RESTORE THE REGISTERS
	RETURN				; AND RETURN
	.PAGE
	.SBTTL	DISPLAY TABLE SEARCH ROUTINE
	;
SE$MOD:	.WORD	0			; SEARCH MODE
	;
	;	0  = DIRECT SEARCH FOR REQUESTED DISPLAY
	;	-1 = SEARCH FOR DISPLAY POINTING TO REQUESTED
	;	1  = SEARCH FOR DISPLAY POINTING PAST REQUESTED
	;
$SERCH:	MOV	#$$DFT,R4		; R4 POINTS TO DISPLAY TABLE
	TST	SE$MOD			; WHAT KIND OF SEARCH ?
	BNE	SE.IND			; INDIRECT SEARCH
	MOV	R5,R0			; DIRECT SEARCH, GET NUMBER
	ASL	R0			; MULTIPLY BY TWO
	ADD	R5,R0			; ADD (JUST R0 * 3)
	ASL	R0			; FORM WORD OFFSET
	ADD	R0,R4			; ADD TO BASE ADDRESS
	BR	SE.RET			; AND RETURN
	;
SE.IND:	MOV	#64.,R1			; R1 = NUMBER OF DISPLAY FILES
SE.LUP:	MOV	4(R4),R0		; GET STATUS POINTER WORD
	BIC	#177700,R0		; CLEAR ALL EXCEPT POINTER
	CMP	R0,R5			; COMPARE WITH REQUESTED
	BGE	SE.FND			; IF >= SEARCH MAY BE OVER
SE.CON:	ADD	#6,R4			; ELSE LOOP
	SOB 	R1,SE.LUP		; FOR ALL DISPLAY FILES
	CLR	R4			; INDICATE UNSUCCESSFUL
	BR	SE.RET			; AND RETURN
SE.FND:	TST	SE$MOD			; WHAT KIND OF SEARCH ?
	BGT	SE.PST			; LOOK FOR FILE POINTING PAST
	CMP	R0,R5			; IS THIS THE ONE ?
	BNE	SE.CON			; NO, CONTINUE
	BR	SE.RET			; YES, RETURN
SE.PST:	CMP	R0,R5			; IS THIS THE ONE ?
	BGT	SE.RET			; YES, RETURN
	CLR	R4			; NO, BAD SEARCH
SE.RET:	RETURN				; RETURN
	.PAGE
	.SBTTL	DELETE ROUTINE
	;
	; THIS ROUTINE IS USED TO DELETE A SPECIFIED
	; DISPLAY FILE, AND COMPRESS THE REMAINING DISPLAY
	; FILES IN ORDER TO RECLAIM THE CORE USED
	;
DE$LOW:	.WORD	0			; START ADDRESS OF DISPLAY
DE$HGH:	.WORD	0			; END ADDRESS OF DISPLAY
DE$SAV:	.WORD	0			; NUMBER OF BYTES RECLAIMED
	;
$DELET:	SAVREG				; SAVE THE REGISTERS
	TST	R5			; IS THIS A GOOD DISPLAY ?
	BLT	DE.BDN			; NO, SO ERROR
	CMP	R5,#77			; IS THIS A GOOD DISPLAY ?
	BLE	DE.GDN			; YES, SO CONTINUE
DE.BDN:	MOV	#ER$BDN,R4		; R4 IS ERROR POINTER
	CALL 	$ERROR			; WARNING "% BAD DISPLAY NUMBER"
	MOVB	#3,TR$STA		; LET 10 KNOW THE ERROR
	JMP	DE.RET			; AND RETURN
	;
DE.GDN:	CLR	SE$MOD			; INDICATE DIRECT SEARCH MODE
	CALL 	$SERCH			; LOOK FOR DISPLAY
	BIT	#EX.BIT,4(R4)		; DOES THIS DISPLAY EXIST
	BNE	DE.DE			; YES, SO CONTINUE
	MOV	#ER$DDE,R4		; R4 IS ERROR POINTER
	CALL 	$ERROR			; WARNING "% DISPLAY DOES NOT EXIST"
	INCB	TR$STA			; LET 10 KNOW THE ERROR
	JMP	DE.RET			; AND RETURN
	;
DE.DE:	BIT	#WP.BIT,4(R4)		; IS THE DISPLAY WRITE-PROTECTED
	BEQ	DE.WE			; NO, SO CONTINUE
	MOV	#ER$WP,R4		; R4 IS ERROR POINTER
	CALL 	$ERROR			; WARNING "% CANNOT DELETE THIS DISPLAY"
	MOVB	#8.,TR$STA		; LET 10 KNOW THE ERROR
	JMP	DE.RET			; AND RETURN
	;
DE.WE:	MOV	@R4,R1			; GET LOW ADDRESS
	MOV	R1,DE$LOW		; AND SAVE
	MOV	2(R4),R2		; GET HIGH ADDRESS
	ADD	#2,R2			; POINT ONE WORD PAST
	MOV	R2,DE$HGH		; AND SAVE
	SUB	R1,R2			; GET BYTE COUNT
	MOV	R2,DE$SAV		; AND SAVE
	BIC	#ND.BIT,4(R4)		; IGNORE THE DISABLE BIT
	CALL 	$DSABL			; DISABLE THE DISPLAY
	CLR	(R4)+			;
	CLR	(R4)+			; REMOVE DISPLAY TABLE ENTRY
	CLR	(R4)+			;
	.PAGE
	; LOOP THROUGH THE DISPLAY TABLE. IF ANY ADDRESS WORDS
	; WERE POINTING PAST THE DELETED DISPLAY, THEY SHOULD
	; BE UPDATED TO THE NEW ADDRESS (CURRENT - DE$SAV)
	; IN ORDER TO MAKE THESE TABLE MODIFICATIONS THE DISPLAY
	; WILL HAVE TO BE STOPPED
	;
	MOV	#$$DFT,R4		; R4 POINTS TO DISPLAY TABLE
	MOV	#77,R0			; R0 IS NUMBER OF DISPLAYS
	CALL 	$DSTOP			; STOP THE DISPLAY
DE.TBL:	MOV	2(R4),R3		; SAVE LAST ADDRESS IN R3
	BIT	#EX.BIT,4(R4)		; DOES THE DISPLAY EXIST
	BNE	DE.0			; YES, CONTINUE CHECKING
	ADD	#4,R4			; NO, POINT TO NEXT ENTRY
	BR	DE.3			; AND CONTINUE THE LOOP
DE.0:	CMP	(R4)+,DE$HGH		; DOES THIS NEED TO BE CHANGED ?
	BLT	DE.1			; NO, SON CONTINUE
	SUB	DE$SAV,-2(R4)		; YES, UPDATE THE ADDRESS
DE.1:	CMP	(R4)+,DE$HGH		; DOES THIS NEED A CHANGE ?
	BLT	DE.2			; NO, SO CONTINUE
	SUB	DE$SAV,-2(R4)		; YES, UPDATE THE ADDRESS
DE.2:	CMP	@R3,DE$HGH		; DOES IT NEED TO BE CHANGED ?
	BLT	DE.3			; NO, SO CONTINUE
	SUB	DE$SAV,@R3		; UPDATE THE ADDRESS
DE.3:	TST	(R4)+			; POINT TO NEXT TABLE ENTRY
	SOB 	R0,DE.TBL		; LOOP FOR ALL DISPLAYS
	;
	; NOW CORE NEEDS TO BE COMPACTED. THIS IS DONE BY SHIFTING
	; EACH WORD ABOVE DE$HGH TO THE CORRESPONDING LOCATION
	; ABOVE DE$LOW. WHEN SHIFTING DISPLAYS IN THIS MANNER
	; IT WILL BE NECESSARY TO MODIFY ANY DJMP'S THAT
	; ORIGINALLY POINTED PAST DE$HGH.
	;
	MOV	DE$LOW,R0		; GET DESTINATION ADDRESS
	MOV	DE$HGH,R1		; GET SOURCE ADDRESS
	;
DE.MOV:	CMP	R1,#STACK		; ARE WE THROUGH YET ?
	BGE	DE.FIN			; YES, GO FINISH UP
	MOV	(R1)+,(R0)+		; MOVE THE WORD
	BR	DE.MOV			; AND CONTINUE
	;
	; RESTART THE DISPLAY, AND FIXUP THE STATUS DISPLAY
	;
DE.FIN:	MOV	#FIRST.,@#DPC		; *** RESTART DISPLAY ***
	SUB	DE$SAV,DF$TOP		; RESET MEMORY POINTER
	MOV	#STACK,R1		; GET UPPER MEMORY BOUND
	SUB	DF$TOP,R1		; SUBTRACT LOWER BOUND
	ASR	R1			; FORM WORD COUNT
	FORMAT	R1,ST.FRE,5		; AND FORMAT INTO STATUS DISPLAY
	DEC	DU$CNT			; THERE IS ONE LESS DISPLAY
	DEC	DS$CNT			; AND ONE LESS DISABLED
	FORMAT	DU$CNT,ST.USE,2		; FORMAT INTO STATUS DISPLAY
	FORMAT	DS$CNT,ST.DIS,2		; "   "    "    "   "    "
DE.RET:	RESREG				; RESTORE THE REGISTERS
	RETURN				; AND RETURN
	.PAGE
	.SBTTL	RESET ROUTINE
	;
	; THIS ROUTINE IS USED TO RESET GIDUS BY PERFORMING
	; THE FOLLOWING TASKS:
	;
	; [1] ALL USER DISPLAY FILES ARE DELETED
	; [2] A NEW SCROLLING AREA IS LAYED OUT
	; [3] THE POINTERS ARE RESET
	; [4] THE APPROPRIATE DISPLAYS ARE ENABLED AND DISABLED
	;
$RESET:	SAVREG				; SAVE THE REGISTERS
	MOV	#DF$USR + 4,R1		; R1 POINTS TO DISPLAY TABLE
	MOV	#54.,R2			; R2 IS NUMBER OF USER DISPLAYS
	MOV	#11,R5			; FIRST USER DISPLAY NUMBER
RE.1:	BIT	#EX.BIT,@R1		; DOES THE DISPLAY EXIST ?
	BEQ	RE.2			; NO, SO IGNORE IT
	BIC	#WP.BIT,@R1		; YES, SO CLEAR W.P. BIT
	CALL	$DELET			; AND DELETE THE DISPLAY FILE
RE.2:	ADD	#6,R1			; POINT TO NEXT DISPLAY
	INC	R5			; GET DISPLAY NUMBER
	SOB	R2,RE.1			; AND LOOP FOR ALL USER DISPLAYS
	;
	; LAYOUT A NEW SCROLLING AREA
	;
	DISABL	1			; DISABLE CDF. FOR TIME BEING
	CALL	$DSTOP			; STOP THE DISPLAY
	CALL	$CDINI			; LAYOUT THE SCROLLING AREA
	MOV	CD$END,DF$TOP		; RESET LOWER CORE BOUND
	MOV	#FIRST.,@#DPC		; AND RESTART THE DISPLAY
	;
	; RESET THE POINTERS AND DISABLE THE LIGHT PEN
	;
	MOV	#760,MP.X		; RESET THE MAIN POINTER
	MOV	#1320,MP.Y
	FORMAT	MP.X,ST.MPX,4		; FORMAT INTO STATUS DISPLAY
	FORMAT	MP.Y,ST.MPY,4
	MOV	#1303,AP.X		; RESET THE AUX. POINTER
	MOV	#1320,AP.Y
	FORMAT	AP.X,ST.APX,4		; FORMAT INTO STATUS DISPLAY
	FORMAT	AP.Y,ST.APY,4
	MOV	#1,LP$FLG		; DISABLE THE LIGHT PEN
	CLR	LP$HIT
	MOV	#"LD,ST.LP		; INDICATE IN STATUS DISPLAY
	;
	; ENABLE AND DISABLE THE APPROPRIATE GIDUS DISPLAYS
	;
	CMP	CD$NEW,#27.		; IS THERE ROOM FOR STATUS
	BGT	RE.3			; NO, SO DISABLE IT
	ENABLE	2			; YES, SO ENABLE
	ENABLE	4			; AND ENABLE THE POINTERS
	ENABLE	5
	BR	RE.4			; AND CONTINUE
RE.3:	DISABL	2			; DISABLE STATUS
	DISABL	4			; AND THE POINTERS
	DISABL	5
RE.4:	ENABLE	1			; ENABLE CDF.
	DISABL	6			; DISABLE OPTION MESSAGE
	DISABL	10			; AND OPTION POINTER
	;
	; FIXUP THE STATUS DISPLAY AND TURN OFF ANY ERROR MESSAGES
	;
	MOV	#STACK,R1		; GET UPPER MEMORY BOUND
	SUB	DF$TOP,R1		; SUBTRACT LOWER MEMORY BOUND
	ASR	R1			; FORM WORD COUNT
	FORMAT	R1,ST.FRE,5		; AND FORMAT INTO STATUS DISPLAY
	CLR	R1			; LAST DISPLAY ADDED = 0
	FORMAT	R1,ST.LST,2		; INDICATE IN STATUS DISPLAY
	MOV	#ME.END,ME.ON		; TURN OFF ERROR MESSAGES
	RESREG				; RESTORE THE REGISTERS
	RETURN				; AND RETURN
	.PAGE
	.SBTTL	ERROR DISPLAY ROUTINE
	;
	; UPON ENTRY R4 POINTS TO ERROR MESSAGE
	; WHICH IS AN ASCIZ STRING
	;
	.NLIST	BEX
ER$BDN:	.ASCIZ	/% BAD DISPLAY FILE NUMBER/
ER$FNF:	.ASCIZ	/? DISPLAY FILE NOT FOUND (DISPLAY TABLE CORRUPT)/
ER$ND:	.ASCIZ	/% CANNOT DISABLE A NO-DISABLE DISPLAY FILE/
ER$WP:	.ASCIZ	/% CANNOT DELETE A WRITE PROTECTED DISPLAY FILE/
ER$ADD:	.ASCIZ	/? ODD ADDRESS REFERENCE ?/
ER$DDE:	.ASCIZ	/% DISPLAY DOES NOT EXIST/
	.EVEN
	.LIST	BEX
	;
$ERROR:	SAVREG				; SAVE THE REGISTERS
	MOV	#ME.TXT,R0		; R0 POINTS AT TEXT LINE
	MOV	#"  ,R1			; R1 USED TO BLANK OUT LINE
	MOV	#36.,R2			; NUMBER OF WORDS TO ZAP
ER.1:	MOV	R1,(R0)+		; BLANK IT OUT
	SOB 	R2,ER.1
	MOV	#ME.TXT,R0		; R0 POINTS AT TEXT LINE
ER.2:	MOVB	(R4)+,(R0)+		; MOVE IN CHARACTERS
	BNE	ER.2			; UNTIL NULL
	MOV	#ME.ON,R0		; NOW TURN ON
	MOV	#ME.ON+2,@R0		; THE DISPLAY
	RESREG				; RESTORE THE REGISTERS
	RETURN				; AND RETURN
	.PAGE
	.SBTTL	UTILITY ROUTINES
	;
$SAVRG:	PUSH 	R1			;
	PUSH 	R2			;
	PUSH 	R3			; SAVE ON THE STACK
	PUSH 	R4			;
	PUSH 	R5			;
	MOV	R0,PC			; AND RETURN
	;
	;
	;
$RESRG:	TST	(SP)+			; THROW AWAY R0
	POP 	R5			;
	POP 	R4			;
	POP 	R3			; POP ALL REGISTERS
	POP 	R2			; OFF THE STACK
	POP 	R1			;
	RTS	R0			; RESTORE R0 AND RETURN
	.PAGE
	.SBTTL	DISPLAY STOP ROUTINE
	;
	; THIS ROUTINE POLITELY STOPS THE DISPLAY
	;
$DSTOP:	CMP	DPC,#LAS.1
	BEQ	DS.R9
	MOV	#1,ST$FNC		; STOP FUNCTION
	PUSH 	@#PSW			; SAVE PSW
	CLR	@#PSW			; ALLOW THE STOP
DS.WA:	TST	ST$FNC			; HAVE WE STOPPED YET ?
	BNE	DS.WA			; NO, KEEP WAITING
	POP 	@#PSW			; RESTORE THE OLD PSW
DS.R9:	RETURN				; RETURN
	.PAGE
	; $FRMAT - CONVERT R0 TO OCTAL
	;
	; R1 POINTS TO OUTPUT AREA
	; R2 CONTAINS NUMBER OF DIGITS TO CONVERT
	;
$FRMAT:	ADD	R2,R1			; SET UP POINTER
FR.NXT:	MOV	R5,R3			; USE R3 FOR TEMP. STORAGE
	BIC	#177770,R3		; CLEAR ALL EXCEPT BOTTOM DIGIT
	ADD	#60,R3			; CONVERT TO ASCII
	MOVB	R3,-(R1)		; MOVE TO OUTPUT AREA
	DEC	R2			; LOOP FOR
	BLE	FR.RET			; ALL DIGITS
	CLC				; CLEAR CARRY BIT FOR ROTATE
	BIC	#7,R5			; ZAP BOTTOM DIGIT
	ROR	R5			;
	ROR	R5			; GET NEXT DIGIT
	ROR	R5			;
	BR	FR.NXT			; AND CONVERT IT
FR.RET:	RETURN				; RETURN
	.PAGE
	.SBTTL	GIDUS DISPLAY FILES
	; FIRST DISPLAY FILE
	;
FIRST.:	STATSA ! SINOF ! ITAL0 ! LPDARK ; LOAD STATUS A, NO INTERRUPTS
					; NORMAL FONT
					; L.P. HITS NOT BRIGHTENED
	CHAR				; CHARACTER MODE
	.BYTE	<SI.CH>,0		; SHIFT IN
FI.END:	DJMP,CDF.
	.PAGE
	; GIDUS STATUS DISPLAY FILE
	;
STATS.:	POINT				; SGM - POINT MODE
	.WORD	0,1350			; FIRST LINE OF SCREEN
	CHAR ! BLKOFF			; SGM - CHARACTER MODE
ST.ATE:	.ASCII	/TI / <0>		; GIDUS STATE
ST.DL:	.ASCII	/CH FR=/		; DL-11 STATE
ST.FRE:	.ASCII	/00000 DU=/		; FREE CORE
ST.USE:	.ASCII	/12 DD=/		; DISPLAYS IN USE
ST.DIS:	.ASCII	/03 LA=/		; DISABLED DISPLAYS
ST.LST:	.ASCII	/00 MP=(/		; LAST DISPLAY ADDED
ST.MPX:	.ASCII	/0760,/			; MAIN POINTER X
ST.MPY:	.ASCII	/1320) AP=(/		; MAIN POINTER Y
ST.APX:	.ASCII	/1303,/			; AUX. POINTER X
ST.APY:	.ASCII	/1320) /		; AUX. POINTER Y
ST.LP:	.ASCII	/LD /			; L.P. STATUS
ST.TRC:	.ASCII	/TRACE /		; TRACE VARIABLE
	.BYTE	0			; .EVEN
ST.END:	DJMP,MESAG.			; ONTO NEXT DISPLAY
ST.OLD:	.WORD	0			; OLD STATUS
	.PAGE
	; MESSAGE DISPLAY FILE
	;
MESAG.:	POINT				; SGM - POINT MODE
	.WORD	0,1321			; SECOND LINE OF DISPLAY
	DJMP				; DISABLE AS A SUB-FILE
ME.ON:	ME.END
	CHAR ! BLKON ! INT3		; SGM - CHARACTER MODE
	.NLIST	BEX
ME.TXT:	.ASCII	/GIDUS MESSAGE DISPLAY FILE/
	.BYTE 0
	.ASCII	/                                             /
	.LIST	BEX
ME.END:	DJMP,MP.			; ONTO MAIN POINTER
	.PAGE
	; MAIN POINTER DISPLAY FILE
	;
MP.:	POINT!LPOFF!INT2!BLKOFF!LINE0	; SGM - POINT MODE
MP.X:	.WORD	760			; X POSITION
MP.Y:	.WORD	1320			; Y POSITION
	SHORTV				; SGM - SHORT VECTOR
	SV	30,0			;
	SV	-60,0,1			;
	SV	30,30			; THE POINTER
	SV	0,-60,1			;
	SV	5,0
	CHAR ! INT2 ! LPOFF		; SGM - CHARACTER MODE
	.ASCII	/MP/			; FOR MAIN POINTER
MP.END:	DJMP,AP.			; ONTO AUX. POINTER DISPLAY FILE
	;
	;
	;
	;
	;
	;
	; AUXILLARY POINTER DISPLAY FILE
	;
AP.:	POINT!LPOFF!INT2!BLKOFF!LINE0	; SGM - POINT MODE
AP.X:	.WORD	1303			; X POSITION
AP.Y:	.WORD	1320			; Y POSITION
	SHORTV				; SGM - RELATIVE VECTOR
	SV	30,0			;
	SV	-60,0,1			;
	SV	30,30			; THE POINTER
	SV	0,-60,1			;
	SV	5,0			;
	CHAR ! INT2 ! LPOFF		; SGM - CHARACTER MODE
	.ASCII	/AP/			; FOR AUX. POINTER
AP.END:	DJMP,LAST.			; ONTO NEXT DISPLAY FILE
	.PAGE
	; OPTION LIST DISPLAY FILE
	;
OMSG.:	POINT ! LPOFF ! BLKON ! INT3	; OPTION MESSAGE FILE
	.WORD	810., 655.		; POSITION
	STATSA ! ITAL0			; NORMAL FONT
	CHAR				; CHARACTER MODE
	.ASCII	/SELECT OPTION/
	.BYTE	0
OM.END:	DJMP,0				; A DISABLED DISPLAY FILE
	.PAGE
	; GIDUS COMMAND DISPLAY FILE
	;
GCMND.:	POINT ! LPOFF ! BLKOFF ! INT2	; SGM - POINT MODE
	.WORD	0			; X POSITION
	.WORD	1246			; Y POSITION
	CHAR				; SGM - CHARACTER MODE
	STATSA ! ITAL1			; ITALICS ON
	.ASCII	/GIDUS>> /
	STATSA ! ITAL0			; ITALICS OFF
GC.LNE:	.ASCII	/              / <CR.CH> <LF.CH>
GC.ANS:	.ASCII	/      /		; COMMAND ANSWER
	DJMP				; A DISABLED SUB-DISPLAY FILE
GC.HLP:	GC.END
	POINT				; SGM - POINT MODE
	.WORD	0			; X POSITION
	.WORD	1170			; Y POSITION
	CHAR				; SGM - CHARACTER MODE
	.NLIST	BEX
	.ASCII	/COMMANDS ARE:/ <CR.CH> <LF.CH>
	.ASCII	<LF.CH> /DISABLE N/ <CR.CH> <LF.CH>
	.ASCII	/ENABLE  N/ <CR.CH> <LF.CH>
	.ASCII	/(LD) DISABLE LIGHT PEN/ <CR.CH> <LF.CH>
	.ASCII	/(LE) ENABLE LIGHT PEN/ <CR.CH> <LF.CH>
	.ASCII	/SPEED   N/ <CR.CH> <LF.CH>
	.ASCII	/DELETE  N/ <CR.CH> <LF.CH>
	.ASCII	/EXAMINE ADDR/ <CR.CH> <LF.CH>
	.ASCII	/MODIFY  VALUE/ <CR.CH> <LF.CH>
	.ASCII	/TRACE   ADDR/ <CR.CH> <LF.CH>
	.ASCII	/HELP/ <CR.CH> <LF.CH>
	.ASCII	/RESET NLINES/ <CR.CH> <LF.CH>
	.ASCII	/OFF/
	.EVEN
	.LIST	BEX
GC.END:	DJMP,0				; A DISABLED DISPLAY FILE
	;
	;
	; OPTION POINTER DISPLAY FILE
	;
OPTR.:	POINT ! LPOFF ! BLKON ! INT3
OP$X:	.WORD	740.			; X POSITION
OP$Y:	.WORD	0			; Y POSITION
	STATSA ! ITAL0			; NORMAL FONT
	CHAR				; CHARACTER MODE
	.ASCII	/==>/
	.BYTE	0
OP.END:	DJMP,0				; A DISABLED DISPLAY FILE
	.PAGE
	; LAST DISPLAY FILE
	;
LAST.:	DSTOP				; STOP WITH INTERRUPT
LAS.1:	DJMP,FIRST.			; RE-DISPLAY
	;
	;
	;
	;
	;
	;
DHALT.:	STATSA!SINOF			; FULL STOP, NO INT.
	;
CDF.:	POINT!INT2!BLKON
CDF.X:	.WORD	0,<LST.SC>
	CHAR
	.BYTE	<CRS.CH>,0
	STATSA!ITAL0
	;
	;
	;
	;
	;
	.END	$START