;-*-MIDAS-*-
;;; Copyright (c) 1999 Massachusetts Institute of Technology
;;; See the COPYING file at the top-level directory of this project.

.SBTTL MACROS AND CONDITIONAL ASSEMBLY

;AI PDP-11 TV CONSOLE PROGRAM
;	USER WHO-LINE VARIABLES CODE ADDED 7/28/75 BY GLS
;	AUDIO SWITCH CODE REWRITTEN 7/12/76 BY ED
;	TV IS PDP-11 NUMBER 0 TO THE 10-11 INTERFACE.
;       ELEVATOR CODE 2/13/79 BY DANNY & HIC
;	REGION-SCROLLING 11/3/79 MOON

FONTSW==1	;COMPILE FONTS
FONTMS==0	;USE MACROS TO COMPILE FONTS

;REGISTER ASSIGNMENTS

A=%0		;ASCII CHARACTER
B=%1		;META BITS
C=%2		;C, T, AND TT ARE TEMPORARIES
T=%3
TT=%4
U=%5		;LINE EDITOR OR PAGE PRINTER
SP=%6
PC=%7

.XCREF	A,B,C,T,TT,U,SP,PC,...,....

.IIF E FONTSW,.TITLE TV NOFONTS

.IF NE FONTSW
.TITLE TV
.IF NE FONTMS
.NLIST	;WE'RE ONLY INTERESTED IN FONTS
.IF1
.PRINT /THIS ASSEMBLY WILL TAKE FOREVER!
/
.ENDC	;.IF1
.ENDC	;.IF NE FONTMS
.ENDC	;.IF NE FONTSW

.MACRO	PUSH A
.NLIST
	MOV	A,-(SP)
.LIST
.ENDM

.MACRO	POP A
.NLIST
	MOV	(SP)+,A
.LIST
.ENDM

.MACRO REPORT TEXT,NUM
.NLIST
.IF2
.LIST
.PRINT /TEXT'NUM
/
.NLIST
.ENDC
.LIST
.ENDM

.MACRO CHROFF
.NLIST
	MOVB	PS,-(SP)
	MOVB	#LKLVL,PS
.LIST
.ENDM

.MACRO CHRON
.NLIST
	MOVB	(SP)+,PS
.LIST
.ENDM

.MACRO BLKOFF A
.NLIST
	INCB	BLKSWT(A)
.LIST
.ENDM

.MACRO BLKON A
.NLIST
	DECB	BLKSWT(A)
	BGE	.+4
	BPT
.LIST
.ENDM

.MACRO TENWRD
.NLIST
.IIF NE .&3,.=<.&177774>+4
.LIST
.ENDM

.MACRO CHECK TAG,LENGTH
.NLIST
.IF NE .-<TAG>-<LENGTH>
.ERROR TAG WRONG LENGTH
.ENDC
.EVEN
.LIST
.ENDM

.MACRO TYPOUT A
.NLIST
	JSR	PC,OUTSTR
	.ASCIZ A
	.EVEN
.LIST
.ENDM

.MACRO DECTYPE	NUM
.NLIST
	MOV	NUM,A
	JSR	PC,DECPNT
.LIST
.ENDM

.MACRO	OCTYPE	NUM
.NLIST
	MOV	NUM,A
	JSR	PC,OCTPNT
.LIST
.ENDM

.MACRO ZAPFLG	FLAG
.NLIST
%COMPAT==0
	MOV	PC,FLAG
%COMPAT==1
.LIST
.ENDM

.MACRO CONC A,B,C,D,E,F,G,H,I
A'B'C'D'E'F'G'H'I
.ENDM

.IF NE 0	;PROGRAM MAP:
0, TO PDLORG		;TRAP VECTORS
PDLORG, TO KBDBUF	;PUSH DOWN LIST
KBDBUF, TO GO		;KBD BUFFER
GO, TO XTAB		;PROGRAM
XTAB, TO FNTORG		;KEYBOARD TRANSLATION TABLE
FNTORG, TO VARORG	;FONT DEFINITION
VARORG, TO MISORG	;LINE EDITOR/PAGE PRINTER VARIABLES
MISORG, TO PATCH	;MISCELLANEOUS TABLES AND VARIABLES
PATCH, TO LEBUFS	;PATCH AREA
LEBUFS, TO RUGSA	;FREE STORAGE
.ENDC

.SBTTL HOW IT WORKS
.REPT 0
channel header pointer (location 40, read only)

	ADDRESS(channel header area)
	ADDRESS(pointer area)
	I/O version number
	source file version number
	0	always 0
	INITED	non-zero indicates PDP-11 is running ok(can be cleared by PDP-10)
	0	always 0
	GDOWN	used as flag by PDP-10 to acknowledge clear of INITED
channel header area (aligned on PDP-10 word)

    KBD channel:
	KBDFLG	cleared by 10/set by 11 (chain of activated KBD buffers)
	0	allows PDP-10 to do SKIPN for activation test
    DPY channel: (1 per console)
	DPYCHN	buffer assigned to channel, if zero then DPY channel is closed
	DPYKBD	.BYTE KBD#, DPY# (377 for either implies not assigned)
    KBD flags: (1 per console)
	ECOFLG	Set by PDP-10.  Next time DPYBUF is empty clear ECOFLG
		and put flag on KBD ring to signal this condition
	CHNCLS	if -1, log this guy out!!!!
		If non-negative, has keyboard number (377 if none).
    WHO flags: (1 per console)
	WHOLIN	who line variables for this console
	WHOUSR	-1=>user who line, 0=>system who line


format of KBD buffer (aligned on PDP-10 word)

	KBDSTS	negative=>-(data byte count), 0=>free
	0
	KBDRNG	next KBD buffer associated with this KBD
	KBDLST	next buffer on activated list (0=>end of chain)
	KBDCHN	keyboard channel
	0	not used
	KBDATA	key board data area (1 PDP-11 word/character)

format of DPY buffer (aligned on PDP-10 word)
  (actually, this is the beginning of the "line editor vars" or "channel vars" block).

	DPY10B	word PDP-10 is hacking (used only for initailization)
		This always points at DPYATA for this buffer these days.
	DPY11B	word PDP-11 is hacking
	0
	DPYLGL	last legal address in this buffer
	DPYSIZ	size of data area in bytes
	0	not used
	DPYATA	display data area (1 PDP-11 byte/character)

format of pointer area (aligned on PDP-10 word)

	ADDRESS(system who line variables)
	ADDRESS(PDP-10/PDP-11 communication area)
	TENWHO	-1=>PDP-10 should update who lines
	TENWH1	pads TENWHO
	SYMTAB BEGINNING OF TABLE OF SWITCHES WHICH 10 ACCESSES.

Notes:

1.	All addresses and pointers are in PDP-11 address space.

2.	KBD buffers are ringed two per channel.  While the PDP-10 is
	emptying one, the PDP-11 can fill the other.

3.	There is only one DPY buffer per channel.  When the buffer is filled
	with negative ones, it is free.  When the PDP-10 writes a character
	in the current word: then the PDP-11 processes the data in that
	word, sets that word to negative one, and advances to the next word.
	(Formerly any negative number would do, but now that the byte size is
	8 rather than 16, -1 [377] must be used since valid characters > 200 exist.)

WHO LINE VARIABLES

SYSTEM WHO LINE (ALIGNED ON PDP-10 WORD)
    ITSTDP	# total # dpy's (read only for PDP-10)
    ITSFDP	# free  dpys (read only for PDP-10)
    ITSVER	ITS version #
    ITSJOB	total jobs
    ITSCOR	total core
    ITSRU	runnable users
    ITSWBJ	# jobs swap blocked
    ITSJWP	# jobs waiting for pages
    ITSTRC	total runable core
    ITSCFU	core available for users
    ITSDAT	date [byte (7) year (4) month (5) day]
    ITSDBG	system debug flag
    ITSTIM	time of day (# half seconds since midnight) aligned on PDP-10 word
    ITSTI1	low order of time
    ITSUSR	total number of users
    ITSFSH	fair share

USER WHO LINE (ALIGNED ON PDP-10 WORD)
    WHJOB	job #, -1=>who line not in use
    WHJOB1	if negative then clear who line
    WHMODE	mode	0=>follow keyboard
			1=>freeze
			2=>next higher (when PDP-10 sees this state, it searches
			   user variables for next higher job index number with same
			   uname.  When it finds it, it stores the number in job #
			   and changes mode to 1
			3=>next lower
    WHMOD1	pads WHMODE
    WHUNAM	uname in sixbit (left 18 bits in first two words, right in next two)
    WHUNM1
    WHUNM2
    WHUNM3
    WHJNAM	jname in sixbit
    WHJNM1
    WHJNM2
    WHJNM3
    WHSNAM	sname in sixbit
    WHSNM1
    WHSNM2
    WHSNM3
    WHSTAT	status in sixbit, 0=>job does not exist
    WHSTA1
    WHSTA2
    WHSTA3
    WHJ%RT	job % run time
    WHJTRT	job total run time (in tenth's of seconds)
    WHRPAG	job real memory pages (swapped in)
    WHTPAG	job total pages

NOTE:	The PDP-11 will not update who lines until it sees that ITSTIM
	has changed.

PDP-10/PDP-11 COMMAND CHANNEL

    CMDFLG	aligned on PDP-10
		0=>buffer is free (PDP-10 can write CMDBUF)
		positive=>command # from PDP-10 (PDP-11 can write CMDBUF)
		negative=>affirmative reply from PDP-11 (0=>command failed)
		PDP-10 can read CMDBUF, then must zero CMDFLG
    CMDFL1	always 0
    CMDBUF	each arg takes 4 bytes (1 PDP-10 word)

    PDP-10/PDP-11 COMMANDS

	1	video switch
		arg1:	video switch input #  (set by PDP-10)
		arg2:	video switch output # ( "  "   "  " )

	2	reserve DPY
		arg1:	DPY reserved (set by PDP-11)

	3	free DPY
		arg1:	DPY to free (set by PDP-10)

	4	read video switch
		arg1:	< 0 for default setting, > 0 for current setting (set by PDP-10)
			1=>tty chnl, 2=>KBD, 3=>video switch output
		arg2:	# described by arg1 (set by PDP-10)
		arg3:	input (set by PDP-11)
		arg4:	input (set by PDP-11)
		arg5:	output(set by PDP-11)

	5	audio switch
		arg1:	audio switch input #  (set by PDP-10)
		arg2:	audio switch output # (set by PDP-10)

	6	read audio switch (for this to be useful, 11 must maintain table, since 
				the audio switch is read-only.
		arg1:	< 0 for default setting, > 0 for current setting (set by PDP-10)
			1=>tty chnl, 2=>KBD, 3=>audio switch output
		arg2:	# described by arg1 (set by PDP-10)
		arg3:	input (set by PDP-11)
		arg4:	output(set by PDP-11)

;other 10-11 commuincation issues ..

;go down resetting video switch vs not
;PDP-11 indicates it has reset video switch
	;(PDP-10 then detaches all jobs with tv ttys)

;console scroll register	6/23/74

CSA==157776		;selects where video scan starts in video buffer

__|_____|_____|_____|_____|_____|
15    1211			|
|  3  |1|           12		|
|_____|_|_______________________|
   |   |	     |
   |   |	     |----------------->scroll offset (start video scan at n*4 PDP-11 words from TVLO)
   |   |
   |   |------------------------------->black on white bit (1=>black on white)
   |
   |----------------------------------->not used



;console register		6/24/74

CREG==164044		;selects video buffer memory

__|_____|_____|_____|_____|_____|
15              7		|
|	8	|	8	|
|_______________|_______________|
	|		|
	|		|-------------->console # (TVLO-TVHI on unibus is video bit map)
	|
	|------------------------------>ALU function

video switch	4/17/74

VSW==164060		;sets video switch

__|_____|_____|_____|_____|_____|
15    12  10    7       3       |
|  3  | 2 |  3  |   4   |   4   |
|_____|___|_____|_______|_______|
   |    |    |      |       |
   |    |    |      |       |---------->video source
   |    |    |      |
   |    |    |      |------------------>not used
   |    |    |
   |    |    |------------------------->|	      |card section
   |    |				|switch output|
   |    |------------------------------>|	      |card select
   |
   |----------------------------------->switch section number


audio switch   7/12/76

ASW==170670	;SETS AUDIO SWITCH. (this is a write-only memory.)

__|_____|_____|_____|_____|_____|
15  13    10    7       3       |
| 2 |  3  |  3  |   4   |   4   |
|___|_____|_____|_______|_______|
  |    |     |      |       |
  |    |     |      |       |---------->audio source
  |    |     |      |
  |    |     |      |------------------>not used
  |    |     |
  |    |     |------------------------->|	      |card section (complemented)
  |    |				|switch output|
  |    |------------------------------->|	      |card select
  |
  |------------------------------------>not used

ASWXOR==1617	;complemented fields of ASW.

keyboard multiplexor	3/15/74

KBDPC==340	;interrupt vector
KBDLVL==5_7	;interrupts on level 5

KMS==164050	;keyboard status

__|_____|_____|_____|_____|_____|
151413121110 9 8 7 6 5 4    1   |
|1|1|1|1|1|1|1|1|1|1|1|  3  | 2 |
|_|_|_|_|_|_|_|_|_|_|_|_____|___|
 | | | | | | | | | | |   |    |
 | | | | | | | | | | |   |    |------>KMA extension (bits 17 and 16)
 | | | | | | | | | | |   |
 | | | | | | | | | | |   |----------->not used
 | | | | | | | | | | |
 | | | | | | | | | | |--------------->interrupt enable
 | | | | | | | | | |
 | | | | | | | | | |----------------->direct memory access enable
 | | | | | | | | |
 | | | | | | | | |------------------->waiting to hack memory
 | | | | | | | |
 | | | | | | | |--------------------->8th floor elevator
 | | | | | | |----------------------->9th floor elevator
 | | | | | |
 | | | | | |------------------------>extra OC output, pin BBF1.
 | | | | |
 | | | | |--------------------------->buzz the 9th floor door (dip relay)
 | | | |
 | | | |----------------------------->generate copy from second source(currently not
 | | |									enabled)
 | | |------------------------------->generate copy from first source
 | |
 | |--------------------------------->ready line
 |
 |----------------------------------->waiting to interrupt

KMA==165052	;keyboard memory address register

__|_____|_____|_____|_____|_____|
15		  7	    1   |
|         9       |    5    | 2 |
|_________________|_________|___|
          |            |      |
          |            |      |----->always 0
	  |	       |
	  |	       |------------>binary counter (overflow lost)
	  |
	  |------------------------->buffer origin

;keyboard multiplexor	3/15/74
;format of data written into memory (each record is two words)

;first word

__|_____|_____|_____|_____|_____|
151413  11  9   7   5           |
|1|1| 2 | 2 | 2 | 2 |     6     |
|_|_|___|___|___|___|___________|
 | |  |   |   |   |	  |
 | |  |   |   |   |       |--------->key struck
 | |  |   |   |   |
 | |  |   |   |   |----------------->shift (7-left, 6-right)
 | |  |   |   |
 | |  |   |   |--------------------->top (9-left, 8-right)
 | |  |   |
 | |  |   |------------------------->control (11-left, 10-right)
 | |  |
 | |  |----------------------------->meta (13-left, 12-right)
 | |
 | |-------------------------------->shift lock
 |
 |---------------------------------->always 1

;second word

__|_____|_____|_____|_____|_____|
15  13          7               |
| 2 |     6     |       8       |
|___|___________|_______________|
  |	  |		|
  |	  |		|----------->high order bits of character (ignored)
  |	  |
  |	  |------------------------->console number
  |
  |--------------------------------->always 0

.ENDR

;CHARACTER FORMAT WRITTEN BY KBD MULTIPLEXOR

RCHAR==177700	;6 BITS FOR KEY STRUCK
RSHBIT==300	;SHIFT BITS
RTPBIT==1400	;TOP BITS
RCLBIT==6000	;CONTROL BITS
RMTBIT==30000	;META BITS
RSLBIT==40000	;SHIFT LOCK
RXTRA==100000	;UNUSED BITS

;XTAB BITS USED FOR XTAB LOOK UP

XTPBIT==400	;TOP
XSLBIT==200	;SHIFT LOCK
XSHBIT==100	;SHIFT

;POSITION OF META BITS, ASCII COMPATIBLE

ACTBIT==SNB		;CAUSES CHARACTER TO ACT AS ACTIVATOR
ACLBIT==200		;CONTROL
AMTBIT==400		;META
ASHBIT==XSHBIT_3	;SHIFT
ASLBIT==XSLBIT_3	;SHIFT LOCK
ATPBIT==XTPBIT_3	;TOP
ACMBIT==AMTBIT+ACLBIT	;CONTROL AND META TOGETHER

.SBTTL ASSIGNMENTS

;GEOMETRY

BITPL==1100		;BITS PER LINE
NLINS==706		;LINES ON SCREEN
BYTPL==BITPL/10		;BYTES PER LINE
WRDPL==BYTPL/2		;WORDS PER LINE

CHRWD==6		;CHARACTER WIDTH ON TEXT LINE
GRIDWD==5		;WIDTH OF CHARACTER GRID
CHRHT==12		;CHARACTER HEIGHT
CHRVSP==2		;BLANK RASTER LINES BETWEEN CHARACTER LINES
LINHT==CHRHT+CHRVSP	;CHRACTER LINE HEIGHT
CHRPL==BITPL/CHRWD	;CHARACTERS PER LINE
CHRLN==NLINS/LINHT	;CHARACTER LINES ON SCREEN

;MEMORY MAP

NXMPC==   4		;BUS ERROR VECTOR
NXMPSW==  6
RESPC==  10		;RESERVED INTRUCTION VECTOR
RESPSW== 12
BPTPC==  14		;BREAK POINT VECTOR
BPTPSW== 16
IOTPC==  20		;IOT VECTOR
IOTPSW== 22
PWRPC==  24		;POWER FAIL TRAP VECTOR
PWRPSW== 26
EMTPC==  30		;EMULATE TRAP VECTOR
EMTPSW== 32
TRPPC==  34		;TRAP INSTRUCTION VECTOR
TRPPSW== 36
TYIPC==  60		;TTY INPUT INTERRUPT VECTOR
TYIPSW== 62
LKPC==  100		;LINE CLOCK INTERRUPT VECTOR
LKPSW== 102
KLIPC== 320		;KL11 INPUT INTERRUPT VECTOR
KLIPSW==322
KBDPC== 340		;KEYBOARD MULTIPLEXOR INTERRUPT VECTOR
KBDPSW==342

PDLORG==400			;ORIGIN OF PUSH DOWN LIST
TVLO=60000			;ORIGIN OF DISPLAY MEMORY
TVFENCE=TVLO+<CHRLN*LINHT*BYTPL> ;ADDR OF FIRST TEXT LINE THAT SHOULDN'T BE USED
				;(IT'S INCOMPLETE AND CONTAINS THE WHO-LINE).
TVCFENC=TVHI-<BYTPL*<CHRHT-1>>	;DON'T TRY TO DISPLAY A CHARACTER AFTER THIS POINT
TVHI=TVLO+<BYTPL*NLINS>-2	;HIGHEST LEGAL DISPLAY ADDRESS
CSA=157776			;DISPLAY REFRESH STARTING ADDRESS (STARTS AT 0)

CREG==  164044		;UNIBUS CONSOLE REGISTER ADDRESS
CALU==  164045		;CONSOLE REGISTER LOGICAL FUNCTION ADDR
KMS==   164050		;KEYBOARD MULTIPLEXOR STATUS
KMA==   164052		;KEYBOARD MULTIPLEXOR MEMORY ADDRESS
VSW==   164060		;VIDEO SWITCH
ASW==   170670		;AUDIO SWITCH
KLIS==  174000		;KL11 INPUT STATUS
KLIB==  174002		;KL11 INPUT BUFFER
KLOS==  174004		;KL11 OUTPUT STATUS
KLOB==  174006		;KL11 OUTPUT BUFFER

.EXPUNGE DIV,MUL,ASH	;THESE ARE PREDEFINED AS 11/45 INSTRUCTIONS.
DIV==   177300		;EAE GOODIES
AC==    177302
MQ==    177304
MUL==   177306
SC==    177310
SR==    177311
NOR==   177312
LSH==   177314
ASH==   177316
LKS==   177546		;LINE CLOCK STATUS
TKS==   177560		;TTY KEYBOARD STATUS
TKB==   177562		;TTY KEYBOARD BUFFER
TPS==   177564		;TTY PRINTER STATUS
TPB==   177566		;TTY PRINTER BUFFER
CSR==   177570		;CONSOLE SWITCH REGISTER
PS==    177776		;PROCESSOR STATUS REGISTER
...==0
....==0

;TEN/11 COMMUNICATIONS AREA

CHAP==40		;CHANNEL HEADER AREA POINTER
POINTP==42		;POINTER TO POINTER AREA
CIOVER==44		;HOLDS I/O VERSION FOR PDP-10 TO LOOK AT
CVERSE==46		;ASSEMBLY VERSION FOR PDP-10
	;50		;ALWAYS 0
INITED==52		;INITED FLAG, SET BY 11 CLEARED BY 10
	;54		;ALWAYS 0
GDOWN==56		;INTERLOCKS WITH INITED, CLEARED BY 11 SET BY 10

;CONSOLE REGISTER FUNCTIONS

CSETC==0
CNOR==1
CANDC==2
CSETZ==3
CNAND==4
CCOMP==5
CXOR==6
CANCSD==7
CEQV==11
CORCSD==10
CSAME==12
CAND==13
CORSCD==13
CSETO==14
CIOR==16
CSET==17

;INTERRUPT LEVELS

KBDLVL==5_5	;KEYBOARD MULTIPLEXOR INT. PRIORITY (BUT HANDLER RUNS AT LKLVL).
LKLVL==6_5	;LINE CLOCK
ERRLVL==7_5	;PROCESSOR ERRORS

;MISCELLANEOUS ASSIGNMENTS

IOVER==3	;I/O VERSION FOR ITS
PDL==400	;PUSH DOWN LIST SIZE
MAXKBD==64.	;MAXIMUM # OF KEYBOARDS
MAXTV==16.	;MAX NUMBER OF TV DISPLAYS
MAXBLK==MAXTV	;MAXIMUM # OF BLINKERS
MAXASI==20	;AUDIO SWITCH INPUTS
MAXASO==100	;AUDIO SWITCH OUTPUTS
ASWXOR==3400	;XOR THIS INTO EACH CONTROL WORD TO BE SENT TO THE ASW.
MAXVSI==20	;VIDEO SWITCH INPUTS
MAXVSO==40	;VIDEO SWITCH OUTPUTS
VSWSEC==2	;# VIDEO SWITCH SECTIONS
VSWINC==MAXVSO_10	;INCREMENTS VIDEO SWITCH SECTION NUMBER
QPYVSW==27	;VIDEO SWITCH OUTPUT FOR TEKTRONIX VIDEO HARD COPY UNIT
QPTIME==21.*60.	;21. SECONDS BETWEEN COPIES
QPYKMS==20000	;GENERATE COPY FROM FIRST SOURCE (IN KEYBOARD STATUS, NATURALLY)
QPYKM2==10000	;GENERATE COPY FROM SECOND SOURCE.
BUZKMS==4000	;BUZZ DOOR (ALSO IN KEYBOARD STATUS)
BUZTIM==3*60.	;LEAVE THE DOOR BUZZING FOR 3 SECONDS
ELKMS8==1	;8TH FLOOR ELEVATOR BIT, SWAPPED (IT LIVES IN BYTE 1 OR WORD)
ELKMS9==2	;9TH FLOOR ELEVATOR BIT, SWAPPED.
ELEKMS==1400	;ALL ELEVATOR BITS
ELETIM==20	;PUSH THE BUTTON FOR 1/3 OF A SEC
KBDTIM==10.	;TIME UNTIL KEYBOARD GETS RESET (IN SEMI-SLOW CLOCK TICKS)
MAXBEL==4	;MAXIMUM # OF BELLS ALLOWED
GLITIM==60.*60.*2	;# CLOCK TICKS BETWEEN GLITCHES ON CONSOLE FREE DPY
NCQSLT==100	;# CLOCK QUEUE SLOTS
KBDBFL==200	;SIZE OF KEYBOARD BUFFER
LBLEN==100	;PDP-10 INPUT BUFFER SIZE (BETTER BE DIVISIBLE BY 4)
LBCHRS==LBLEN/2	;# CHARACTERS IN INPUT BUFFER
DPSIZE==600	;PDP-10 OUTPUT BUFFER SIZE
BOWBIT==10000	;CSA BLACK ON WHITE BIT
SAMSK==BOWBIT-1	;MASK FOR SCROLL REGISTER
CSAMSK==170000	;COMPLEMENT OF SAMSK
BLKTIM==15.	;CLOCK TICKS BETWEEN BLINKS
SNB==100000	;SIGN BIT
PATL==400	;SIZE OF PATCH AREA
CMDARG==10	;# ARGUMENTS WHICH WILL FIT INTO PDP-10/PDP-11 COMMAND BUFFER
RUGSA==57100	;STARTING ADDRESS OF RUG
TYMSLC==2	;MAX # 60THS OF A SECOND, MINUS 1, TO CONCENTRATE ON ONE TV

.SBTTL GO CODE, PDL, AND KBD BUFFER

.ABS

;PUSH DOWN LIST AND KEYBOARD BUFFER

.=PDLORG+PDL
.IIF NE .&177,.=<.&177600>+200	;ALIGN ON 200 BYTE BOUNDARY
PDBUF==.

KBDBUF:
.=.+KBDBFL
KBDEND==.

REPORT GO=,\GO

GO:	RESET			;IN THE PRIVACY OF YOUR OWN HOME
	CLR	PS
	MOV	#PDBUF,SP	;SET UP PUSH DOWN POINTER
	MOV	#ERRLVL,C	;ALL PROCESSOR TRAPS GO ON 7
	MOV	#NXMPC,B
	MOV	#NXMBRK,(B)+	;BUS TIME OUT
	MOV	C,(B)+
	MOV	#RESBRK,(B)+	;RESERVED INSTRUCTION
	MOV	C,(B)+
	MOV	(B),T		;BREAK POINT
	BNE	.+6
	MOV	#BPTBRK,T
	MOV	T,(B)+
	MOV	C,(B)+
	MOV	#IOTBRK,(B)+	;IOT TRAP
	MOV	C,(B)+
	MOV	#PWRBRK,(B)+	;POWER FAILURE
	MOV	C,(B)+
	MOV	#EMTBRK,(B)+	;EMT
	MOV	C,(B)+
	MOV	#TRPBRK,(B)+	;"TRAP" TRAP (LEV 7)
	MOV	C,(B)+
	MOV	#CHA,(B)+	;CHANNEL HEADER AREA
	MOV	#POINTA,(B)+	;POINTER AREA POINTER
	MOV	#IOVER,(B)+	;I/O VERSION
	MOV	VERSE,(B)+	;ASSEMBLY VERSION
	CLR	(B)+		;INITED
	CLR	(B)+
	MOV	C,(B)+		;NON-ZERO SUFFICES
	MOV	C,(B)+		;GDOWN
	MOV	#CLKBRK,LKPC	;CLOCK
	MOV	#LKLVL,LKPSW
	MOV	#KBDBRK,KBDPC	;KBD
	MOV	#LKLVL,KBDPSW
	MOV	#BPT,0		;CATCH JUMPS TO ZERO.

;FALLS THROUGH

;INITIALIZE VARIBLES	FALLS THROUGH

	JSR	PC,INIT

;ENABLE INTERRUPTS

	MOV	#100,LKS	;CLOCK
	MOV	#KBDBUF,KMA
	MOV	#KBDBUF,OLDKMA
	MOV	#140,KMS	;KEYBOARD MULTIPLEXOR
	MOV	#-1,INITED

;THE MAIN LOOP

MAIN:	MOV	#MAXTV-1,U		;CHANNEL
	CMP	WHOTIM,ITSTI1		;TIME FOR WHO LINES?
	BEQ	MAIN1
	ZAPFLG	WHOFLG			;TRIGGER WHO LINES
MAIN1:	TST	INITED
	BEQ	GO			;RESET THE WORLD
	TST	CSR
	BLT	GO2RUG			;SWITCH 15 => GO TO RUG
MAIN3:	JSR	PC,DPYDPY
	MOV	CMDFLG,A		;PDP-10 GIVING COMMAND?
	BLE	MAIN2
	PUSH	U
	JSR	PC,TENCMD		;PROCESS THE COMMAND
	POP	U
MAIN2:	DEC	U
	BGE	MAIN1			;CYCLED THROUGH ALL CHANNELS?
	CLR	WHOFLG			;TURN OFF WHO LINES
	BR	MAIN

GO2RUG:	BPT
	BR	MAIN3

;HERE TO RESTART, NOTIFY THE PDP-10

GODOWN:	RESET
	CLR	PS
	MOV	#INITED-2,B
	CLR	(B)+
	CLR	(B)+		;INITED
	CLR	(B)+
	CLR	(B)+		;GDOWN
	TST	GDOWN		;WAIT FOR THE PDP-10 TO REPLY
	BEQ	.-4
	JMP	GO

.SBTTL INITIALIZATION

INIT:	CLR	TICKS
	CLR	TICKS1
;******* TEMPORARY CODE FOR FONT CHECKSUM *******
	MOV #FNTORG,T
	MOV T,CKSPNT
	CLR CKSSUM
	CLR TT
1$:	ADD (T)+,TT
	CMP T,#FNTEND
	BLO 1$
	MOV TT,CKSSMG
;******* END OF TEMPORARY CODE *******
	CLR	KBDFLG
	CLR	KBDFLG+2
	CLR	KBDACT
	CLR	KBDLAST
	CLR	KBDTSW
	CLR	CMDFLG
	CLR	CMDFLG+2
	CLR	WHOTIM
	CLR	ITSTI1
	CLR	WHOFLG
	CLR	TENWHO
	CLR	QPYSWT
	CLR	BUZSWT
	CLR	ELESWT
	CLR	SSCC
	JSR	PC,REASW		;FEED EVERY SPEAKER SILENCE.

	MOV	#LEBUFS,U		;INITIALIZE FREE LIST OF 11-TO-10 INPUT BUFFERS.
	MOV	U,FSP
	MOV	#NLBUFS-1,B
INIT6:	MOV	U,TT
	ADD	#<LHLEN+LBLEN>,TT
	MOV	TT,LHFS(U)
	MOV	TT,U
	DEC	B
	BGT	INIT6
	CLR	LHFS(U)			;END OF LIST

	CLR	BLINK
	MOV	#BLINKS,A
	MOV	#BELCNT,C
	MOV	#-1,T			;SET UP BELL COUNTS
	MOV	#MAXTV-1,B
	CLR	ITSTDP
INIT5:	CLRB	CHNUSE(B)		;EVERY CHANNEL IS FREE.
	CLRB	BLKSWT(B)		;NO TV HAS BLINKING TEMPORARILY INHIBITED.
	TSTB	CHCREG(B)		;HOW MANY CHANNELS ARE WORKING?
	BLT	INIT5A
	INC	ITSTDP
INIT5A:	CLR	(A)+
	MOV	T,(C)+
	DEC	B
	BGE	INIT5
	MOV	ITSTDP,ITSFDP		;# FREE DPY'S

	MOV	#MAXBLK,B		;PUT ALL BLINKER BLOCKS ON THE FREE BLINKERS LIST.
	MOV	#BLKVAR,U
	MOV	U,FBLINK
INIT7:	MOV	U,TT
	ADD	#BLLEN,TT
	MOV	TT,BLNEXT(U)
	CLRB	BLON(U)
	MOV	TT,U
	DEC	B
	BGT	INIT7
	CLR	<BLNEXT-BLLEN>(U)

	MOV	#MAXTV-1,A
	CLR	T
	MOV	#WHVARS,C
INIT2:	MOV	DPYCHN(T),U
	JSR	PC,CHCLR		;SET UP THAT CHANNEL
	MOV	#-1,DPYKBD(T)
	MOV	#-1,CHNCLS(T)
	CLR	ECOFLG(T)
	MOV	C,WHOLIN(T)
	MOV	#-1,(C) .SEE WHJOB
	ADD	#WHLEN,C
	CMP	(T)+,(T)+
	DEC	A
	BGE	INIT2			;MORE DPY CHANNELS TO SET UP?

	MOV	#-1,C
	JSR	PC,CHCONS	;GET A CHANNEL FOR THE FREE SCREENS.
	TST	T
	BEQ	.+4		;THIS SHOULD ALWAYS GIVE US CHANNEL 0.
	 BPT
	MOV	WHOLIN,TT		;WANT SYSTEM WHO LINE ON CONSOLE FREE DPY
	MOV	#NWHCMD,WHMODE(TT)
	MOVB	CHCREG,TT		;TT GETS WHICH VIDEO BUFFER IT IS.
	MOV	TT,DPYFRE		;REMEMBER # OF DPY USED FOR FREE SCREENS.
	MOVB	TT,CREG			;SET UP CONSOLE REGISTER FOR PRINT
	CLR	CSA
	TYPOUT	</TV's ready, but not in operation
/>
	MOVB	LECREG(U),C		;DPY
	ASL	C
	MOV	#MAXVSO-1,B		;SWITCH TO ALL OUTPUTS
INIT1:	MOV	DPYVSW(C),TT		;VIDEO SWITCH INPUT
	MOV	B,T			;SWITCH OUTPUT
	JSR	PC,VSWIT
	DEC	B
	BGE	INIT1

	MOV	#MAXKBD,A		;CLEAR KBDLE
	CLR	B
INIT8:	CLR	KBDLE(B)
	CLR	KBDESC(B)
	MOV	#-1,KBDDEF(B)
	TST	(B)+
	DEC	A
	BGT	INIT8

	MOV	#NCQSLT-1,C		;INITIALIZE CLOCK QUEUE
	CLR	CLOCKQ
	MOV	#CQUEUE,A
	MOV	A,CLOCKF
INIT9:	MOV	A,B
	ADD	#CQLEN,B
	MOV	B,(A)
	MOV	B,A
	DEC	C
	BGT	INIT9
	CLR	(A)
	MOVB	#CSET,CALU
	MOV	CREG,T			;SEED QUEUE WITH GLITCH CONSOLE FREE
	JSR	TT,ADQUE
		GLITIM
		MSGLIT
	RTS	PC

.SBTTL MAIN PROGRAM LEVEL ROUTINES

;HERE TO GET CHARACTER FROM OPEN CHANNEL
;LOOPS UNTIL NO MORE CHARACTERS AVAILABLE

DPYDPY:	TSTB	CHNUSE(U)
	BLE	DPYD5			;IGNORE FREE DISPLAYS.
	PUSH	U			;DPY CHANNEL NUMBER
	ASL	U
	ASL	U
	PUSH	U
	MOV	DPYCHN(U),U		;U GETS CHANNEL VAR BLOCK ADDR
	JSR	PC,GETCHR		;ANY OUTPUT FOR THIS CHANNEL?
	BEQ	DPYDON			;NO, GO CHECK FOR WHO LINES, ETC.
	MOV	#TYMSLC,TYMSHR		;MAX TIME BEFORE CHECKING OTHER CHANNELS
	MOVB	LECREG(U),T		;SET UP CONSOLE REGISTER
	MOVB	T,CREG
	PUSH	T
	BLKOFF	T			;TURN OFF ALL BLINKERS ON THIS SCREEN
	JSR	PC,CLBLIN		;AND CLEAR THEM
	PUSH	U			;SAVE PAGE PRINTER FOR DPYTVO+5
	MOVB	#CIOR,CALU		;ALU FUNCTION FOR DRAWING CHARACTERS
	MOV	LECPC(U),TT		;RESUMING COROUTINE?
	BEQ	DPYDP1			;NO.
	MOV	LESVB(U),B		;YES, RESTORE B AND PC FOR CORETURN FROM THE
	CLR	LECPC(U)		;GETCHC THAT DIDN'T FIND ANY CHARS.
	BIC	#-400,A			;CLEAR EXTRA BITS DUE TO SIGN-EXTENSION
	PUSH	#DPYXIT			;GETCHC'S CALLER'S RETURN ADDR MUST BE DPYXIT.
	JMP	(TT)			;GETCHC ENFORCES THAT.

;FAST CHARACTER OUTPUT LOOP
DPYDP1:	MOV	(SP),U			;GET PP POINTER
	MOVB	A,A			;FLUSH HIGH BITS FROM CHAR
	BLT	DPYCTL			;BRANCH IF NON-PRINTING CONTROL FUNCTION
DPYTVO:	MOV	LEPHS(U),C		;SET UP TO DRAW CHARACTER
	MOV	LECC(U),TT		;THIS IS OPEN-CODED FOR SPEED
	ASL	A			;COPIED FROM CODE AT GENCHR
	MOV	CTAB(A),T
	JSR	PC,GENCH1		;GENERATE CHARACTER, CLOBBER ALL ACS
	MOV	(SP),U			;RESTORE PP POINTER, CLOBBERED BY GENCH1
	JSR	PC,LEDADC		;ADVANCE CURSOR
DPYXIT:	TST	TYMSHR			;TIME UP?
	BMI	DPYDX2			;YES, LEAVE THIS TV FOR A WHILE
	MOV	(SP),U
	JSR	PC,GETCHR		;NO, GET NEXT CHARACTER
	BNE	DPYDP1			;AND LOOP BACK TO PROCESS IT
DPYDX2:	POP	U
	POP	T			;DONE WITH THIS DPY FOR NOW
	BLKON	T			;ALLOW BLINKERS TO BLINK AGAIN
	BR	DPYDON

;HERE IF NO CHARACTER AVAILABLE.  TWO WORDS STILL ON THE STACK:
;(SP) IS 4 TIMES CHANNEL NUMBER, 2(SP) IS CHANNEL NUMBER (TO BE POPPED INTO U).

DPYDON:	POP	B
	TST	CHNCLS(B)
	BLT	DPYFLS			;FLUSH DPY CHANNEL?
	TST	ECOFLG(B)
	BEQ	DPYD2			;CAUSE PSEUDO ACTIVATION?
	MOV	U,T
	ADD	#LEZER0,T

	CHROFF
	MOV	KBDACT,LELIST(TT)	;PUT LINE EDITOR ON ACTIVE RING
	MOV	T,KBDACT
	TST	KBDFLG
	BNE	DPYD0
	MOV	T,KBDFLG
	CLR	KBDACT
	CLR	KBDLAST
DPYD0:	CHRON

DPYD1:	CLR	ECOFLG(B)
DPYD2:	TST	WHOFLG			;DO WHO LINES?
	BEQ	DPYD3
	MOV	WHOLIN(B),T
	TST	WHMODE(T)
	BMI	DPYD4			;DON'T DO WHO LINE, BUT MIGHT WANT TO CLEAR IT
	TST	WHO1(T)
	BMI	DPYD4			;USER WHO MODE VAR CAN ALSO DISABLE WHO LINE
	JSR	PC,DOWHO		;DO THE WHO LINE FOR THIS GUY
DPYD3:	POP	U
DPYD5:	RTS	PC

;HERE IF NO WHO LINE IS TO BE DONE, WE MIGHT WANT TO CLEAR IT

DPYD4:	MOV	WHOLIN(B),T
	TST	2(T)			;IF NEGATIVE, THEN CLEAR IT
	BGE	DPYD3
	CLR	2(T)			;ZAP THE SWITCH
	JSR	PC,ZAPWHL		;CLEAR THE LINE
	BR	DPYD3

;HERE TO FLUSH DPY CHANNEL

DPYFLS:	MOV	(SP),T
	TSTB	CHNUSE(T)	;ALREADY FREED?
	BEQ	DPYD3		;YES, THIS MEANS MAIN LOOP SHOULD SIMPLY IGNORE THIS DPY.
	CHROFF
	JSR	PC,CHRETN
	CHRON
	BR	DPYD3

;HERE IF CONTROL CODE FOUND

DPYCRF:	SUB	#5,A
DPYCTL:	BIC	#177600,A	;DISPATCH ON CONTROL CODE
	CMP	#ILLCTL,A
	BLOS	DPYTVO		;BRANCH IF ILLEGAL CODE
	ASL	A
	PUSH	#DPYXIT		;MAKE THE RETURN ADDR BE "DPYXIT"
	JMP	@CTLTAB(A)	;SO GETCHC COROUTINING WILL WORK.

;CONTROL FUNCTION ROUTINES CALLED WITH PP INDEX IN U.
;MAY CLOBBER ALL ACS BUT MUST LEAVE CIOR IN CALU.  MANY ARE ALSO
;CALLED FROM ELSEWHERE AND EXPECTED TO PRESERVE U.

CTLTAB:	SETCUR		;200	%TDMOV (FOLLOWED BY TWO IGNORED CHARS, THEN VPOS, HPOS).
	SETCR1		;201	%TDMV1 (FOLLOWED BY NEW VPOS AND NEW HPOS)
	CLEOF		;202	%TDEOF (CLEAR TO END OF SCREEN)
	CLEOL		;203	%TDEOL (CLEAR TO END OF LINE)
	CLRCHR		;204	%TDDLF (DELETE FORWARD)
	RTSPC		;205	%TDMTF (MOTOR OFF - IGNORED)
	RTSPC		;206	%TDMTN (MOTOR ON - IGNORED)
	CRLF		;207	%TDCRL (CRLF AND CLEAR EOL, BUT SCROLL AT END OF SCREEN)
	RTSPC		;210	%TDNOP (NO-OP)
	DPYBS		;211	%TDBS (BACKSPACE)
	LF		;212	%TDLF (LF)
	CR		;213	%TDRCR (RAW CR)
	RTSPC		;214	%TDORS (OUTPUT RESET - WE CAN'T DO ANYTHING USEFUL)
	RTSPC		;215	%TDQOT (DEVICE DEPENDENT DATA FOLLOWS - WELL, THIS DEVICE
					;SAYS IT DOESN'T REALLY DEPEND)
	LEDADC		;216	%TDFS
	SETCR1		;217	%TDMV0 (SAME AS %TDMV1 FOR OUR PURPOSES)
	DPYCLR		;220	%TDCLR (HOME UP AND CLEAR SCREEN)
	BELL		;221	%TDBEL (FLASH THE SCREEN)
	RTSPC		;222	%TDINI (REINITIALIZE INTELLIGENT TERMINAL (NOT APPLICABLE))
	LINS		;223	%TDILP (INSERT LINE POSITION (FOLLOW BY # LINES TO INSERT))
	LDEL		;224	%TDDLP (DELETE LINE POSITION (FOLLOW BY # LINES TO DELETE))
	CINS		;225	%TDICP (INSERT CHARACTER POSITION (FOLLOW BY # CHARS))
	CDEL		;226	%TDDCP (DELETE CHARACTER POSITION (FOLLOW BY # CHARS))
	RTSPC		;227	%TDBOW (IGNORED)
	RTSPC		;230	%TDRST (IGNORED)
	RTSPC		;231	%TDGPH (IGNORED)
	RGSCUP		;232	%TDRSU (REGION SCROLL UPWARDS)
	RGSCDN		;233	%TDRSD (REGION SCROLL DOWN)
ILLCTL==<.-CTLTAB>/2

.SBTTL WHO LINE ROUTINES

;PRINTS WHO LINE, TAKES 10/11 CHANNEL IN B

DOWHO:	PUSH	B		;SAVE 10/11 CHANNEL
	MOV	ITSTI1,WHOTIM	;TIME WE DID WHO LINE
	MOV	#WHOPP,TT	;SET DEFAULTS FOR WHO PAGE PRINTER
	MOV	#LEDFLT,T
	MOV	#LELEN,U
	JSR	PC,CALCPY	;ZAP
	MOV	#WHOPP,U	;SET UP PAGE PRINTER INDEX
	CLR	A		;CHARACTER X
	MOV	#CHRLN,B	;CHARACTER Y, PAST LAST LINE
	JSR	PC,SETXY0
	MOV	(SP),B		;RESTORE 10/11 CHANNEL INDEX
	MOV	WHOLIN(B),A
	TST	WHO1(A)		;SIGN OF .WHO1 VARIABLE INHIBITS ALL HACKERY
	BPL	.+4		;ASSUME USER HAS STUFF THERE AND SHOULDN'T CLOBBER IT.
	 RTS	PC
	JSR	PC,ZAPWHL	;CLEAR OUT THE WHO LINE
WHINIT:	MOV	(SP),B		;10/11 CHANNEL INDEX
	MOV	WHOLIN(B),TT
	CMP	#NWHCMD-1,WHMODE(TT)
	BHI	DATIME		;NO VERSION NUMBER FOR USER WHO LINE
	TYPOUT	/ITS /
	DECTYP	ITSVER		;TYPE VERSION NUMBER
	JSR	PC,SPACE
	TST	ITSDBG
	BEQ	DATIME
	TYPOUT	/BEING DEBUGGED /

;TYPES DAY TIME AND DATE

DATIME:	MOV	ITSDAT,A	;PRINT PACKED DATE FIRST
	JSR	PC,DATTYP	; 7 BITS YEAR, 4 MONTH, 5 DAY
	JSR	PC,SPACE
	MOV	#MQ,B
	MOV	ITSTI1,(B)
	MOV	ITSTIM,-(B)
	JSR	PC,TIMTY1	;TYPE DAY TIME NEXT
	JSR	PC,SPACE
	POP	B		;10/11 CHANNEL
	MOV	WHOLIN(B),TT
	CMP	#NWHCMD-1,WHMODE(TT)
	BHI	UWHLDO		;DO USER WHO LINE?

;SYSTEM WHO LINE
;ITS XXX {BEING DEBUGGED} MM/DD/YY HH:MM:SS ITSFDP/ITSTDP USR RU/JOB SHARE SWBJ JWP TRC/COR CFU

SWLDO:	TYPOUT	/TVS: /
	DECTYP	ITSFDP		;# FREE DPYS
	JSR	PC,SLASH
	DECTYP	ITSTDP		;TOTAL DPYS
	TYPOUT	/ USERS: /
	DECTYP	ITSUSR		;# SYSTEM USERS
	JSR	PC,SPACE
	DECTYP	ITSRU		;RUNABLE JOBS/
	JSR	PC,SLASH
	DECTYP	ITSJOB		;# SYSTEM JOBS
	JSR	PC,SPACE
	DECTYP	ITSFSH		;FAIR SHARE IN %
	TYPOUT	/% SB=/
	DECTYP	ITSWBJ		;SWAP BLOCKED JOBS
	TYPOUT	/ PG=/
	DECTYP	ITSJWP		;JOBS WAITING FOR PAGES
	TYPOUT	/ CORE: /
	DECTYP	ITSTRC		;RUNABLE CORE
	JSR	PC,SLASH
	DECTYP	ITSCOR		;TOTAL CORE
	JSR	PC,SPACE
	DECTYP	ITSCFU		;CORE FOR USERS
	RTS	PC

;USER WHO LINE
;MM/DD/YY HH:MM:SS JOB UNAME JNAME SNAME STATUS J%RT HH:MM:SS.S JCORE {USER VARS}

WHNOJB:	TYPOUT / JOB SLOT VACANT/		;HERE IF JOB SLOT VACANT
	RTS	PC

UWHLDO:	OCTYPE	WHJOB(TT)	;JOB #
	TST	WHSTAT(TT)
	BEQ	WHNOJB		;VACANT JOB SLOT?
	JSR	PC,SPACE
	MOV	#WHUNAM,T
	ADD	TT,T
	JSR	PC,SIXPNT	;UNAME
	JSR	PC,SPACE
	JSR	PC,SIXPNT	;JNAME
	JSR	PC,SPACE
	JSR	PC,SIXPNT	;SNAME
	JSR	PC,SPACE
	JSR	PC,SIXPNT	;STATUS
	JSR	PC,SPACE
	DECTYP	WHJ%RT(TT)	;JOB % RUN TIME
	JSR	PC,SLASH
	DECTYP	ITSFSH		;OUT OF FAIR SHARE
	JSR	PC,PERCNT
	JSR	PC,SPACE
	MOV	WHJTRT(TT),A	;JOB RUNTIME IN .1-SEC TICKS
	JSR	PC,TIMTEN
	JSR	PC,SPACE
	DECTYP	WHRPAG(TT)	;# PAGES REAL CORE
	JSR	PC,SLASH
	DECTYP	WHTPAG(TT)	;# PAGES OF VIRTUAL CORE
	MOV	#'K,A
	JSR	PC,TVO
	JSR	PC,SPACE
	MOV	WHO1(TT),A	;PRINT FIRST USER WHO VAR
	MOV	#WHO2,T
	JSR	PC,UWVDO
	MOV	WHO1A(TT),A	;MAYBE PRINT SPACE
	BMI	UWHLD1
	JSR	PC,SPACE
	MOV	WHO1A(TT),A
UWHLD1:	MOV	#WHO3,T		;NOW SECOND USER WHO VAR
;TAKE CONTROL WORD IN A, OFFSET (OFF TT) TO FOUR WORDS IN T, PRINT USER WHO VAR
;CONTROL WORD:
;	15	USED ELSEWHERE - IGNORE HERE
;	14	SUPPRESS SPACE BETWEEN TWO HALVES
;	13-11	MODE FOR FIRST HALF
;	10-08	MODE FOR SECOND HALF
;	07	DOUBLE 06-00
;	06-00	CHARACTER TO PRINT AFTER FIRST HALF, BEFORE SPACE
UWVDO:	PUSH	A		;SAVE CONTROL WORD
	ADD	TT,T		;T POINT TO VAR
	MOVB	1(SP),A
	ASR	A		;GET FIRST MODE
	ASR	A
	ASR	A
	JSR	PC,UWVDO4	;PRINT FIRST HALF
	MOVB	(SP),A
	BEQ	UWVDO1
	BIT	#200,A
	BEQ	UWVDO3
	JSR	PC,TVOMSK	;SEPARATOR CHAR(S)
UWVDO3:	JSR	PC,TVOMSK
UWVDO1:	BITB	#100,1(SP)
	BNE	UWVDO2
	JSR	PC,SPACE	;INTERVENING SPACE
UWVDO2:	MOVB	1(SP),A		;GET SECOND MODE
	TST	(SP)+		;POP CONTROL WORD, THEN DO SECOND HALF
UWVDO4:	BIC	#177770,A
	ASL	A
	JMP	@UWVDTB(A)

UWVDTB:	RTSPC			;0	DON'T PRINT
	UWVDAT			;1	PACKED DATE AS MM/DD/YY
	UWVTEN			;2	TIME IN .025 SECONDS AS HH:MM:SS.T
	UWVHAK			;3	TIME IN .5 SECONDS AS HH:MM:SS
	UWVHAK			;4	OCTAL (18. BITS)
	UWVHAK			;5	DECIMAL (18. BITS)
	SIXPN1			;6	THREE SIXBIT CHARS
	RTSPC			;7	RESERVED FOR EXPANSION

;USER-CONTROLLED WHO-LINE FIELD PRINT-OUT ROUTINES.

UWVHAK:	MOV	#MQ,B
	TST	(T)+
	MOV	(T),(B)
	MOV	-(T),-(B)
	CMP	(T)+,(T)+
	MOV	#-14.,LSH
	JMP	@UWVDT1-6(A)

UWVDT1:	TIMTY1
	UWVOCT
	UWVDEC

UWVOCT:	MOV	#10,B
	BR	UWVDC1

UWVDEC:	MOV	#10.,B
UWVDC1:	PUSH	RADIX
	MOV	B,RADIX
	JSR	PC,DECPN9
	POP	RADIX
	RTS	PC

UWVTEN:	MOV	(T)+,A
	TST	(T)+
	JMP	TIMTEN

UWVDAT:	MOV	(T)+,A
	TST	(T)+
	JMP	DATTYP

;SOME WHO LINE UTILITY ROUTINES

PERCNT:	MOV	#'%,A
JMPTVO:	JMP	TVO

SPACE:	MOV	#40,A
	BR	JMPTVO

SLASH:	MOV	#'/,A
	BR	JMPTVO

;TAKES POINTER TO SIXBIT IN T AND TYPES IT (ADVANCING T)

SIXPNT:	JSR	PC,SIXPN1	;DO TWO SETS OF THREE CHARS
SIXPN1:	MOV	#MUL,B		;DO ONE SET OF THREE CHARS
	MOV	#LSH,C
	CMP	(T)+,(T)+	;BAG BITING EAE HAS TO LOADED IN JUST THE RIGHT ORDER
	MOV	-(T),-(B)	;LOW ORDER FIRST
	MOV	-(T),-(B)
	CMP	(T)+,(T)+
	MOV	#-10.,(C)	;FIRST CHARCTER IN AC, THE REST IN MQ
	JSR	PC,SIXPN2	;PRINT FIRST CHAR
	JSR	PC,SIXPN2	;PRINT SECOND, FALL IN FOR THIRD
SIXPN2:	MOV	(B)+,A		;SIXBIT
	ADD	#40,A		;ASCII
	PUSH	(B)+
	JSR	PC,TVO
	POP	-(B)
	CLR	-(B)		;CLEAR AC
	MOV	#6,(C)		;NEXT CHARACTER INTO AC
	RTS	PC

;TAKES TENTHS OF SECONDS IN A AND PRINTS AS HH:MM:SS.T

TIMTEN:	MOV	#MQ,T
	MOV	A,(T)
	CLR	-(T)
	MOV	#10.,-(T)	;DO DIVIDE
	TST	(T)+
	PUSH	(T)+		;TENTH'S OF SECONDS
	MOV	(T),A
	ASL	A		;# HALF SECONDS JOB HAS BEEN RUNNING
	JSR	PC,TIMTYP	;TYPE TIME
	MOV	#'.,A
	JSR	PC,TVO
	POP	A		;TENTH'S OF SECONDS
	JMP	DECPNT

;TAKES # HALF SECONDS IN A AND TYPES TIME IN HH:MM:SS FORMAT

TIMTYP:	MOV	#MQ,B
	MOV	A,(B)
	CLR	-(B)
;TAKE # HALF SECONDS IN EAE AC-MQ AND TYPE AS HH:MM:SS
TIMTY1:	MOV	#120.,-(B)	;MINUTES SINCE MIDNIGHT
	TST	(B)+
	PUSH	(B)		;REMAINDER IS SS*2
	ASR	(SP)
	CLR	(B)		;CLEAR AC
	MOV	#60.,-(B)	;HOURS SINCE MIDNIGHT
	TST	(B)+
	PUSH	(B)+		;REMAINDER IS MM
	MOV	(B),A		;HH
	JSR	PC,DECPNT
	MOV	#':,C		;COLON SEPARATES GOODIES
	POP	A
	JSR	PC,MSDPNT	;PRINTS COLON AND PADS WITH LEADING ZERO IF NECESSARY
	POP	A
MSDPNT:	PUSH	A
	MOV	C,A		;PRINT SEPARATING CHARACTER
	JSR	PC,TVO
	CMP	#10.,(SP)
	BLE	MSDPN1		;PAD WITH LEADING ZERO?
	MOV	#'0,A
	JSR	PC,TVO
MSDPN1:	POP	A
	JMP	DECPNT		;PRINT NUMBER

;TAKE DATE PACKED AS 7 BITS YEAR, 4 MONTH, 5 DAY AND PRINT AS MM/DD/YY

DATTYP:	MOV	#MQ,B
	MOV	A,(B)
	CLR	-(B)		;CLEAR AC
	MOV	#LSH,C
	MOV	#7,(C)		;YEAR
	PUSH	(B)
	CLR	(B)
	MOV	#4,(C)		;MONTH
	MOV	(B),A
	CLR	(B)
	MOV	#5,(C)		;DAY
	PUSH	(B)
	JSR	PC,DECPNT	;PRINT MONTH
	MOV	#'/,C		;USE SLASH AS SEPARATOR
	POP	A
	JSR	PC,MSDPNT	;PRINT DAY
	POP	A
	JMP	MSDPNT		;PRINT YEAR


.SBTTL PDP-10 COMMAND PROCESSOR SWITCH VIDEO SWITCH, ETC.

TENCMD:	CMP	#MAXCMD,A	;LEGAL COMMAND?
	BLOS	TENCFL		;NO, COMMAND FAILS
	ASL	A		;BYTES FOR DISPATCH
	JMP	@TENDSP(A)

;PDP-10 COMMAND DISPATCH

TENDSP:	TENCFL	;0 ILLEGAL
	TENVSW	;1 VIDEO SWITCH
	TENDPC	;2 CONS DPY FOR PDP-10
	TENDPR	;3 RETURN DPY
	TENRVS	;4 READ VIDEO SWITCH
	TENASW	;5 AUDIO SWITCH
	TENRAS	;6 READ AUDIO SWITCH
MAXCMD==<.-TENDSP>/2

;HERE TO SWITCH VIDEO SWITCH

TENVSW:	MOV	CMDBUF,TT	;SWITCH INPUT
	MOV	CMDBUF+4,T	;SWITCH OUTPUT
	CHROFF			;INHIBIT INTERRUPTS WHILE WE DO THIS
	JSR	PC,VSWCMD	;CHECKS FOR LEGAL BEFORE SWITCHING
	BHIS	TENCF1		;JUMP IF THEY WERE ILLEGAL.
TENCS1:	CHRON
TENCSD:	MOV	#-1,CMDFLG	;COMMAND SUCCEEDS
	RTS	PC

;SWITCH AUDIO SWITCH UPON COMMAND FROM PDP-10

TENASW:	MOV	CMDBUF,TT	;SWITCH INPUT
	MOV	CMDBUF+4,T	;SWITCH OUTPUT
	CHROFF
	JSR	PC,ASWCMD	;SWITCH SWITCH, TESTING LEGALITY.
	BHIS	TENCF1		;JUMP IF THEY WERE ILLEGAL, TO SAY COMMAND FAILED.
	BR	TENCS1

;HERE TO CONS UP DPY FOR PDP-10

TENDPC:	CHROFF			;INHIBIT INTERRUPTS AGAIN
	MOV	CMDBUF,C	;ARG IS KEYBOARD TO USE, OR -1 FOR NO KEYBOARD.
	CMP	C,#MAXKBD	;BUT BARF IF ILLEGAL KEYBOARD NUMBER.
	BGE	TENCF1
	JSR	PC,CHCONS	;GET A CHANNEL, CONNECT IT TO THAT KEYBOARD.
	TST	T
	BLT	TENCF1		;CAN'T => COMMAND FAILS.
	MOVB	LECREG(U),CMDBUF ;ELSE RETURN THE VIDEO BUFFER NUMBER
	CLRB	CMDBUF+1
	MOV	T,CMDBUF+4	;AND THE 10-11 CHANNEL NUMBER (TTY NUMBER MINUS 52).
	BR	TENCS1

TENCF1:	CHRON
TENCFL:	CLR	CMDFLG		;REPORT FAILURE OF A COMMAND TO THE TEN.
	RTS	PC

;HERE TO RETURN DPY ON COMMAND

TENDPR:	MOV	CMDBUF,TT	;THE DPY TO RETURN
	MOV	#MAXTV-1,T
TENDR0:	CMPB	CHCREG(T),TT	;WHICH CHANNEL DOES IT BELONG TO?  GET # IN T.
	BEQ	TENDR1
	DEC	T
	BGE	TENDR0
	BR	TENCSD

TENDR1:	TST	CHNUSE(T)	;DO NOTHING IF THE CHANNEL IS FREE.
	BEQ	TENCSD
	CHROFF			;OTHERWISE, FREE THAT CHANNEL.
	JSR	PC,CHRETN
	BR	TENCS1

;HERE RETURN STATE OF VIDEO SWITCH

TENRVS:	JSR	PC,SWTARG	;SET UP 10-11 CHANNEL ARGUMENT
	BLOS	TENCFL		;ILLEGAL ARG MAKES COMMAND FAIL
	JMP	@RVSDSP(T)
RVSDSP:	TENCFL			;0 IS ILLEGAL
	RVSCHN			;1 10/11 CHANNEL #
	RVSKBD			;2 KBD #
	RVSOUT			;3 VIDEO SWITCH OUTPUT #
NSWTRG==<.-RVSDSP>/2

RVSKBD:	JSR	PC,CHKKBD	;HERE GIVEN KBD #;  TEST IT.
	BHI	RVSCH1		;IF LEGAL, FALL INTO MAIN LINE CODE
	BR	TENCFL		;ILLEGAL, TELL HIM SO

RVSOUT:	MOV	CMDBUF+4,TT	;HERE GIVEN VIDEO SWITCH OUTPUT #.
	MOV	#-1,T		;ILLEGAL KBD #
	CMP	#MAXVSO,TT	;CHECK FOR LEGAL
	BHI	RVSCH2		;FALL INTO MAIN LINE CODE
	BR	TENCFL		;HERE IF ILLEGAL	

RVSCHN:	JSR	PC,CHNKBD	;HERE GIVEN 10-11 CHANNEL #; GET KBD # IN T
	BLOS	TENCFL
RVSCH1:	MOVB	KBDVSW(T),TT	;GET VIDEO SWITCH OUTPUT INTO TT
RVSCH2:	MOV	TT,CMDBUF+<4*4>	;PUT VIDEO SWITCH OUTPUT INTO COMMAND BUFFER
	MOV	TT,CMDBUF+<3*4>
	TST	CMDBUF
	BMI	RVSDF		;BRANCH IF HE WANTS DEFAULT INPUT OF THIS OUTPUT.
	MOVB	VSWTAB(TT),TT	;GET CURRENT INPUT OF THIS OUTPUT AND STORE.
	BR	RVSCH3

RVSDF:	ASL	T		;MAKE IT BYTE INDEX
	BMI	RVSNL		;NEGATIVE IF NOT LOGGED IN
	MOV	KBDLE(T),U
	BEQ	RVSNL		;KBD NOT LOGGED IN, ITS THE DEFAULT
RVSDF1:	MOVB	LECREG(U),TT	;THE REGISTER HE HACKS
	CMP	#MAXTV,TT
	BLOS	TENCFL		;BRANCH IF ILLEGAL CONSOLE #
	ASL	TT		;MAKE IT A BYTE INDEX
	MOV	DPYVSW(TT),TT	;VIDEO SWITCH INPUT
RVSCH3:	MOV	TT,CMDBUF+<2*4>	;STORE SWITCH INPUT INTO COMMAND BUFFER
	BR	TENCSD

RVSNL:	MOV	DPYCHN,U	;CHANNEL 0 IS CONSOLE FREE CHANNEL
	BR	RVSDF1		;AND BACK INTO MAIN STREAM

;GIVEN 10/11 CHANNEL # AND RETURNS KBD IN T

CHNKBD:	MOV	CMDBUF+4,T	;PICK UP CHANNEL #
	CMP	#MAXTV,T
	BLOS	CHNKB2
	ASL	T		;MAKE CHANNEL # INTO INDEX INTO CHANNEL TABLES
	ASL	T
	TST	CHNCLS(T)	;MAKE SURE CHANNEL IS OPEN
	BLT	CHNKB3
	MOVB	DPYKBD(T),T	;PICK UP KBD #
CHNKB1:	CMP	#MAXKBD,T	;FIX CONDITION CODES FOR SUCCESSFUL RETURN
CHNKB2:	RTS	PC

CHNKB3:	MOV	#MAXKBD+1,T	;HERE IF CHANNEL CLOSED
	BR	CHNKB1		;CONS UP ILLEGAL KBD #

CHKKBD:	MOV	CMDBUF+4,T	;CHECK FOR REASONABLE KBD #
	BR	CHNKB1

;HERE TO SET UP SWITCH ARG FOR 10-11 COMMAND RETURN IN CONDITION CODES
;IS THE RESULT OF CMP #NCHARG,<argument type> TO CHECK FOR LEGALITY

SWTARG:	MOV	CMDBUF,T	;ARGUMENT TYPE
	BPL	.+4		;MAKE SURE WE HAVE A POSITIVE #
	NEG	T
	ASL	T		;MAKE IT INTO A BYTE INDEX
	CMP	#NSWTRG*2,T	;TEST FOR LEGAL
	RTS	PC

;HERE RETURN STATE OF AUDEO SWITCH

TENRAS:	JSR	PC,SWTARG	;SET UP 10-11 CHANNEL ARGUMENT
	BLOS	RASLOS		;ILLEGAL ARG MAKES COMMAND FAIL
	JMP	@RASDSP(T)
RASDSP:	TENCFL			;0 IS ILLEGAL
	RASCHN			;1 10/11 CHANNEL #
	RASKBD			;2 KBD #
	RASOUT			;3 AUDEO SWITCH OUTPUT #
.IIF NZ .-<NSWTRG*2>-RASDSP,.ERROR RASDSP AND RVSDSP DIFFER.

RASCHN:	JSR	PC,CHNKBD		;GIVEN A 10-11 CHANNEL #;  GET KBD # IN T
	BLOS	RASLOS
RASCH1:	MOVB	KBDASW(T),TT		;GET AUDEO SWITCH OUTPUT INTO TT
RASCH2:	MOV	TT,CMDBUF+<3*4>		;PUT OUTPUT NUMBER IN AS RETURN VALUE.
	CLR	CMDBUF+<2*4>		;IF HE WANTS DEFAULT INPUT OF THIS OUTPUT, IT'S 0.
	TST	CMDBUF
	BMI	RASCH3			;BRANCH IF HE WANTS DEFAULT INPUT OF THIS OUTPUT.
	MOVB	ASWTAB(TT),CMDBUF+<2*4>	;GET CURRENT INPUT OF THIS OUTPUT AND STORE.
RASCH3:	JMP	TENCSD

RASKBD:	JSR	PC,CHKKBD	;HERE IF GIVEN KBD #; TEST FOR LEGALITY.
	BHI	RASCH1		;IF LEGAL, FALL INTO MAIN LINE CODE
RASLOS:	JMP	TENCFL		;ILLEGAL, TELL HIM SO

RASOUT:	MOV	CMDBUF+4,TT	;HERE IS GIVEN AUDEO SWITCH OUTPUT
	CMP	#MAXASO,TT	;CHECK FOR LEGAL
	BHI	RASCH2		;FALL INTO MAIN LINE CODE
	BR	RASLOS		;HERE IF ILLEGAL	

.SBTTL ERROR TRAPS HERE

NXMBRK:	BPT
RESBRK:	BPT
IOTBRK:	BPT
PWRBRK:	BPT
EMTBRK:	BPT
TRPBRK:	BPT

;BPT BREAKS COME HERE IF THERE IS NO RUG.
;DON'T WANT TO HALT THE 11 SINCE 11TEN INTERFACE WOULDN'T BE ABLE TO GET TO BUS.
;WANT TO PUT CONTENTS OF REGISTERS IN CORE WHERE CARPET CAN GET AT THEM.

BPTBRK:	.REPT 7			;SAVE THE ACS
	 MOV %0+.RPCNT,BPTACS+<2*.RPCNT>
	.ENDR
	MOV #INITED-2,A		;TELL THE 10 WE'RE DOWN
	CLR (A)+
	CLR (A)+
	CLR (A)+
	CLR (A)+

; BELOW LOSES - PREVENTS RESTUFFING UNLESS YOU GO HIT SWITCHES
;	WAIT			;PUT 000001 IN LIGHTS (11/05)
	BR .			;WAIT FOR RELOAD OR MANUAL INTERVENTION
				;BRANCH TO POINT SO STUFF WILL AUTOMATICALLY START IT.
	.REPT 7			;PROCEED
	 MOV BPTACS+<2*.RPCNT>,%0+.RPCNT
	.ENDR
	RTI

BPTACS:	.BLKW 7

.SBTTL CLOCK ROUTINES CAUSE BLINKING

CLKBRK:	DEC	TYMSHR		;COUNT DOWN THIS DPY'S QUANTUM
;******* TEMPORARY CODE TO CHECKSUM THE FONT *******
;CHECKSUM IT 100 OCTAL WORDS AT A TIME, SO AS NOT TO SLOW THINGS DOWN
;TOO MUCH.  WILL GET CHECKED APPROXIMATELY FOUR TIMES A SECOND.
	PUSH T
	PUSH TT
	MOV CKSPNT,T
	MOV T,TT
	ADD #100*2,TT
	CMP TT,#FNTEND
	BLOS 1$
	MOV #FNTEND,TT
1$:	ADD (T)+,CKSSUM
	CMP T,TT
	BLO 1$
	MOV T,CKSPNT
	CMP TT,#FNTEND
	BNE 2$
	CMP CKSSUM,CKSSMG
	BEQ .+4
	 BPT
	CLR CKSSUM
	MOV #FNTORG,CKSPNT
2$:	POP TT
	POP T
;******* END OF TEMPORARY CODE *******
	PUSH	T
	ADD	#1,TICKS1	;INC DOES NOT AFFECT C-BIT (SIGH)
	ADC	TICKS
	TST	KBDFLG
	BNE	CLKBR1		;HAS PDP-10 HACKED THE LAST BUNCH?
	MOV	KBDACT,KBDFLG	;YES, GIVE HIM THE NEW BUNCH
	CLR	KBDFLG+2	;PARANOIA REIGNS SUPREME
	CLR	KBDACT
	CLR	KBDLAST		;POINTS TO END OF ACTIVE CHAIN

;CLOCK QUEUE DISPATCH

CLKBR1:	MOV	CLOCKQ,T
	BEQ	CLKBR2		;ANYTHING ON CLOCK QUEUE?
	TST	(T)+		;IGNORE CDR
	CMP	(T)+,TICKS	;DOUBLE-PRECISION COMPARE TIME NOW
	BHI	CLKBR2		;WITH TIME IN QUEUE BLOCK; TO CLKBR2 IF NOT DUE YET.
	BLO	CLKBR3
	CMP	(T)+,TICKS1
	BHI	CLKBR2
CLKBR3:	PUSH	CLOCKQ		;CDR THE CLOCK QUEUE
	MOV	@(SP),CLOCKQ
	JSR	PC,@(T)+	;CALL CLOCK LEVEL ROUTINE, T POINTS TO ARGUMENT
	POP	T
	MOV	CLOCKF,(T)	;PUT OLD SLOT ON FREE LIST
	MOV	T,CLOCKF
	BR	CLKBR1		;CHECK AGAIN IF SOMETHING STILL ON QUEUE

CLKBR2:	DEC	BLINK
	BGE	.+10
	MOV	#BLKTIM,BLINK
	CMP	BLINK,#MAXTV
	BHIS	CLKR1
	MOV	BLINK,T
	TSTB	BLKSWT(T)
	BNE	CLKR1
	PUSH	U
	PUSH	CREG
	PUSH	AC
	PUSH	MQ
	MOVB	T,CREG
	ASL	T
	MOV	BLINKS(T),T	;BLINK CHAIN FOR THIS DPY
	BEQ	CLKBR4
CLKLOP:	MOV	BLCURS(T),U	;CURSOR TO BLINK
	JSR	PC,XORCHR
	COMB	BLON(T)		;CHANGE STATE OF BLINK
	MOV	BLNEXT(T),T
	BNE	CLKLOP
CLKBR4:	POP	MQ		;CLOCK RETURN
	POP	AC
	POP	CREG
	POP	U
CLKR1:	TST	BLINK
	BEQ	CLKR3
	CMP	BLINK,#BLKTIM/2
	BNE	CLKR2
CLKR3:	JSR	PC,RPT		;AS OFTEN AS WE BLINK, HANDLE THE REPEAT KEY.
CLKR2:	INCB	SSCC		;INCREMENT SEMI-SLOW CLOCK COUNT
	BNE	CLKRET		;WRAP-AROUND => SEMI-SLOW CLOCK TICK
	BR	CLKBRS

;ON ALL CONSOLES IN "REPEAT" MODE, PERFORM ONE REPETITION
;BY SENDING AS INPUT TO THE PDP-10 ANOTHER COPY OF THE CHAR
;MOST RECENTLY SENT.  ALSO DECREMENTS ALL FINITE REPEAT COUNTS.
RPT:	JSR U,ACSAV
	PUSH CREG
	MOV #LEUVAR,U
RPT4:	TST LERPT(U)
	BEQ RPT3
	BMI RPT1
	DEC LERPT(U)
RPT1:	MOV LELSTA(U),A
	MOV LELSTB(U),B
	JSR PC,PUTCHR
RPT3:	ADD #LELEN,U
	CMP #LEUEND,U
	BGT RPT4
	POP CREG
	JMP ACRES

;COME HERE EVERY  256./60. = 4.27  SECONDS FOR SEMI-SLOW CLOCK
CLKBRS:	PUSH	TT
	PUSH	C
	PUSH	U
	PUSH	#69.		;FOR DEBUGGING
	TST	KBDTSW
	BEQ	SSCRET
	CLR	KBDTSW
	MOV	#KBDDEF+<2*MAXKBD>,T
	BR	CLKBR5

CLKBR9:	INC	KBDTSW
CLKBR5:	CMP	#KBDDEF-2,T
	BEQ	SSCRET
	TST	-(T)		;FAST LOOP LOOKING FOR ANY KEYBOARD
	BGE	CLKB10		; NEEDING ITS CONSOLE'S VIDSW INPUT RESET
	BR 	CLKBR5
CLKB10:	DECB	1(T)
	BGE	CLKBR9		;NOT TIME TO RESET THIS SCREEN YET
	MOV	T,C
	SUB	#KBDDEF,C	;C HAS 2*KBD NUMBER, FOR VSWDEF.
	PUSH	T
	JSR	PC,VSWSGO	;SET UP L.E. INDEX IN U, VSW OUTPUT IN T
	BLT	CLKBR7		;VSWSGO IS NEGATIVE IF SOMETHING IS FUNNY.
	JSR	PC,VSWDEF	;RESET VIDEO SWITCH INPUT
CLKBR7:	POP	T
	BR	CLKBR5

SSCRET:	CMP	(SP)+,#69.	;IS STACK SCREWED?
	BEQ	SSCRE1
	BPT
SSCRE1:	POP	U
	POP	C		;SEMI-SLOW CLOCK RETURN
	POP	TT
CLKRET:	POP	T
CRTI:	RTI

;CLEARS ALL BLINKERS ON THIS DPY

CLBLIN:	PUSH	U
	MOVB	CREG,T
	BIC	#177400,T
	ASL	T
	MOV	BLINKS(T),T
	BEQ	CLBL2
CLBL0:	TSTB	BLON(T)		;BLINK ON?
	BEQ	CLBL1
	MOV	BLCURS(T),U
	JSR	PC,XORCHR
	CLRB	BLON(T)
CLBL1:	MOV	BLNEXT(T),T
	BNE	CLBL0
CLBL2:	POP	U
	RTS	PC

;CLOCK QUEUE ROUTINES

;ADQUE	CALLED WITH ARG IN T, THE CALLING SEQUENCE IS:

;	JSR	TT,ADQUE
;		DELTA T
;		ROUTINE TO CALL AT CLOCK LEVEL

ADQUE:	PUSH	T		;ARG FOR ROUTINE
	MOV	CLOCKF,T	;GET FREE CLOCK QUEUE SLOT
	BEQ	ADQFL		;IF THERE IS A FREE ONE
	TST	(T)+		;IGNORE CDR
	MOV	TICKS,(T)+	;MOVE IN CURRENT TIME
	MOV	TICKS1,(T)
	ADD	(TT)+,(T)+	;TIME TO CALL ROUTINE
	ADC	-4(T)
	MOV	(TT)+,(T)+	;ROUTINE TO CALL
	MOV	(SP)+,(T)	;AND ITS ARG
	PUSH	TT		;RETURN ADDRESS
	MOV	CLOCKF,TT	;ADDRESS OF THIS CLOCK QUEUE SLOT
	MOV	(TT),CLOCKF	;CDR THE FREE LIST
	PUSH	TT		;ADDRESS OF ONE TO ADD
	PUSH	#CLOCKQ		;ADDRESS OF PREVIOUS CLOCK QUEUE ENTRY
ADQUE1:	MOV	@(SP),TT	;CURRENT ENTRY IN QUEUE
	BEQ	ADQUE2		;END OF QUEUE?
	MOV	2(SP),T		;THE ONE WE WANT TO ADD
	CMP	(T)+,(TT)+	;IGNORE CDR'S
	CMP	(T)+,(TT)+	;HIGH ORDER OF TIME
	BLO	ADQUE2		;GO SPLICE IT IN HERE
	BHI	ADQUE3
	CMP	(T)+,(TT)+	;LOW ORDER
	BLOS	ADQUE2
ADQUE3:	MOV	@(SP),(SP)	;CDR THE QUEUE
	BR	ADQUE1

;HERE TO SPLICE ENTRY INTO CLOCK QUEUE

ADQUE2:	MOV	@(SP),@2(SP)	;CDR OF QUEUE, GOES TO CDR OF NEW ENTRY
	MOV	2(SP),@(SP)	;CURRENT SLOT GOES TO CDR OF PREVIOUS
	CMP	(SP)+,(SP)+	;CLEANSE STACK
	POP	TT
	RTS	TT

;HERE FOR NO FREE CLOCK QUEUE SLOTS

ADQFL:	CMP	(TT)+,(TT)+	;SKIP OVER ARGS
	POP	T		;CLEANSE STACK
	RTS	TT

;THIS CAUSES CONSOLE FREE DPY TO GLITCH

MSGLIT:	PUSH	CREG
	MOV	(T),T
	MOV	T,CREG
	JSR	TT,ADQUE
		GLITIM
		MSGLIT
	MOV	CSA,T
	PUSH	T
	BIC	#-BOWBIT,T		;CLEAR BOW AND OTHER GARBAGE
	ADD	#LINHT*BYTPL/10,T	;GLITCH ONE CHARACTER LINE
	CMP	#LINHT*BYTPL*CHRLN/10,T
	BHI	.+4			;WRAP AROUND?
	CLR	T
	BIC	#-1#<-BOWBIT>,(SP)
	BIS	T,(SP)
	POP	CSA		;ZAP
	POP	CREG
	RTS	PC

;HERE TO RING BELL ON DPY

BELL:	PUSH	T
	MOV	CREG,T
	MOVB	T,TT		;DOUBLE TV BUFFER # FOR BYTE INDEX
	ASL	TT

	CHROFF			;INHIBIT INTERRUPTS WHILE WE HACK CLOCK QUEUE, ETC.
	INC	BELCNT(TT)	;FLASH SCREEN AT LEAST ONCE
	BEQ	BELL0		;IF NONE PENDING, FLASH IT NOW
	INC	BELCNT(TT)	;IF BELLS PENDING THEN FLASH TWICE
	CMP	BELCNT(TT),#MAXBEL
	BLOS	BELL0A
	DEC	BELCNT(TT)
	DEC	BELCNT(TT)
	BR	BELL0A

;HERE IF NO BELLS PENDING, FLASH SCREEN RIGHT AWAY, ADD CLOCK QUEUE ENTRY

BELL0:	JSR	PC,BOWXOR	;FLASH THE SCREEN NOW!
	JSR	PC,BELL1A	;ADD CLOCK QUEUE ENTRY
BELL0A:	CHRON

	POP	T
	RTS	PC

;CLOCK LEVEL BELL ROUTINE

BELL1:	PUSH	CREG
	MOV	(T),T		;THE DESIRED CONSOLE REGISTER
	MOV	T,CREG		;N.B. THE ALU MODE WAS SAVED AS "XOR"
	MOV	#BOWBIT,CSA	;FLASH THE SCREEN
	BIC	#177400,T	;THE DPY #
	ASL	T		;BYTE INDEX
	DEC	BELCNT(T)	;WE JUST DID THAT ONE
	BMI	BELL1B		;ANY MORE PENDING?
	JSR	PC,BELL1A	;YES, PUT ANOTHER ON QUEUE
BELL1B:	POP	CREG
	RTS	PC

BELL1A:	MOV	CREG,T		;PUT ANOTHER BELL ON CLOCK QUEUE
	JSR	TT,ADQUE
		BLKTIM
		BELL1
	RTS	PC

.SBTTL KEYBOARD INTERRUPT ROUTINES

;KEYBOARD BREAK ROUTINES  THE LINE EDITOR RUNS AT THIS LEVEL

KBDBRK:	JSR	U,ACSAV		;PUT AC'S ON STACK
	PUSH	CREG
	PUSH	AC
	PUSH	MQ
KBDLOP:	MOV	OLDKMA,A
	CMP	#KBDEND,A	;CHECK WRAP AROUND
	BHI	.+6
	MOV	#KBDBUF,A
	CMP	KMA,A
	BEQ	KBDRET		;NO MORE CHARACTERS
	MOV	(A)+,B		;RAW CHARACTER
	TSTB	(A)+		;GARBAGE
	MOVB	(A)+,-(SP)	;KEYBOARD #
	MOV	A,OLDKMA

;GET ASCII REPRESENTATION OF CHARACTER
;	ASCII CODE IN A, META BITS IN B

	MOV	B,C		;TWO COPIES OF RAW CHARACTER
	BIC	#RCHAR,B	;KEY STRUCK
	BIT	#RTPBIT,C	;TOP?
	BEQ	KBDX1
	BIS	#XTPBIT,B
	BR	KBDX2
KBDX1:	BIT	#RSLBIT,C	;SHIFT LOCK?
	BEQ	.+6
	BIS	#XSLBIT,B
	BIT	#RSHBIT,C	;SHIFT?
	BEQ	KBDX2
	BIS	#XSHBIT,B
KBDX2:	MOVB	XTAB(B),A	;ASCII REPRESENTATION
	BIC	#<<XSLBIT!XSHBIT!XTPBIT>#-1>,B	;FLUSH ALL UNINTERESTING BITS
	ASL	B		;XTAB TO ASCII REPRESENTATION
	ASL	B
	ASL	B
	BIT	#RMTBIT,C	;META?
	BEQ	.+6
	BIS	#AMTBIT,B
	BIT	#RCLBIT,C	;CONTROL?
	BEQ	.+6
	BIS	#ACLBIT,B
	MOVB	(SP)+,C		;KEYBOARD #
	ASL	C		;BYTE FOR INDEX INTO KBDLE
	TST	A
	BLT	NONASC		;NON-ASCII
KBDUN3:	TSTB	KBDESC(C)
	BNE	ESCBRK		;ESCAPE OR BREAK IS IN PROGRESS
	TSTB	KBDCNT(C)	;IF THIS SCREEN IS SPYING WITH A TIMEOUT,
	BLT	KBDUN1
	JSR	PC,VSWUNS	;UN-SPY IT IMMEDIATELY.
KBDUN1:	MOV	KBDLE(C),U	;ASSOCIATED LINE EDITOR?
	BEQ	KBDLOP
	TST	LERPT(U)	;IF THE REPEAT KEY IS IN EFFECT,
	BEQ	KBDUN2		;TURN IT OFF, AND FLUSH THIS CHARACTER.
	CLR	LERPT(U)
	BR	KBDLOP

KBDUN2:	MOVB	LECREG(U),CREG	;SET UP CONSOLE REGISTER
	BIS	#ACTBIT,B	;FEED THIS CHAR TO THE PDP-10
	JSR	PC,PUTCHR
	BR	KBDLOP

;KEYBOARD RETURN

KBDRET:	POP	MQ
	POP	AC
	POP	CREG
	POP	A
	POP	B
	POP	C
	POP	T
	POP	TT
	POP	U
	RTI

;NON-ASCII CHARACTERS COME HERE

NONASC:	NEG	A
	CMP	#MAXNAS,A
	BHIS	.+4
NONAS1:	BPT			;ILLEGAL CHARACTER
	CMP	#<MAXKBD*2>,C	;C HAS BEEN DOUBLED
	BHI	.+4
	BPT			;GARBAGE KBD #
	CLRB	KBDESC(C)
	ASL	A		;BYTES
	JSR	PC,@NASCTB(A)	;DISPATCH TO ROUTINE
JBDLOP:	JMP	KBDLOP

;PROCESS ESCAPE AND BREAK COMMANDS

ESCBRK:	JSR	PC,UPPER	;CONVERT LOWER CASE TO UPPER CASE
	MOV	#ESCHAR,T
ESCBR1:	CMPB	(T),A		;MATCH?
	BEQ	DOESC
	TSTB	(T)+		;END OF TABLE?
	BNE	ESCBR1
ESCBR2:	CLRB	KBDESC(C)	;NO COMMAND
	BR	JBDLOP

DOESC:	MOV	KBDLE(C),U	;IF COMMAND NEEDS LOGGED-IN KBD,
	BEQ	DOESC2		; MAKE SURE WE'RE LOGGED IN,
	MOVB	LECREG(U),CREG	; AND SET UP U AND CREG
DOESC1:	SUB	#ESCHAR,T
	CLRB	KBDESC(C)
	ASL	T		;MAKE A WORD INDEX.
	JSR	PC,@ESCTAB(T)	;C MUST BE KBD #, SOME ESCAPE ROUTINES RELY ON IT
	BR	JBDLOP

DOESC2:	CMP	#ESCSRN,T	;IF NOT LOGGED IN BUT MUST BE,
	BLE	ESCBR2		; THEN WE LOSE TOTALLY
	MOVB	DPYFRE,CREG	;OTHERWISE SET UP CREG FOR THE
	BR	DOESC1		; SAKE OF RANDOM BELLS

;NASCTB FOR KEYS SUCH AS BREAK, CLEAR, ETC POINTS HERE
;TO TURN THOSE CHARACTERS INTO TOP-LETTERS STARTING WITH "A".
;A HOLDS TWICE THE NASCTB INDEX.
BRKCLR:	ASR	A
	ADD	#4000+'@,A
BRKCLX:	TST	(SP)+		;FLUSH RETURN POINTER TO JBDLOP
	JMP	KBDUN3		;AND GO GIVE CHARACTER TO TEN.

GAMMA:	MOV #4011,A
	BR BRKCLX

DELTA:	MOV #4012,A
	BR BRKCLX

CRCPLS:	MOV #4015,A
	BR BRKCLX

PLSMNS:	MOV #4014,A
	BR BRKCLX

.SBTTL 10/11 INPUT/OUTPUT ROUTINES

;HERE TO COMPLEMENT STATE OF BOW BIT WHEN PDP-10 FALLS BEHIND ON KBD

SLOW10:	MOVB	LECREG(U),CREG
	JMP	BELL		;RING BELL


;PUT CHARACTER WHICH IS A OR'D WITH B INTO BUFFER. ACTIVATES IF
;	1	FINDS ACTIVATION CHARACTER
;	2	BUFFER FILLS
;A AND B ARE SAVED IN LELSTA AND LELSTB IN CASE THE USER DECIDES
;TO REPEAT THE CHARACTER.

PUTCHR:	TST	@LEBUF(U)
	BGT	PUTCH0			;BUFFER BEING FILLED?
	BLT	SLOW10			;HAS PDP-10 FALLEN BEHIND?
	MOV	#LBCHRS,@LEBUF(U)	;MARK BUFFER BUSY WITH # FREE CHARACTERS
PUTCH0:	TST	LEFREE(U)		;ANY ROOM LEFT IN BUFFER?
	BGT	PUTCH2
	BEQ	SLOW10			;NOPE, DO SOME ERROR CHECKING
	BPT				;LOSE IF LESS THAN NO ROOM

PUTCH2:	MOV	A,@LECHR(U)
	BIS	B,@LECHR(U)
	MOV	A,LELSTA(U)
	MOV	B,LELSTB(U)
	ADD	#2,LECHR(U)
	DEC	LEFREE(U)		;BUFFER FULL?
	BGT	PUTCH4
	BEQ	.+4			;WE MUST ACTIVATE ANYWAY
	BPT
	MOV	LEBUF(U),T
	TST	LHQUED(T)		;IF ALREADY QUEUED TO ACTIVATE,
	BEQ	ACTIVA			; DON'T ACTIVATE NOW
	RTS	PC

PUTCH4:	TST	B
	BGE	RTSPC1			;NOT ACTIVATING
	MOV	LEBUF(U),T		;ACTIVATION CHAR, MUST ACTIVATE
	TST	LHQUED(T)		;IF ALREADY QUEUED TO ACTIVATE,
	BNE	RTSPC1			; DON'T ACTIVATE NOW
	TST	@LHNEXT(T)		;TEST NEXT BUFFER IN RING
	BMI	QBFR			;IF NOT FREE, TRY ACTIVATION ON NEXT CLOCK TICK

;HERE TO ACTIVATE BUFFER

ACTIVA:	SUB	#LBCHRS,LEFREE(U)	;NEGATIVE OF ACTIVE CHARS
	BLT	.+4
	BPT				;HAD BETTER BE NEGATIVE
	MOV	LEBUF(U),T		;THE BUFFER TO ACTIVATE
	MOV	LEFREE(U),LHFLAG(T)	;THAT ACTIVATES IT

	CHROFF
	CLR	LHALST(T)		;PUT THIS ONE AT END CHAIN
	PUSH	KBDLAST
	MOV	T,KBDLAST
	POP	T
	BNE	ACTIV0			;EMPTY ACTIVATION LIST?
	MOV	KBDLAST,KBDACT		;YES, MAKE ACTIVE LIST POINT TO THIS ONE
	BR	ACTV0A
ACTIV0:	MOV	KBDLAST,LHALST(T)	;OLD LAST POINTS TO NEW LAST
ACTV0A:	MOV	KBDLAST,T		;IN ANY EVENT THIS THE ONE JUST ADDED
	TST	KBDFLG			;DOES THE PDP-10 WANT MORE
	BNE	ACTIV1
	MOV	KBDACT,KBDFLG		;ACTIVATE THIS LIST
	CLR	KBDACT			;AND PREPARE FOR NEXT
	CLR	KBDLAST
ACTIV1:	CHRON

	MOV	LHNEXT(T),T		;NEXT ON RING
	MOV	#LHLEN,TT
	ADD	T,TT			;FIRST FREE CHARACTER
	MOV	T,LEBUF(U)		;NEW BUFFER
	TST	(T)+			;LHFLAG IS SET AT PUTCHR
	CLR	(T)+			;LHZERO
;	CMP	(T)+,(T)+		;DON'T HACK LHNEXT AND LHALST
	MOV	TT,LECHR(U)		;FIRST FREE CHARACTER
	MOV	#LBCHRS,LEFREE(U)	;FREE CHARACTERS IN BUFFER
RTSPC1:	RTS	PC

;HERE AT CLOCK LEVEL TO ACTIVATE BUFFER

CLKACT:	PUSH	TT
	PUSH	U
	MOV	(T),U			;THE LINE EDITOR
	MOV	LEBUF(U),T		;THE BUFFER
	TST	LHFLAG(T)
	BGE	.+4
	BPT				;CAN'T ACTIVATE AN ALREADY ACTIVATED BUFFFER
	TST	@LHNEXT(T)		;THE NEXT BUFFER
	BMI	CLKAC1			;ACTIVATE IF READY
	CLR	LHQUED(T)
	JSR	PC,ACTIVA
CLKAC2:	POP	U
	POP	TT
	RTS	PC

CLKAC1:	JSR	PC,QBFR			;NOT, READY TRY ANOTHER CLOCK TICK
	BR	CLKAC2

;HERE IF NEXT BUFFER ON RING IS NOT FREE, TRY ACTIVATION AT NEXT CLOCK TICK

QBFR:	ZAPFLG	LHQUED(T)		;SET FLAG THAT SAYS WE'RE QUEUED
	MOV	U,T			;ARG
	CHROFF				;INHIBIT INTERRUPTS WHILE WE DO THIS
	JSR	TT,ADQUE		;PUT ON CLOCK QUEUE
		1			;AT NEXT TICK
		CLKACT			;CLOCK LEVEL ACTIVATION
	CHRON
	RTS	PC

;SAVE ALL ACS ON STACK

ACSAV:	PUSH	TT
	PUSH	T
	PUSH	C
	PUSH	B
	PUSH	A
	PUSH	U		;RETURN ADDRESS
	MOV	14(SP),U	;RESTORE U
	RTS	PC

;GETS NEXT CHARACTER FROM DPY BUFFER
;DPY CHANNEL POINTER IN U.  RETURNS SIGN-EXTENDED CHARACTER IN A, CLOBBERS TT.
;RETURNS 'EQ' IN CONDITION CODES IF NO CHARACTER PRESENT.

GETCHR:	MOV	DPY11B(U),TT		;GET POINTER FOR EASE IN INCREMENTING
	MOVB	(TT),A			;GET NEXT CHARACTER
	CMP	A,#-1			;HAS TEN PUT GOODIES THERE?
	BEQ	RTSPC1			;NO
	MOVB	#-1,(TT)		;MARK AS TAKEN
	DEC	DPY11B(U)		;ADVANCE POINTER
	ROR	TT			;USING PDP10 BYTE ORDER (1, 0, 3, 2)
	BCS	GETCH1			;BRANCH IF 1->0 OR 3->2
	ADD	#4,DPY11B(U)		;0->3 OR 2->1 NEXT WORD
	ROR	TT
	BCC	GETCH1			;BRANCH IF 0->3
	MOV	DPY11B(U),TT		;OTHERWISE NEXT PDP10 WORD
	DEC	TT
	MOV	#-1,-2(TT)		;SO SET PREV ONE TO ALL -1.
	MOV	#-1,-4(TT)		; IN CASE OF TIMING ERROR
	CMP	TT,DPYLGL(U)		;PAST END OF BUFFER?
	BLOS	GETCH1
	MOV	U,DPY11B(U)		;YES, RESET TO
	ADD	#DPDATA+1,DPY11B(U)	;FIRST WORD OF DATA AREA, HIGH BYTE
GETCH1: CLZ
	RTS	PC			;RETURN CONDITION CODE 'NE'

;GET NEXT CHARACTER BUT IF NOT AVAILABLE DO A COROUTINE-RETURN
;FROM THE CHARACTER-READING LOOP, SO THAT WHEN THE NEXT CHARACTER
;IS READ THIS CALL WILL BE RETURNED FROM.  ASSUMES THAT U CONTAINS THE
;ADDRESS OF THE CHANNEL VAR BLOCK, AND MAY RESET ALL ACS
;BUT B TO WHAT THEY HOLD AT DPYCTL. B IS ALWAYS PRESERVED.
GETCHC:	JSR	PC,GETCHR
	BEQ	GETCH2
	BIC	#-400,A		;CLEAR EXTRA BITS DUE TO SIGN-EXTENSION
	RTS	PC

GETCH2:	MOV	B,LESVB(U)
	POP	LECPC(U)
	POP	B
	CMP	B,#DPYXIT
	BEQ	GETCH3
	BPT			;CALLER OF GETCHC HAD WRONG RETURN ADDRESS
GETCH3:	JMP	DPYDX2		;CEASE TYPING ON THIS TV FOR A WHILE

.SBTTL DISPLAY FUNCTION (%TD, ETC) ROUTINES

TVOMSK:	BIC	#177600,A	;HERE IF YOU DON'T TRUST THE HIGH BITS

;TYPE CHARACTER IN A AND ADVANCE OVER IT.  PRESERVES A.

TVO:	JSR	PC,GENCHR	;GENERATES CHARACTER AND ADVANCES CURSOR

;LEDADC ADVANCES LINE EDITOR CURSOR

LEDADC:	ADD	#CHRWD,LEX(U)	;INCREMENT HPOS IN BITS FROM RIGHT MARGIN.
	BEQ	LEDAD2		;REACHED MARGIN => WRAP AROUND.
	TST	LEPHS(U)	;ELSE, INCREMENT THE AUXILIARY VARIABLES.
	BGT	LEDAD1
	ADD	#20,LEPHS(U)	;HERE IF WE ARE ADVANCING TO A NEW WORD.
	ADD	#2,LECC(U)
	CMP	LECC(U),#TVCFENCE
	BLOS	LEDAD1
	MOV	#TVLO,LECC(U)
LEDAD1:	SUB	#CHRWD,LEPHS(U)
	RTS	PC

LEDAD2:	JMP	CR

;RETREATS LINE EDITOR CURSOR

LEDREC:	CMP	LEX(U),#-BYTPL	;IF AT LEFT MARGIN, DON'T DO ANYTHING.  WE COULD WRAP AROUND,
	BEQ	LEDRE1		;BUT THAT'S MORE WORK, AND SHOULDN'T EVER HAPPEN ANYWAY.
	ADD	#CHRWD,LEPHS(U)
	SUB	#CHRWD,LEX(U)
	CMP	#<20-CHRWD>,LEPHS(U)
	BGE	LEDRE1
	SUB	#20,LEPHS(U)	;BACKUP A WORD IN DISPLAY
	SUB	#2,LECC(U)
	CMP	LECC(U),#TVLO
	BHIS	LEDRE1
	BPT			;BACKING UP PAST BEGINNING OF SCREEN?
LEDRE1:	RTS	PC

;HERE TO CRLF AND CLEAR EOL.
CRLF:	JSR	PC,CR
	CMP	#TVFENCE-<BYTPL*LINHT>,LELCC(U)	;IF NOW ON LAST LINE OF SCREEN,
	BEQ	CRLF1			;MUST SCROLL.
	JSR	PC,LF			;ELSE JUST MOVE DOWN AND CLEAR A LINE.
	JMP	CLEOL

CRLF1:	JSR	PC,SCROLL		;MOVE EVERYTHING UP 4 LINES,
	JMP	LF			;THEN MOVE DOWN 1 LINE.

;SCROLL THE TEXT, MOVING THE CURSOR WITH IT, UP 4 LINES.
SCROLL:	PUSH	LEY(U)			;TO SCROLL, HOME UP AND DELETE 4 LINES AT SCREEN TOP.
	PUSH	LELCC(U)
	PUSH	LECC(U)
	JSR	PC,HU
	MOV	#4,A
	JSR	PC,LDEL0
	POP	LECC(U)			;THEN RESTORE POSITION (TO LAST LINE, USUALLY)
	POP	LELCC(U)
	POP	LEY(U)
	MOV	LELCC(U),A
	SUB	#4*BYTPL*LINHT,A	;AND MOVE UP 4 LINES (OR TO SCREEN TOP).
	CMP	A,#TVLO
	BHI	SCROL1
	JMP	HU

SCROL1:	MOV	A,LELCC(U)
	SUB	#4*BYTPL*LINHT,LECC(U)
	SUB	#4*LINHT,LEY(U)
SCROLX:	RTS	PC

;HERE TO BACKSPACE (NO-OP IF AT BEGINNING OF LINE)

DPYBS:	CMP	LELCC(U),LECC(U)
	BEQ	SCROLX
	JMP	LEDREC

;HERE TO HOME UP AND CLEAR SCREEN.

DPYCLR:	JSR	PC,HU
	JMP	CLEOF

;HERE FOR LINE FEED, NO FRILLS.  WRAP AROUND AT SCREEN BOTTOM.
LF:	ADD	#<BYTPL*LINHT>,LELCC(U)
	ADD	#<BYTPL*LINHT>,LECC(U)
	ADD	#LINHT,LEY(U)
	CMP	#TVFENCE,LELCC(U)
	BHI	LF1
	SUB	#TVFENCE-TVLO,LELCC(U)
	SUB	#TVFENCE-TVLO,LECC(U)
	MOV	#-NLINS,LEY(U)
LF1:	RTS	PC

;HERE TO HOME UP
HU:	MOV	#TVLO,LELCC(U)		;RESET POINTER TO CURRENT LINE BEGINNING.
	MOV	#-NLINS,LEY(U)		;AND ITS POSITION ON SCREEN.

;HERE FOR CARRIAGE RETURN
CR:	MOV	LELCC(U),LECC(U)	;ORIGIN OF THIS LINE
CR1:	MOV	#20-CHRWD,LEPHS(U)	;PHASE
	MOV	#-BITPL,LEX(U)		;RESET X
	RTS	PC

;DELETE LINE(S).  MOVE UP THE LINES BELOW THE CURRENT ONE,
;FLUSHING THE CURRENT ONE.  BLANK LINES ARE SHIFTED IN AT THE BOTTOM.
LDEL:	JSR	PC,GETCHC		;READ NUMBER OF LINES TO DELETE IN A.
LDEL0:	MOV	#TVFENCE,B		;ADDRESS OF "END OF REGION"
LDEL00:	MOV	A,MQ
	BEQ	LINSX
	CMP	A,#50
	BHI	LINS3
	MOV	#BYTPL*LINHT,MUL	;GET # LINES * BYTPL*LINHT, = # BYTES TO SHIFT BY.
	MOV	LELCC(U),TT		;TT GETS ADDR OF THIS LINE.
	MOV	TT,T
	ADD	MQ,T			;T GETS ADDR OF LINE TO COPY INTO THIS.
	BCS	LDEL4			;CARRY => T IS PAST BOTTOM OF SCREEN ALREADY.
LDEL3:	CMP	T,B			;NO MORE LINES AT BOTTOM TO COPY UP =>
	BHIS	LDEL4			; START CLEARING INSTEAD.
	JSR	PC,CPYCHL		;COPY THEM, INCREMENTING T AND TT TO NEXT LINES.
	BR	LDEL3

LDEL4:	MOV	TT,T
;CLEAR TEXT LINES FROM THE ONE T POINTS TO, TO END OF REGION IN B.  PUTS CIOR IN CALU.
LDEL5:	CMP	T,B
	BHIS	LINSX			;POPJ, SETTING CALU TO CIOR.
	JSR	PC,CLRCHL
	BR	LDEL5

;INSERT LINE(S).  MOVE THE CURRENT LINE AND LOWER ONES DOWN ONE OR MORE POSITIONS.
;BLANK LINES SHIFT IN AT THE CURRENT POSITION.
LINS:	JSR	PC,GETCHC		;HOW MANY LINES TO INSERT (IN A).
	MOV	A,MQ
	BEQ	LINSX			;DON'T WASTE TIME IF INSERTING 0 LINES.
	CMP	A,#50			;DELETING INFINITE LINES = CLEAREOF
	BHI	LINS3
	MOV	#BYTPL*LINHT,MUL
	MOV	#TVFENCE-<BYTPL*LINHT>,TT	;TT POINTS AT LAST ACTUAL LINE ON SCREEN.
LINS4:	MOV	TT,T
	SUB	MQ,T			;T IS LINE TO COPY INTO IT (COPYING DOWNWARD).
	BCS	LINS3			;IF T IS ABOVE TOP OF SCREEN, GIVE UP.
LINS1:	CMP	LELCC(U),T		;STOP AFTER COPYING CURRENT LINE DOWN.
	BHI 	LINS3
	JSR	PC,CPYCHL		;COPY ONE LINE DOWNWARD.
	SUB	#2*BYTPL*LINHT,T	;THIS ADVANCES T AND TT TO NEXT LINE DOWN,
	SUB	#2*BYTPL*LINHT,TT	; WHEN WHAT WE WANT IS NEXT LINE UP.
	BR	LINS1

LINS3:	MOV	LELCC(U),T

;CLEAR C(A) LINES OF CHARACTERS, STARTING AT THE LINE T POINTS TO, BUT STOP IF REACH END OF SCREEN.
;SETS CALU TO CIOR.
LINS2:	CMP	#TVFENCE,T
	BLOS	LINSX
	JSR	PC,CLRCHL
	DEC	A
	BNE	LINS2
LINSX:	MOVB	#CIOR,CALU
	RTS	PC

;REGION SCROLLING

RGSCDN:	JSR PC,GETCHC		;NUMBER OF LINES IN REGION
	MOV A,B
	JSR PC,GETCHC		;NUMBER OF LINES TO MOVE DOWN
	MOV B,MQ
	MOV #BYTPL*LINHT,MUL
	MOV LELCC(U),TT
	SUB #BYTPL*LINHT,TT
	ADD MQ,TT		;ADDRESS OF LAST LINE IN REGION
	BCS LINSX		;IGNORE IF GARBAGE REGION (WRAPPED AROUND ADDRESS)
	CMP TT,#TVFENCE
	BHIS LINSX		;IGNORE IF GARBAGE REGION
	MOV A,MQ		;CONVERT DISTANCE TO MOVE TO BYTES
	BEQ LINSX		;EXIT IF NOT MOVING
	MOV #BYTPL*LINHT,MUL
	BR LINS4		;GO DO IT, USING INSERT-LINES SUBROUTINE

RGSCUP:	JSR PC,GETCHC		;NUMBER OF LINES IN REGION
	MOV A,B
	JSR PC,GETCHC		;NUMBER OF LINES TO MOVE UP
	MOV B,MQ
	MOV #BYTPL*LINHT,MUL
	MOV LELCC(U),B
	ADD MQ,B		;ADDRESS OF FIRST LINE AFTER REGION
	BR LDEL00		;GO DO IT, USING DELETE-LINES SUBROUTINE

;INSERT CHARACTER(S).  MOVE THE CURRENT CHARACTER AND FOLLOWING ONES TO THE RIGHT.
;BLANKS ARE SHOFTED IN AT THE CURRENT POSITION.
CINS:	JSR	PC,GETCHC		;A GETS HOW MANY CHARACTERS TO INSERT.
	JSR	PC,CINSET	;CHECK A FOR VALIDITY;  PUSH A, LELCC(U), LINHT, AND LECC(U).
CINSL:	MOV	6(SP),A
	MOV	(SP),T
	MOV	4(SP),C
	JSR	PC,CINS1L
	ADD	#BYTPL,(SP)
	ADD	#BYTPL,4(SP)
	DEC	2(SP)
	BNE	CINSL
	ADD	#6,SP			;FLUSH ALL BIT # CHAR POSITIONS FROM STACK.
	POP	B
	PUSH	LEX(U)
	PUSH	LEPHS(U)
	PUSH	LECC(U)
CINSC:	JSR	PC,CLRCHR		;NOW CLEAR OUT THE CHAR POSITIONS WE INSERTED.
	JSR	PC,LEDADC		;AND MOVE CURSOR PAST IT.
	DEC	B			;NOTE CLRCHR SETS CALU TO CIOR.
	BNE	CINSC
	POP	LECC(U)			;AND RESTORE THE CURSOR.
	POP	LEPHS(U)
	POP	LEX(U)
CINSX:	RTS	PC

;INSERT C(A) CHARACTER POSITIONS IN ONE RASTER LINE AT PLACE T POINTS AT.
;C POINTS AT FRONT OF RASTER LINE.  REQUIRES CALU/ CSET.
CINS1L:	MOV	A,MQ
	MOV	#CHRWD,MUL		;COMPUTE # OF BITS TO SHIFT THE LINE BY.
	MOV	#20,DIV			;COMPUTE # WORDS TO SHIFT IN MQ, # BITS IN AC.
	MOV	#20-CHRWD,TT
	SUB	LEPHS(U),TT		;TT GETS # BITS AT FRONT OF 1ST WORD NOT TO CHANGE.
	PUSH	TT
	PUSH	(T)			;ALSO SAVE THE WORD CONTAINING THEM.
	PUSH	T			;AND ITS ADDRESS
	PUSH	U			;FIT IN WITH WHAT CINS2 WILL POP.
	MOV	C,A
	ADD	#BYTPL,A		;A GETS ADDR TO AUTODECREMENT TO LAST WORD OF LINE.
	MOV	A,B
	SUB	MQ,B			;SUBTRACT THE # OF BYTES IN THE DESIRED # OF WORDS.
	SUB	MQ,B			;B GETS ADDR OF LAST WORD NOT SHIFTED INTO BIT BUCKET,
	MOV	-(B),TT			;TT GETS ITS CONTENTS, TO INIT THE LOOP.
	MOV	AC,C
	NEG	C			;C <= SHIFT COUNT, TO GET 1 NEW WORD FROM PAIR OF OLD.
CINS1:	CMP	B,T			;NOTE T STILL HAS ADDR OF LOWEST (LAST) WORD TO SHIFT
	BEQ	CINS3
	MOV	TT,MQ
	MOV	-(B),TT			;FETCH ANOTHER (LOWER) OLD WORD, FROM WHICH
	MOV	TT,AC			;(COMBINED WITH PREVIOUS OLD WORD)
	MOV	C,LSH			;WE MAKE A NEW SHIFTED WORD.
	MOV	MQ,-(A)			;STORE THE NEXT NEW WORD.
	BR	CINS1

CINS3:	MOV	AC,-(A)			;REMAINDER OF LAST FROM-WORD GOES INTO LAST TO-WORD.
	BR	CINS2

;FOR INSERT/DELETE CHARACTER, CHECK ARG IN A FOR LEGALITY.  MAYBE JUMP OFF
;TO CLEAR-TO-END-OF-LINE FOR INSERTING OR DELETING TOO MANY CHARACTERS.
;OTHERWISE, RETURN HAVING PUSHED ON THE STACK THE ARG, LELCC(U), #LINHT, AND LECC(U).
CINSET:	POP	B			;GET RET ADDR OFF STACK SO WE CAN POPJ OUR CALLER
	MOV	A,MQ			;OR PUSH ON HIS STACK.
	BEQ	CINSX			;IF ARG IS 0, OUR CALLER HAS NOTHING TO DO, SO POPJ HIM
	MOV	#CHRWD,MUL
	MOV	LEX(U),C		;AT WHAT DOT POSITION DOES REGION INSERTED/DELETED END?
	ADD	MQ,C
	BLT	.+6			;PAST RIGHT MARGIN => THIS OPERATION EQUIVALENT
	 JMP	CLEOL			;TO A CLEAR-TO-END-OF-LINE.
	MOVB	#CSET,CALU
	PUSH	A			;SAVE # CHAR POSITIONS TO INSERT.
	PUSH	LELCC(U)		;SAVE ADDR START OF 1ST RASTER LINE (ADVANCES)
	PUSH	#LINHT
	PUSH	LECC(U)			;AND ADDR OF CURSOR IN 1ST RASTER LINE.
	JMP	(B)			;RETURN TO OUR CALLER, HAVING PUSHED HIS TEMPS.

;DELETE CHARACTERS.  DELETE SOME CHARACTERS AFTER THE CURSOR.  THE FOLLOWING ONES
;MOVE LEFT.  BLANKS ARE SHOFTED IN AT THE RIGHT MARGIN.
CDEL:	JSR	PC,GETCHC		;A GETS HOW MANY CHARACTERS TO DELETE.
	JSR	PC,CINSET		;DECODE A.  MAYBE POPJ OR JUMP TO CLEOL.
					;OTHERWISE, PUSH ON STACK A, LELCC(U), #LINHT, LECC(U).
CDELL:	MOV	6(SP),A
	MOV	(SP),T
	MOV	4(SP),C
	JSR	PC,CDEL1L
	ADD	#BYTPL,(SP)
	ADD	#BYTPL,4(SP)
	DEC	2(SP)
	BNE	CDELL
	ADD	#10,SP
	MOVB	#CIOR,CALU
CDELX:	RTS	PC

;DELETE C(A) CHARACTER POSITIONS FROM ONE RASTER LINE
;T POINTS AT WORD CONTAINING CURSOR, IN THAT RASTER LINE.
;C POINTS AT START OF THAT RASTER LINE.  ASSUMES CALU/ CSET.
CDEL1L:	MOV	A,MQ
	MOV	#CHRWD,MUL		;COMPUTE # OF BITS TO SHIFT THE LINE BY.
	MOV	#20,DIV			;COMPUTE # WORDS TO SHIFT IN MQ, # BITS IN AC.
	MOV	#20-CHRWD,TT
	SUB	LEPHS(U),TT		;TT GETS # BITS AT FRONT OF 1ST WORD NOT TO CHANGE.
	PUSH	TT
	PUSH	(T)			;ALSO SAVE THE WORD CONTAINING THEM.
	PUSH	T			;AND ITS ADDRESS
	MOV	T,TT			;(WHICH IS ALSO ADDR TO START SHIFTING INTO).
	ADD	MQ,TT			;AND ADDR TO START SHIFTING FROM, AND 1ST FROM-WORD.
	ADD	MQ,TT			;MQ HAS # OF WORDS, BUT TT HAS AN ADDRESS.
	MOV	(TT)+,A
	ADD	#BYTPL,C		;C GETS ADDR OF 1ST WORD PAST END OF LINE.
	PUSH	U
	MOV	AC,U			;U HAS # BITS SHIFTING BY.
;NOW MAKE TO-WORDS 1 BY 1 EACH OUT OF A PAIR OF FROM-WORDS.
;THE LAST FROM-WORD IS IN A.  T HAS STORE ADDRESS, TT HAS FETCH ADDRESS.
CDEL1:	CMP	C,TT			;STOP AFTER GOBBLING ALL OF THIS RASTER LINE.
	BLOS	CDEL2
	MOV	(TT)+,B
	MOV	B,MQ			;CLOBBERS AC, SO RELOAD IT FROM T.
	MOV	A,AC
	MOV	U,LSH			;NOW SHIFT THE 2 FROM-WORDS BY # BITS SHIFTING BY,
	MOV	AC,(T)+			;WHICH GIVES AC THE RIGHT STUFF FOR NEXT TO-WORD.
	MOV	B,A			;NOW T GETS THE NEWEST FROM-WORD, AND FETCH ANOTHER.
	BR	CDEL1

CDEL2:	MOV	A,MQ			;REMAINDER OF LAST FROM-WORD IS NEXT TO-WORD.
	MOV	U,LSH
	MOV	MQ,(T)+
	JSR	PC,CLRRNG		;CLEAR STARTING WHERE T POINTS, ENDING WHERE C POINTS.
;NOW RESTORE THE FIRST FEW BITS OF THE FIRST WORD (WHICH WEREN'T SUPPOSED
;TO BE INCLUDED IN THE SHIFT).
CINS2:	POP	U
	POP	C			;GET ADDRESS OF 1ST TO-WORD
	POP	A			;GET OLD 1ST TO-WORD CONTENTS
	POP	T			;AND NUMBER OF BITS AT TOP NOT TO INCLUDE IN SHIFT.
	MOV	#-1,AC
	NEG	T
	MOV	T,LSH			;MQ GETS MASK TO BITS WE WANT SHIFTED INTO.
	MOV	AC,T
	BIC	T,A			;FLUSH THOSE IN SAVED CONTENTS.
	COM	T
	BIC	T,(C)			;FLUSH THE OTHERS IN SHIFTED CONTENTS.
	BIS	A,(C)			;MERGE OLD BITS WITH NEW.
	RTS	PC

CLRRN1:	CLR	(T)+
CLRRNG:	CMP	T,C
	BNE	CLRRN1
	RTS	PC

;CLEARS TO END OF LINE

CLEOL:	PUSH	LECC(U)
	PUSH	LEPHS(U)
	PUSH	LEX(U)
	JSR	PC,CLEOL1	;DO THE DIRTY WORK
CLEOX:	POP	LEX(U)
	POP	LEPHS(U)
	POP	LECC(U)
	MOVB	#CIOR,CALU	;RESTORE FOR DPYDP1 LOOP
	RTS	PC

CLEOL1:	MOV	LEX(U),TT	;ALREADY AT END OF LINE?
	BGE	CLEOLX
	CMP	LEPHS(U),#20-CHRWD
	BEQ	CLEOL2		;IF AT START OF WORD, START CLEARING WORD-WISE
	JSR	PC,CLRCHR	;ELSE CLEAR 1 CHAR AT A TIME TILL REACH WORD BOUNDARY.
	JSR	PC,LEDADC
	CMP	LEX(U),#-BITPL
	BEQ	CLEOLX		;CLEARED WHOLE LINE AND WRAPPED AROUND => DONE
	BR	CLEOL1

CLEOL2:	ASR	TT
	ASR	TT
	ASR	TT
	ASR	TT		;-(# WORDS TO CLEAR)
	PUSH	TT
	PUSH	LECC(U)		;ADDR OF 1ST WORD TO CLEAR,
	PUSH	#LINHT		;# LINES TO PROCESS
	MOVB	#CSET,CALU
CLEOL3:	MOV	2(SP),T		;START CLEARING HERE
CLEOL4:	CLR	(T)+
	INC	TT
	BLT	CLEOL4
	ADD	#BYTPL,2(SP)
	MOV	4(SP),TT	;-(# WORDS TO CLEAR)
	DEC	(SP)
	BGT	CLEOL3
	ADD	#6,SP		;CLEANSE STACK
	MOV	T,LECC(U)
	JMP	CR1		;RESET X AND PHASE

CLEOLX:	MOV	LELCC(U),T
	ADD	#<LINHT*BYTPL>,T	;HERE IF ALREADY AT END OF LINE
	MOV	T,LECC(U)
	JMP	CR1

;CLEARS TO END OF SCREEN

CLEOF:	MOV	LELCC(U),T		;IF AT START OF LINE, DO FAST CLEAR FROM THIS LINE.
	CMP	#-BYTPL,LEX(U)		;IF NOT AT BEGINNING OF LINE, USE CLEOL TO CLEAR
	BEQ	CLEOF1			;ONLY THE REST OF THIS LINE.
	JSR	PC,CLEOL
	MOV	LELCC(U),T		;AND START FAST CLEAR WITH NEXT LINE.
	ADD	#BYTPL*LINHT,T
CLEOF1:	MOV	#TVFENCE,B
	JMP	LDEL5

;HERE TO FORWARD SPACE

FS:	JMP	LEDADC

;HANDLE %TDMOV
SETCUR:	JSR	PC,GETCHC	;OLD VERTICAL AND HORIZONTAL
	JSR	PC,GETCHC

;HANDLE %TDMV0, %TDMV1  ABSOLUTE POSITIONING COMMANDS.
SETCR1:	JSR	PC,GETCHC	;NEW VERTICAL
	MOV	A,B
	JSR	PC,GETCHC	;NEW HORIZONTAL
				;NOTE GETCHC MAY RETURN AND BE REENTERED,
				;RESETTING ALL ACS BUT B.

;HERE TO SET CURSOR GIVEN A COORDINATE PAIR (X,Y) IN CHARACTERS.
;X AND Y ARE IN A AND B RESPECTIVELY, (0,0) IS UPPER LEFTHAND CORNER
;(1,3) IS THE SECOND CHARACTER OF FOURTH LINE

SETXY:	CMP	#CHRPL,A		;CHECK FOR LEGAL POSITION
	BLOS	SETXY1
	CMP	#CHRLN,B
	BLOS	SETXY1
SETXY0:	MOV	#MQ,T			;FOR THE MYRIAD MULTIPLIES AND DIVIDES
	MOV	B,(T)+			;Y POSITION
	MOV	#BYTPL*LINHT,(T)	;FIND ORIGIN OF LINE IN MEMORY
	MOV	-(T),LECC(U)
	MOV	(T),LELCC(U)
	MOV	A,(T)+			;X POSITION
	MOV	#CHRWD,(T)
	MOV	-(T),LEX(U)		;BITS FROM LEFT OF SCREEN
	CLR	-(T)			;CLEAR OUT AC
	MOV	#20,-(T)		;DIVIDE GIVES WORDS FROM LEFT AND PHASE
	TST	(T)+
	MOV	(T)+,LEPHS(U)		;PHASE
	ASL	(T)			;BYTES FROM BEGIN OF LINE
	ADD	(T),LECC(U)		;LEAVE T POINTING AT MQ
	ADD	#-BITPL,LEX(U)		;THAT'S ALL DONE
	NEG	LEPHS(U)
	ADD	#20-CHRWD,LEPHS(U)	;PHASE IS SET
	MOV	B,(T)+			;Y POSITION AGAIN
	MOV	#LINHT,(T)
	MOV	-(T),LEY(U)
	ADD	#-NLINS,LEY(U)		;LEY SET
	ADD	#TVLO,LECC(U)
	ADD	#TVLO,LELCC(U)
	BIT	#1,LECC(U)		;MAKE SURE IT LINES UP ON WORD BOUNDARY
	BEQ	.+4
	BPT
SETXY1:	RTS	PC

;OUTSTR TAKES STRING TO PRINT IN B

OUTSTR:
OUTS1:	MOVB	@(SP),A
	INC	(SP)
	TST	A
	BEQ	OUTSX
	CMP	#12,A
	BEQ	OUTSLF
	CMP	#15,A
	BEQ	OUTSCR
	JSR	PC,TVO
	BR	OUTS1
OUTSLF:	JSR	PC,LF
	BR	OUTS1
OUTSCR:	JSR	PC,CR
	BR	OUTS1
OUTSX:	ASR	(SP)	;MAKE SURE WE RETURN TO EVEN ADDRESS
	ADC	(SP)
	ASL	(SP)
	RTS	PC

;TAKES # IN A AND PRINTS AS UNSIGNED INTEGER

OCTPNT:	PUSH	RADIX
	MOV	#10,RADIX
OCTPN1:	JSR	PC,DECPN0
	POP	RADIX
	RTS	PC

DECPNT:	PUSH	RADIX
	MOV	#10.,RADIX	;FOR DECIMAL PRINTING
	BR	OCTPN1

DECPN0:	MOV	A,MQ		;INTO EAE
DECPN9:	MOV	#AC,A		;FOR FAST ACCESS
DECPN1:	MOV	RADIX,-(A)	;DIVIDE BY RADIX
	TST	(A)+		;POINTS AT AC
	MOV	(A)+,-(SP)	;REMAINDER
	ADD	#'0,(SP)
	TST 	(A)		;QUOTIENT IS IN MQ
	BEQ	DECPN2
	CLR	-(A)		;FLUSH OUT AC, LEAVING MQ UNTOUCHED
	JSR	PC,DECPN1	;RECURSIVE YET!
DECPN2:	POP	A		;TYPE OUT THAT DIGIT
	JMP	TVO		;TYPES DIGIT AND ADVANCES CURSOR

.SBTTL CALL, BREAK AND ESCAPE ROUTINES

;LEGAL ESCAPE AND BREAK COMMAND TABLE

ESCHAR:	.BYTE '0,'1,'2,'3,'4,'5,'6,'7,'8,'9	;DON'T DISTURB DIGITS
	.BYTE 'S,'Q,'F,'D,'A,'E			;THESE CAN BE DONE ON ANY KBD
ESCSRN:	.BYTE 'C,'L,'I,'R,'W,'U			;THESE NEED A SCREEN TO WIN
NESCMD==.-ESCHAR
	.BYTE 0					;MARKS END OF TABLE
	.EVEN

;DISPATCH TABLE

ESCTAB:	.REPT 10.
	.NLIST
	ESCDIG		;DIGIT
	.LIST
	.ENDR
	VSWSEL		;<S> SELECT VIDEO CHANNEL
	ESCQPY		;<Q> CAUSE A HARD COPY TO EXIST
	ESCFRE		;<F> SAME AS S, BUT TO CONSOLE FREE BUFFER
	ESCBUZ		;<D> BUZZ 9TH FLOOR DOOR
	ESCAUD		;<A> SELECT AUDIO INPUT.
	ESCELE		;<E> CALL THE ELEVATOR
CHECK ESCTAB,<<ESCSRN-ESCHAR>*2>
	BOWXOR		;<C> TOGGLE BLACK ON WHITE BIT
	ESCCLR		;<L> CLEAR SCREEN UNBEKNOWNST TO TEN.
	ESCCSR		;<I> CLEAR SCROLL REGISTER
	ESCRPT		;<R> START REPEATING THE PREV. CHAR TYPED IN.
	ESCWHO		;<W> WHO LINE CONTROL
	ESCWHO		;<U> WHO LINE CONTROL
CHECK ESCTAB,NESCMD*2

;HERE FOR ESCAPE

ESCAPE:	BIT	#ACLBIT+AMTBIT,B
	BEQ	ESCAP1		;ESCAPE WITH CONTROL OR META TURNS INTO TOP-A.
	JMP	BRKCLR

ESCAP1:	MOVB	A,KBDESC(C)	;SAY FOLLOWING CHARS TO BE INTERPRETED AS AN ESCAPE CMD.
	CLRB	KBDARG(C)	;DEFAULT ARG TO ZERO
RTSPC4:	RTS	PC

;ACCUMULATE ARGS FOR ESCAPE AND BREAK

ESCDIG:	ASR	T		;DIGIT
	MOVB	KBDARG(C),A	;MULTIPLY ACCUMULATED VALUE BY 8
	ASL	A
	ASL	A
	ASL	A
	ADD	T,A		;ADD IN NEW DIGIT
	MOVB	A,KBDARG(C)
	INCB	KBDESC(C)	;READ NEXT CHAR AS A COMMAND CHAR, NOT AS PDP-10 INPUT.
	RTS	PC

;TAKES CHARACTER IN A AND CONVERTS IT UPPER CASE

UPPER:	TST	A		;MAKE SURE ITS LEGAL ASCII
	BLE	UPPER1
	CMP	#'a,A		;LOWER CASE?
	BGT	UPPER1
	CMP	#'z,A
	BLT	UPPER1
	SUB	#'a-'A,A	;MAKE IT UPPER CASE
UPPER1:	RTS	PC

;HANDLE ESCAPE-R.  WITH NO ARG, STARTS INDEFINITE REPETITION OF LAST CHARACTER TYPED.
;WITH ARG, STOPS AFTER THAT MANY REPETITIONS.  IN ANY CASE, ANY USER-SUPPLIED
;INPUT STOPS THE REPETITION.
ESCRPT:	MOVB KBDARG(C),A
	BNE ESCRP1
	DEC A
ESCRP1:	MOV A,LERPT(U)
	RTS PC

;HERE TO SELECT VIDEO SWITCH INPUT.
;C HAS 2*KBD NUMBER; KBDARG(C) HAS VSW INPUT # OR 0 => DEFAULT.

VSWSEL:	JSR	PC,VSWSGO	;SET UP L.E. IDX IN U, VSW OUTPUT IN T.
	BLT	RTSPC4
	MOV	#-1,KBDDEF(C)	;NORMALLY RESET ANY TIME-OUT, BUT
	TSTB	KBDARG(C)	;IF THERE'S AN ARGUMENT,
	BEQ	VSWSL0
	TST	U
	BNE	VSWSL0
	JSR	PC,VSWSL3	;SET UP A TIMEOUT, IF WE ARE A FREE SCREEN.
VSWSL0:	MOVB	KBDARG(C),TT	;GET ARG
	BNE	VSWSL1		;SELECT DEFAULT?

;SELECT THE DEFAULT INPUT FOR A KEYBOARD.
;C HAS 2*KBD #, U HAS L.E. IDX OR 0 IF NONE, T HAS DEFAULT VSW OUTPUT OF THAT KBD.
VSWDEF:	MOV	#-1,KBDDEF(C)	;SAY THERE'S NO TIMEOUT ON THIS VSW SELECTION.
	TST	U		;FREE SCREEN => DEFAULT IS THE FREE DPY BUFFER.
	BEQ	VSWFRE
	MOVB	LECREG(U),TT	;GET DPY # TO SET DEFAULT
	BLT	RTSPC4		;GARBAGE?
;COME HERE WITH DPY BUFFER # IN TT, TO SELECT THAT DPY BUFFER.
VSWDE1:	ASL	TT
	MOV	DPYVSW(TT),TT	;DEFAULT VIDEO SWITCH INPUT
	JMP	VSWIT		;DON'T NEED TO CHECK THIS

;COME HERE FOR [ESC]<N>S, WITH <N> IN TT.
VSWSL1:	BIC	#-400,TT	;UNDO SIGN-EXTENSION AT VSWSL0
	CMP	TT,NF11TY
	BLO	VSWSL2		;<N> TOO SMALL TO BE TTY # => IT IS VSW INPUT #.
	CMP	TT,#200
	BHIS	VSWSL4		;<N> >= 200 => IT IS DPY BUFFER # PLUS 200.
	TST	NF11TY		;IF NF11TY ISN'T KNOWN, VSW INPUT #S LOOK LIKE TTY #S
	BEQ	VSWSL2		;BUT WE ARE EVEN SMARTER AND KNOW IT'S REALLY VSW INPUT.
	SUB	NF11TY,TT	;ELSE <N> SHOULD BE TTY NUMBER
	CMP	TT,#MAXTV
	BHIS	RTSPC4		;DO NOTHING IF ARG OUT OF RANGE.
	ASL	TT
	ASL	TT
	MOVB	DPYKBD+1(TT),TT	;GET DPY BUFFER # FOR THIS TV, AND SELECT THAT DPY BUFFER.
	BMI	RTSPC4
	BR	VSWDE1

VSWSL4:	SUB	#200,TT		;TT SUPPOSEDLY HAS 200 PLUS DPY BUFFER NUMBER.
	CMP	TT,#MAXTV
	BLO	VSWDE1
	BR	RTSPC4

;COME HERE TO HANDLE SET-VSW COMMAND FROM PDP10. T HAS OUTPUT #, TT HAS INPUT #.
;IF THEY ARE ILLEGAL WE DO NOTHING.
;ON RETURN, BLO JUMPS IF THEY WERE LEGAL.
VSWCMD:	MOV	#-1,KBDDEF(C)	;FLUSH ANY TIME-OUT.
	CMP	T,#MAXVSO	;CHECK FOR LEGAL OUTPUT
	BHIS	RTSPC4
;COME HERE WITH VALID OUTPUT # IN T, AND (MAYBE INVALID) INPUT # IN TT.
VSWSL2:	CMP	TT,#MAXVSI*VSWSEC
	BHIS	RTSPC4		;REASONABLE?
	JMP	VSWIT		;SWITCH THE SWITCH

ESCFRE:	JSR	PC,VSWSGO	;SET UP U AND T FOR VSWDE1.
	BLT	RTSPC5
	JSR	PC,VSWSL3	;THERE IS A TIMEOUT ON THIS SPYING.
VSWFRE:	MOV	DPYFRE,TT	;GET DPY # OF FREE CONSOLE SCREEN
	BR	VSWDE1

;SET UP A TIMEOUT WHEN A SPY IS ABOUT TO BE DONE. C HAS 2*KBD.
VSWSL3:	MOVB	#KBDTIM,KBDCNT(C)	;SET UP A TIMEOUT ON THIS KEYBOARD.
	INC	KBDTSW		;TELL CLOCK LEVEL TO START CHECKING TIMEOUTS.
	RTS	PC

;SET UP U := L.E. IDX, OR 0 IF NONE; T HAS DEFAULT VSW OUTPUT; GIVEN 2*KBD # IN C
;NEGATIVE IF SOMETHING FUNNY IS GOING ON, AND CALLER SHOULDN'T HACK.
VSWSGO:	MOV	KBDLE(C),U
	BLT	RTSPC5		;THIS IF TEN SELECTS NON-EXISTENT VSW OUTPUT.
	BEQ	VSWSG1
	TST	LEKBD(U)
	BLT	RTSPC5
VSWSG1:	MOV	C,T
	ASR	T
	MOVB	KBDVSW(T),T
	RTS	PC

;DO [ESC]S ON KBD SPEC'D BY 2*KBD IN C.
VSWUNS:	JSR	PC,VSWSGO
	BLT	RTSPC5
	JMP	VSWDEF


;HANDLE [ESC] <ASW INPUT> A.
ESCAUD:	MOVB	KBDARG(C),TT		;ASW INPUT NUMBER.
	MOV	C,T
	ASR	T			;KEYBOARD NUMBER.
	MOVB	KBDASW(T),T		;OUTPUT NUMBER OF KEYBOARD.
	BMI	RTSPC5			;WE DON'T KNOW YET OR IT HAS NO SPEAKER.
	JMP	ASWIT			;CONNECT THEM.

;CHANGE STATE OF BOW BIT

BOWXOR:	MOVB	#CXOR,CALU
	MOV	#BOWBIT,CSA
	RTS	PC

;HERE TO CLEAR SCREEN

ESCCLR:	MOVB	CREG,T		;THE SCREEN TO CLEAR
	PUSH	T

	BLKOFF	T
	JSR	PC,CLBLIN	;CLEAR ALL BLINKERS
	JSR	PC,CLRSCR	;CLEAR THE SCREEN
	POP	T
	BLKON	T

	RTS	PC

;HERE TO RESET SCROLL REGISTER

ESCCSR:	MOVB #CSET,CALU
	BIC #SAMSK,CSA	;RESET THE SCROLL REGISTER
	RTS PC

;HERE TO GENERATE VIDEO HARD COPY

ESCQPY:	TST	QPYSWT		;IS THE SWITCH LOCKED?
	BNE	ESCQPB
	TST	QPYDWN		;IS THE QPY DOWN?
	BNE	ESCQPB
ESCQP1:	MOV	KBDLE(C),U
	BEQ	ESCQP6
	TST	LEKBD(U)
	BLT	RTSPC5
ESCQP6:	MOV	#QPYVSW,T	;THE VIDEO SWITCH OUTPUT FOR THE HARD COPY UNIT
	JSR	PC,VSWSL0	;PROCESS THE ARG
	CHROFF
	ZAPFLG	QPYSWT		;LOCK THE SWITCH
	BIS	#QPYKMS,KMS	;CAUSE THE COPY
	JSR	TT,ADQUE	;SCHEDULE THE UNCOPY
		2
		ESCQP2
	MOV	CREG,T
	JSR	TT,ADQUE	;SCHEDULE THE SWITCH UNLOCK
		QPTIME
		ESCQP3
RTSON:	CHRON
RTSPC5:	RTS	PC

ESCQPB:	JMP	BELL		;SOME ONE ELSE IS COPYING, GIVE HIM A BELL

ESCQP2:	BIC	#QPYKMS,KMS	;UNCAUSE THE COPY
	RTS	PC

ESCQP3:	JSR	PC,CLKBEL	;BELL WHEN COPY DONE
	CLR	QPYSWT
	RTS	PC

;HERE TO BUZZ 9TH FLOOR DOOR
ESCBUZ:	TST	BUZSWT		;IS THE SWITCH LOCKED?
	BEQ	ESCBZ1
	JMP	BELL
ESCBZ1:	CHROFF
	ZAPFLG	BUZSWT		;LOCK SWITCH
	BIS	#BUZKMS,KMS	;BUZZ THE DOOR
	MOV	CREG,T
	JSR	TT,ADQUE	;SCHEDULE THE UNBUZZ
		BUZTIM
		ESCBZ2
	BR	RTSON

ESCBZ2:	JSR	PC,CLKBEL	;BELL WHEN BUZZ DONE
	BIC	#BUZKMS,KMS	;UNBUZZ THE DOOR
	CLR	BUZSWT		;UNLOCK THE SWITCH
	RTS	PC

;HERE TO CALL THE ELEVATOR
; C HAS 2*KBD NUMBER

ESCELE:	TST	ELESWT		;IS THE SWITCH LOCKED?
	BEQ	ESCEL1
	JMP	BELL
ESCEL1:	CHROFF
	ZAPFLG	ELESWT		;LOCK SWITCH
	MOV	C,T
	ASR	T		;DEVIDE BY 2
	CMP	T,#MAXVSO	;IS IT IN RANGE?
	BHIS	RTSON
	MOVB    ELETAB(T),TT	;WHICH FLOOR IS IT ON?
	SWAB	TT		;GET CONSTANT INTO THE LEFT HALF WORD
	BIS	TT,KMS		;FROB THE CORRECT BIT
	MOV	CREG,T
	JSR	TT,ADQUE	;SCHEDULE THE UNPUSH
		ELETIM
		ESCEL2
	BR	RTSON


ESCEL2:	JSR	PC,CLKBEL	;BELL WHEN DONE
	BIC	#ELEKMS,KMS	;UNPRESS
	CLR	ELESWT		;UNLOCK THE SWITCH
	RTS	PC



CLKBEL:	PUSH	CREG		;FOR USE BY CLOCK QUEUED ROUTINES
	MOV	(T),CREG	;T POINTS TO DESIRED CREG
	PUSH	TT		;DON'T CLOBBER AT PI LEVEL!!
	JSR	PC,BELL
	POP	TT
	POP	CREG
	RTS	PC

;HERE TO CONTROL WHO LINE

;	  [ESC]<N>W		      WHMODE
;	N=0	TURN OFF WHO LINE      -1
;	  1	FOLLOW KEYBORAD		0
;	  2	FREEZE			1
;	  3	NEXT HIGHER		2
;	  4	NEXT LOWER		3
;ALL OTHERS	SYSTEM WHO LINE

;	  [ESC]<N>U
;FREEZES WHOLINE ON JOB WHOSE USER INDEX IS N*L (L IS THE ITS SYMBOL).

NWHCMD==5	;NUMBER OF WHO COMMANDS

ESCWHO:	MOV	LECHN(U),TT	;10/11 CHANNEL
	ASL	TT		;MAKE IT CHANNEL INDEX
	ASL	TT
	MOV	WHOLIN(TT),TT	;WHO LINE VARIABLES
	CMPB	A,#'U
	BEQ	ESCWHU
	MOVB	KBDARG(C),T	;ARGUMENT
	DEC	T		;HACK
	BMI	ESCWH2		;TURN IT OFF?
	MOV	T,WHMODE(TT)	;SET THE MODE WE WANT
ESCWU1:	CLR	WHMOD1(TT)	;JUST TO BE SURE
	MOV	#-1,TENWHO	;TELL PDP-10 TO UPDATE WHO LINES
	RTS	PC

;TURNS OFF WHO LINE

ESCWH2:	;CLEAR WHO LINE AT MAIN PROGRAM LEVEL TOO
	MOV	T,2(TT)		;(T HAS -1 IN IT)
	MOV	T,WHMODE(TT)	;AND TURN IT OFF
	BR	CLRWHL

ZAPWHL:	MOV	DPYCHN(B),A	;SET UP CREG
	MOVB	LECREG(A),CREG
CLRWHL:	MOV	#TVLO+<LINHT*CHRLN*BYTPL>,T
	MOV	#CHRHT-1,TT
	JMP	CLRCL0

ESCWHU:	MOV	#1,WHMODE(TT)
	MOVB	KBDARG(C),WHJOB(TT)
	CLR	WHJOB1(TT)
	BR	ESCWU1

;COME HERE FOR CALL KEY

CALL:	PUSH	B
	TSTB	KBDCNT(C)
	BLT	CALL1
	JSR	PC,VSWUNS	;IF DOING A SPY WITH A TIMEOUT, UNDO IT.
CALL1:	MOV	KBDLE(C),U	;LINE EDITOR VARIABLES
	BNE	UPTREE		;GET FRESH LINE EDITOR?
	ASR	C
	JSR	PC,CHCONS	;ALLOCATE A CHANNEL.
;T HAS CHANNEL NUMBER.  U HAS LINE EDITOR ADDR.  A HAS WHOLINE VAR BLOCK ADDR.
	TST	T		;-1 RETURNED AS CHANNEL # => NONE AVAILABLE.
	BLT	CALLLS
	MOVB	LECREG(U),CREG
	CLR	CSA		;CLRSCR SETS UP CALU

;HERE IF CALL AND LINE EDITOR EXISTS.

UPTREE:	POP	B
	CLR	LERPT(U)
	MOV	#32,A		;CONTROL-Z (SIGH)
	BIS	#ACTBIT,B	;ACTIVATES BUFFER
	JMP	PUTCHR		;SEND THAT CHARACTER TO PDP-10

CALLLS:	POP	B
RTSPC2:	RTS	PC

;HERE TO ALLOCATE A DISPLAY CHANNEL.
;CALLED WITH KEYBOARD NUMBER IN C, OR -1 IF NOT ALLOCATING THIS DPY FOR A KEYBOARD.
;RETURNS THE CHANNEL NUMBER (TTY NUMBER MINUS NF11TY) IN T,
;THE LINE EDITOR BLOCK ADDR IN U,
;AND THE ADDRESS OF THE WHOLINE VARIABLE BLOCK IN A.  SETS WHMODE TO 0.
;IF NO CHANNEL IS AVAILABLE, OR THE KEYBOARD CAN'T BE USED FOR SOME REASON,
;WE RETURN -1 IN T TO INDICATE THAT.

CHCONS:	MOV	C,T		;IF A KEYBOARD IS SPECIFIED,
	BLT	CHCON4
	TSTB	KBDVSW(C)	;DON'T ALLOW IT IF KEYBOARD HAS NO SCREEN
	BLT	CHCNFL
	ASL	T
	TST	KBDLE(T)	;OR IS ALREADY IN USE.
	BNE	CHCNFL
CHCON4:	CLR	T		;NOW FIND A FREE CHANNEL
CHCON1:	TSTB	CHCREG(T)	;DON'T ALLOCATE CHANNELS THAT DON'T HAVE BUFFERS.
	BLT	CHCON0
	TSTB	CHNUSE(T)
	BEQ	CHCON2
CHCON0:	INC	T
	CMP	T,#MAXTV
	BLT	CHCON1
CHCNFL:	MOV	#-1,T
	RTS	PC		;NO FREE CHANNEL

CHCON2:	INCB	CHNUSE(T)	;FOUND A CHANNEL.  MARK IT IN USE.
	DEC	ITSFDP		;DECREASE COUNT OF FREE CHANNELS.
	MOVB	CHCREG(T),A
	PUSH	A		;SAVE VIDEO BUFFER NUMBER FOR POPPING INTO LECREG
	MOVB	A,CREG		;SELECT THAT BUFFER
	PUSH	T		;PROTECT T, SMASHED BY CLRSCR (TT ALSO SMASHED)
	JSR	PC,CLRSCR	;AND CLEAR IT (SLOW, BUT NECESSARY BEFORE SWITCHING VSW)
	POP	T
	MOV	T,A
	ASL	A
	ASL	A
	MOV	DPYCHN(A),U	;GET THE ADDR OF CHANNEL'S VAR BLOCK.
	JSR	PC,CHCLR	;PUT -1'S IN THE 10-TO-11 BUFFER, RESET POINTERS.
	JSR	PC,LECON2	;INITIALIZE THE LINE EDITOR BLOCK.
	MOVB	(SP),DPYKBD+1(A)	;TELL THE 10 WHICH TV BUFFER.
	POP	LECREG(U)	;TELL THE LINE EDITOR WHICH TV BUFFER IT IS.
	MOV	C,LEKBD(U)	;AND WHICH KEYBOARD IT IS.
	BLT	CHCON3
	MOV	C,CHNCLS(A)	;TELL THE 10 ABOUT THE KEYBOARD.
	CLRB	CHNCLS+1(A)	;MAKE SURE CHNCLS IS NON-NEGATIVE EVEN IF KBD WAS -1
	MOVB	C,DPYKBD(A)
	MOV	T,LECHN(U)	;TELL LE WHICH DPY CHANNEL NUMBER IT IS
	PUSH	T		;SHOW OUR DPY BUFFER ON THE KBD'S SCREEN.
	MOVB	KBDVSW(C),T	;VIDEO SWITCH OUTPUT
	MOVB	LECREG(U),B
	ASL	B
	MOV	DPYVSW(B),TT	;GET OUR DPY'S VIDEO INPUT NUMBER.
	JSR	PC,VSWIT	;SWITCH THE SWITCH
	MOV	FBLINK,T	;CONS UP A BLINKER FOR THE CURSOR
	BNE	.+4		;ARE THERE FREE BLINKERS?
	BPT

	MOV	BLNEXT(T),FBLINK
	MOV	BLINKS(B),BLNEXT(T)
	MOV	T,BLINKS(B)	;THE BLINKER
	MOV	U,BLCURS(T)	;FOLLOW PAGE PRINTER
	CLRB	BLON(T)		;BLON

	POP	T
	ASL	C		;MAKE THE KEYBOARD AND THIS LINE EDITOR POINT AT EACH OTHER.
	MOV	U,KBDLE(C)
CHCON3:	PUSH	WHOLIN(A)
	PUSH	T
	MOV	T,TT
	MOV	LEBUF(U),T
	JSR	PC,CLRING	;CLEAR THE 11-TO-10 INPUT BUFFER RING.
	POP	T
	POP	A
	MOV	#0,WHMODE(A)
	RTS	PC

;CLEAR OUT THE 10-TO-11 BUFFER WHICH U POINTS AT.

CHCLR:	MOV	DPY10B(U),TT	;POINTER TO START OF BUFFER
	MOV	TT,DPY11B(U)	;RESET OUR POINTER INTO THE CHANNEL'S BUFFER.
	INC	DPY11B(U)	;MAKE POINT AT 1ST BYTE IN PDP10 ORDER!
CHCLR1:	MOV	#-1,(TT)+
	CMP	TT,DPYLGL(U)
	BLOS	CHCLR1
	RTS	PC

;HERE TO INITIALIZE MOST OF THE WORDS OF A LINE EDITOR BLOCK,
;AND GET A RING OF KEYBOARD BUFFERS FOR IT.
LECON2:	PUSH	T
	PUSH	U
	MOV	U,TT		;SET DEFAULTS
	ADD	#DPSIZE+DPDATA,TT
	MOV	#LEDFLT+DPSIZE+DPDATA,T
	MOV	#LELEN-DPSIZE-DPDATA,U
	JSR	PC,CALCPY	;DEFAULT IS FOR FREE VARIABLES
	POP	U
	MOV	FSP,T		;FIRST FREE BUFFER
	BEQ	LECON3
	MOV	LHFS(T),TT	;NEXT BUFFER
	BEQ	LECON3
	MOV	LHFS(TT),FSP	;TAKE THOSE TWO
	MOV	T,LHNEXT(TT)
	MOV	TT,LHNEXT(T)	;ALL NICE AND COZY
	MOV	T,LEBUF(U)	;POINTER TO RING
	ADD	#LHLEN,T
	MOV	T,LECHR(U)	;BUFFER ACCESS POINTER
	POP	T
	RTS	PC

LECON3:	BPT		;NO 11-TO-10 BUFFERS AVAILABLE FOR A RING?

;CLEARS HEADERS OF BUFFER RING, CALLED WITH RING IN T, CHN# IN TT

CLRING:	PUSH	T
CLRNG1:	CLR	(T)+	.SEE LHFLAG
	CLR	(T)+	.SEE LHZERO
	TST	(T)+	.SEE LHNEXT
	CLR	(T)+	.SEE LHALST
	CLR	2(T)	.SEE LHFS
	CLR	4(T)	.SEE LHQUED
	MOV	TT,(T)	.SEE LHCHN
	TST	-(T)	.SEE LHALST
	MOV	-(T),T	;.SEE LHNEXT COMMENT THIS OUT DUE TO PALX BRAIN DAMAGE
	CMP	(SP),T
	BNE	CLRNG1
	POP	T
	RTS	PC

;HERE TO COPY A BLOCK OF CORE
:	 T SOURCE
;	TT DESTINATION
;	 U BYTE COUNT (ONLY EVEN NUMBERS WILL WORK)

CALCPY:	INC	U		;MAKE A WORD COUNT
	ASR	U
CALCP1:	MOV	(T)+,(TT)+
	DEC	U
	BGT	CALCP1
	RTS	PC

;HERE TO RETURN DPY CHANNEL.  T HAS CHANNEL NUMBER.

CHRETN:	TST	T		;DON'T RETURN CHANNEL 0.
	BEQ	CHRET0
	DECB	CHNUSE(T)	;MARK THE CHANNEL AS NOT IN USE
	BGE	.+4
	 BPT
	INC	ITSFDP		;AND INCLUDE IT IN THE COUNT OF FREE CHANNELS.
	BR	CHRET1

CHRET0:	MOV	#377,CHNCLS	;IF FREEING THE FREE TV DISPLAY, DON'T REALLY FREE IT
CHRET1:	ASL	T
	ASL	T
	MOV	DPYCHN(T),U
	JSR	PC,CHCLR	;RESET THE 10-TO-11 BUFFER AND POINTERS.
	TST	T
	BEQ	CHRETX		;DON'T RETURN CHANNEL 0 (FREE CONSOLE DISPLAY)
	MOV	#-1,DPYKBD(T)	;TELL THE PDP-10 WE'RE LOGGING OUT
	MOV	WHOLIN(T),TT
	MOV	#-1,WHMODE(TT)	;TURN OFF WHO-LINE GENERATION ON THIS CHANNEL.

;HERE TO FREE THE 11-TO-10 INPUT BUFFERS, AND MARK THE KEYBOARD AND CHANNEL
;AS DISCONNECTED.  ALSO FREE THE BLINKERS.
LERETN:	CLR	LERPT(U)
	MOV	LEBUF(U),T	;RETURN BUFERS IN RING
	BEQ	LERT2A		;BUFFERS TO RETURN?
	PUSH	T
LERET1:	MOV	LHNEXT(T),LHFS(T)
	CMP	LHFS(T),(SP)
	BEQ	LERET2
	MOV	LHFS(T),T
	BR	LERET1
LERET2:	MOV	FSP,LHFS(T)	;CUT RING, PATCH ON TO FREE LIST
	POP	FSP
	CLR	LEBUF(U)	;MARK AS FREE
LERT2A:	MOV	LEKBD(U),T
	BLT	LERT2B		;A KEYBOARD?
	ASL	T		;BYTES
	CLR	KBDLE(T)
	ASR	T
	MOVB	KBDVSW(T),T	;VSW THE OUTPUT
	BLT	LERT2B
	MOV	DPYFRE,TT	;MESSAGE DPY
	ASL	TT		;BYTES
	MOV	DPYVSW(TT),TT
	JSR	PC,VSWIT	;GIVE HIM THE CONSOLE FREE MESSAGE
LERT2B:	MOVB	LECREG(U),T	;RETURN ALL THE BLINKERS
	BLT	LERET5		;A DPY?
	MOVB	#-1,LECREG(U)	;INVALIDATE DPY #
	ASL	T
	TST	BELCNT(T)	;ANY BELLS PENDING?
	BMI	LERET6
	CLR	BELCNT(T)	;THE NEXT FLASH WILL BE THE LAST
LERET6:	MOV	BLINKS(T),TT	;RETURN THIS DISPLAY'S BLINKERS TO FREE LIST.
	BEQ	LERET5
LERET3:	TST	BLNEXT(TT)
	BEQ	LERET4
	MOV	BLNEXT(TT),TT
	BR	LERET3
LERET4:	MOV	FBLINK,BLNEXT(TT)
	MOV	BLINKS(T),FBLINK
	CLR	BLINKS(T)
LERET5:	MOV	#-1,LEKBD(U)
CLRUJ:	CLR	U		;SEARCH FAILED
CHRETX:	RTS	PC

.SBTTL VIDEO AND AUDIO SWITCH ROUTINES

;VIDEO SWITCH TABLES (ONE INPUT CAN DRIVE MANY OUTPUTS)

;THE SWITCH IS COMPOSED OF SEVERAL IDENTICAL SECTIONS, THE CORRESPONDING
;OUTPUTS OF EACH SECTION ARE MIXED TOGETHER TO FORM THE FINAL VIDEO THAT IS
;SENT TO THE MONITOR.  INPUT 0 OF EACH SECTION OF THE SWITCH IS THE NULL INPUT,
;HENCE WE USUALLY USE THAT INPUT WHEN USING A MONITOR AS A DISPLAY.

;VSWTAB, INDEXED BY OUTPUT NUMBER, IS A BYTE GIVING THE NONNULL INPUT FEEDING THAT OUTPUT.
;THE INPUT NUMBER IS RELATIVE TO THE WHOLE SWITCH, NOT JUST THE SECTION.
;0 MEANS THAT ONLY NULL INPUTS ARE FEEDING AN OUTPUT.

VSWTAB:	.BLKB	MAXVSO


;HERE TO SWITCH VIDEO SWITCH (OUTPUT IN T, INPUT IN TT).
;CLOBBERS NO ACS.

VSWIT:	PUSH	TT
	JSR	PC,VSWNUL		;FLUSH ALL OTHER INPUTS TO THAT OUTPUT.
	POP	TT
VSWIT1:	PUSH	B
	PUSH	C
	MOVB	TT,VSWTAB(T)		;UPDATE OUR OWN INTERNAL TABLE.
	MOV	TT,MQ
	MOV	#MAXVSI,DIV		;DIVIDE TO TURN INPUT NUMBER
	MOV	MQ,C			;INTO SECTION NUMBER
	MOV	AC,B			;AND NUMBER WITHIN SECTION.
	TST	A			;CLEAR C BIT
	ROR	C
	ROR	C
	ROR	C
	ROR	C			;GET SECTION NUMBER INTO TOP THREE BITS OF WORD.
	BIS	C,B
	MOV	T,C
	SWAB	C
	BIS	C,B			;CREATE ARGUMENT FOR VIDEO SWITCH.
	MOV	B,VSW			;SWITCH IT!
	POP	C
	POP	B
	RTS	PC

;HERE SEND NULL VIDEO TO OUTPUT SPECIFIED IN T
;CLOBBERS TT
VSWNUL:	PUSH	#VSWSEC		;# SECTIONS
	CLR	TT		;INPUT 0 IN SECTION 0.
VSWN1:	JSR	PC,VSWIT1	;SWITCH IT
	ADD	#MAXVSI,TT	;ADVANCE TO INPUT 0 IN NEXT SECTION
	DEC	(SP)
	BGT	VSWN1		;MORE
	TST	(SP)+		;CLEANSE STACK
	CLRB	VSWTAB(T)	;MAKE SURE INTERNAL TABLE SAYS NOTHING FEEDING THIS OUTPUT.
	RTS	PC

;AUDEO SWITCH TABLES (ONE INPUT CAN DRIVE MANY OUTPUTS)

;INPUT 0 IS SILENCE.  RIGHT NOW, THAT IS THE NORMAL SETTING FOR ANY OUTPUT.

;ASWTAB, INDEXED BY OUTPUT NUMBER, IS A BYTE GIVING THE INPUT FEEDING THAT OUTPUT.
ASWTAB:	.BLKB	MAXASO


;GIVEN ASW OUTPUT IN T AND INPUT IN TT, CONNECT THEM IF THEY ARE LEGAL.
;ON RETURN, BLO JUMPS IF THEY WERE LEGAL.
ASWCMD:	CMP	T,#MAXASO
	BHIS	ASWITX
	CMP	TT,#MAXASI
	BHIS	ASWITX

;HERE TO SWITCH AUDEO SWITCH (OUTPUT IN T, INPUT IN TT).
;CLOBBERS NO ACS.

ASWIT:	PUSH	C
	MOV	T,C
	SWAB	C
	BIS	TT,C			;CONSTRUCT OUTPUT,,INPUT AND GIVE TO SWITCH AS COMMAND.
	PUSH	B
	MOV	C,B			;NOW COMPLEMENT SOME OF C (WHAT'S IN ASWXOR).
	BIC	#<-1>#ASWXOR,B
	BIS	#ASWXOR,C
	BIC	B,C
	POP	B
	MOV	C,ASW
	MOVB	TT,ASWTAB(T)		;UPDATE OUR OWN INTERNAL TABLE.
	POP	C
ASWITX:	RTS	PC

;RESET THE AUDEO SWITCH (ALL OUTPUTS RECEIVING SILENCE).
REASW:	MOV	#MAXASO-1,T
	CLR	TT
REASW1:	JSR	PC,ASWIT
	DEC	T
	BGE	REASW1
	RTS	PC

.SBTTL CHARACTER GENERATOR ROUTINES

;CLEARS CHARACTER AT LINE EDITOR CURSOR

CLRCHR:	JSR	U,ACSAV
	MOVB	#CANDC,CALU
CLCHR1:	MOV	#BLOB,T			;BLOB MASKS ENTIRE CHARACTER
CLCHR2:	MOV	LEPHS(U),C
	MOV	LECC(U),TT
	JSR	PC,GENCH1
	MOVB	#CIOR,CALU		;RESTORE FOR DPYDP1 LOOP
	BR	ACRES

;BLINK CHARACTER AT CURSOR

XORCHR:	JSR	U,ACSAV
	MOVB	#CXOR,CALU
	MOV	#BLOB,T
	BR	CLCHR2

;GENERATE A CHARACTER
;CALL WITH CHARACTER IN A AND PAGE PRINTER IN U
;PRESERVES ALL ACS

GENCHR:	JSR	U,ACSAV
	MOV	LEPHS(U),C
	MOV	LECC(U),TT
	MOVB	#CIOR,CALU
	ASL	A		;MAKE IT A BYTE OFFSET
	MOV	CTAB(A),T	;POINTS AT FONT DESCRIPTION
	JSR	PC,GENCH1
ACRES:	POP	A
	POP	B
	POP	C
	POP	T
	POP	TT
	POP	U
	RTS	PC

;The lowest level character generator
;Initial AC settings

;A	LSH address of EAE shift counter
;B	MQ address of EAE regiseter
;C	number of desired shifts
;T	points into font description
;TT	points into display memory
;U	number of bytes per line of display memory

;initial memory settings

;AC	0, EAE register
;CREG	CIOR,,console number, console register
;;NOTE THAT MQ=AC+2
;THIS ROUTINE CLOBBERS -ALL- ACS

GENCH1:	MOV	#LSH,A
	TST	C
	BLT	OVRLAP
EZCASE:	MOV	#BYTPL,U
	MOV	#AC,B
	CLR	(B)+		;CLEAR AC

.REPT CHRHT
.NLIST
	MOVB	(T)+,(B)	;5.2	;CHARACTER RASTER LINE INTO MQ
	MOV	C,(A)		;3.7	;INITIATE SHIFT
	MOV	(B),(TT)	;5.2	;OUT OF MQ INTO DISPLAY MEMORY
	ADD	U,TT		;2.3	;GET TO NEXT RASTER LINE
;			TOTAL	16.4 MICRO-SECONDS
.LIST
.ENDR
	RTS	PC

;initial settings same as EZCASE with one exception
;U	<number of bytes per line of display memory>-2

OVRLAP:	MOV	#BYTPL-2,U
	MOV	#MQ+2,B

.REPT CHRHT
.NLIST
	CLR	-(B)		;3.7	;CLEAR MQ
	CLRB	-(B)		;2.3	;CLEAR HIGH ORDER OF AC
	MOVB	(T)+,-(B)	;5.2	;LOAD AC WITH CHARACTER LINE
	MOV	C,(A)		;3.7	;INIATE SHIFT
	MOV	(B)+,(TT)+	;5.2	;AC TO DISPLAY MEMORY
	MOV	(B)+,(TT)	;5.2	;MQ TO DISPLAY MEMORY
	ADD	U,TT		;2.3	;SET TO NEXT RASTER LINE
			;TOTAL	27.6 MICRO-SECONDS
.LIST
.ENDR
RTSPC:	RTS	PC

;SOME LOW LEVEL GOODIES

;CLEARS ONE RASTER LINE

CLRRST:	MOVB	#CSET,CALU
CLRRS1:	.REPT WRDPL
	.NLIST
	CLR	(T)+
	.LIST
	.ENDR
	RTS	PC

;CLEARS ONE CHARACTER LINE

CLRCHL:	MOV	#LINHT-1,TT
CLRCL0:	JSR	PC,CLRRST
CLRCH1:	JSR	PC,CLRRS1
	DEC	TT
	BGT	CLRCH1
	RTS	PC

;CLEAR ENTIRE SCREEN

CLRSCR:	MOV	#TVLO,T
	JSR	PC,CLRRST
	MOV	#NLINS-1,TT
CLRSC1:	JSR	PC,CLRRS1
	DEC	TT
	BGT	CLRSC1
	RTS	PC

;COPIES ONE RASTER LINE

CPYRST:	MOVB	#CSET,CALU
CPYRS1:	.REPT WRDPL
	.NLIST
	MOV	(T)+,(TT)+
	.LIST
	.ENDR
	RTS	PC

;COPIES ONE CHARACTER LINE

CPYCHL:	PUSH	A
	MOV	#LINHT-1,A
	JSR	PC,CPYRST
CPYCH1:	JSR	PC,CPYRS1
	DEC	A
	BGT	CPYCH1
	POP	A
	RTS	PC

.SBTTL KEYBOARD TABLES

.MACRO KBDKEY N,PLAIN,SH,SL,SLSH,TOP
.XLIST
.=XTAB+N
.BYTE PLAIN
.=XTAB+N+100
.BYTE SH
.=XTAB+N+200
.BYTE SL
.=XTAB+N+300
.BYTE SLSH
.=XTAB+N+400
.BYTE TOP
.LIST
.ENDM

;WHAT FOLLOWS IS THE GRAND CHARACTER CONVERSION TABLE

;AN 8 BIT QUANTITY IS USED TO INDEX INTO THE XTAB
;	0-5	KEYBOARD KEY NUMBER
;	  6	SHIFT
;	  7	SHIFT LOCK
;	  8	TOP (6 AND 7 GUARANTEED TO BE ZERO)

;IF THE BYTE PICKED IS NEGATIVE, YOU HAVE STRUCK A KEY THAT DOES NOT
;HAVE AN ASCII CODE.  THESE CODES ARE ASSIGNED AS FOLLOWS:

NASCTB:	NONAS1	;	 0	ILLEGAL
	ESCAPE	;	-1	ESCAPE
	BRKCLR	;	-2	BREAK
	BRKCLR	;	-3	CLEAR
	PLSMNS	;	-4	PLUS-MINUS
	CRCPLS	;	-5	CIRCLE-PLUS
	DELTA	;	-6	DELTA
	GAMMA	;	-7	GAMMA
	BRKCLR	;	-10	HELP
	RTSPC	;	-11	BACK -- not really used
	RTSPC	;	-12	NEXT -- not really used
	CALL	;	-13	CALL
MAXNAS==<<.-NASCTB>/2>-1	;MAXIMUM # NON-ASCII CHARACTERS

.EVEN

;	CHAR	NORMAL	SHIFT	LOCK	SHIFT&LOCK	TOP

XTAB:
KBDKEY	0,	-2,	-2,	-2,	-2,		-2	;BREAK
KBDKEY	1,	-1,	-1,	-1,	-1,		-1	;ESCAPE
KBDKEY	2,	'1,	'!,	'1,	'!,		'!
KBDKEY	3,	'2,	'",	'2,	'",		'"
KBDKEY	4,	'3,	'#,	'3,	'#,		'#
KBDKEY	5,	'4,	'$,	'4,	'$,		'$
KBDKEY	6,	'5,	'%,	'5,	'%,		'%
KBDKEY	7,	'6,	'&,	'6,	'&,		'&
KBDKEY	10,	'7,	'',	'7,	'',		''
KBDKEY	11,	'8,	'(,	'8,	'(,		'(
KBDKEY	12,	'9,	'),	'9,	'),		')
KBDKEY	13,	'0,	'_,	'0,	'_,		'_
KBDKEY	14,	'-,	'=,	'-,	'=,		'=
KBDKEY	15,	'@,	'`,	'@,	'`,		'`
KBDKEY	16,	'^,	'~,	'^,	'~,		'~
KBDKEY	17,	10,	10,	10,	10,		10	;BACK SPACE
KBDKEY	20,	-13,	-13,	-13,	-13,		-13	;CALL
KBDKEY	21,	-3,	-3,	-3,	-3,		-3	;CLEAR
KBDKEY	22,	11,	11,	11,	11,		11	;TAB
KBDKEY	23,	33,	33,	33,	33,		33	;ALT-MODE
KBDKEY	24,	'q,	'Q,	'Q,	'Q,		4,	;and
KBDKEY	25,	'w,	'W,	'W,	'W,		37	;or
KBDKEY	26,	'e,	'E,	'E,	'E,		22	;intersection
KBDKEY	27,	'r,	'R,	'R,	'R,		23	;union
KBDKEY	30,	't,	'T,	'T,	'T,		20	;subset
KBDKEY	31,	'y,	'Y,	'Y,	'Y,		21	;superset
KBDKEY	32,	'u,	'U,	'U,	'U,		5	;not
KBDKEY	33,	'i,	'I,	'I,	'I,		26	;xor
KBDKEY	34,	'o,	'O,	'O,	'O,		1	;down arrow
KBDKEY	35,	'p,	'P,	'P,	'P,		13	;up arrow
KBDKEY	36,	'[,	'{,	'[,	'{,		'{
KBDKEY	37,	'],	'},	'],	'},		'}
KBDKEY	40,	'\,	'|,	'\,	'|,		'|
KBDKEY	41,	'/,	16,	'/,	16,		16	;infinity
KBDKEY	42,	-4,	-6,	-4,	-6,		-6	;plus-minus, delta
KBDKEY	43,	-5,	-7,	-5,	-7,		-7	;circle-plus, gamma
KBDKEY	44,	14,	14,	14,	14,		14	;form
KBDKEY	45,	13,	13,	13,	13,		13	;vertical tab
KBDKEY	46,	177,	177,	177,	177,		177	;rubout
KBDKEY	47,	'a,	'A,	'A,	'A,		34	;.leq.
KBDKEY	50,	's,	'S,	'S,	'S,		35	;.geq
KBDKEY	51,	'd,	'D,	'D,	'D,		36	;equivalence
KBDKEY	52,	'f,	'F,	'F,	'F,		17	;delta (partial derivative)
KBDKEY	53,	'g,	'G,	'G,	'G,		32	;not equals
KBDKEY	54,	'h,	'H,	'H,	'H,		-10	;HELP!!!!!
KBDKEY	55,	'j,	'J,	'J,	'J,		30	;back arrow
KBDKEY	56,	'k,	'K,	'K,	'K,		31	;forward arrow
KBDKEY	57,	'l,	'L,	'L,	'L,		27	;both ways arrow
KBDKEY	60,<';>,	'+,<';>,	'+,		'+
KBDKEY	61,	':,	'*,	':,	'*,		'*
KBDKEY	62,	15,	15,	15,	15,		15	;carriage return
KBDKEY	63,	12,	12,	12,	12,		12	;line feed
KBDKEY	64,	37,	37,	37,	37,		37	;next, back gives ^_
;KBDKEY	64,	-12,	-11,	-12,	-11,		-11	;next, back
KBDKEY	65,	'z,	'Z,	'Z,	'Z,		2	;alpha
KBDKEY	66,	'x,	'X,	'X,	'X,		3	;beta
KBDKEY	67,	'c,	'C,	'C,	'C,		6	;epsilon
KBDKEY	70,	'v,	'V,	'V,	'V,		10	;lambda
KBDKEY	71,	'b,	'B,	'B,	'B,		7	;pi
KBDKEY	72,	'n,	'N,	'N,	'N,		24	;for all
KBDKEY	73,	'm,	'M,	'M,	'M,		25	;there exists
KBDKEY	74,<',>,	'<,<',>,	'<,		'<
KBDKEY	75,	'.,	'>,	'.,	'>,		'>
KBDKEY	76,	'/,	'?,	'/,	'?,		'?
KBDKEY	77,	40,	40,	40,	40,		40	;space

.SBTTL FONT MACROS AND DEFINITION

.IIF E FONTSW,CTAB==0
.IF NE FONTSW
FNTORG==.
	.MACRO CTBENT A
	.XCREF ...'A
	...'A
	.ENDM

CTAB:	.REPT 200
	.NLIST
	CTBENT \.RPCNT
	.LIST
	.ENDR
	...200				;THIS CHAR IS A BLOB FOR CURSORS.

.MACRO	FONT A
.NLIST
....==0
...==1_GRIDWD

.IRPC	CHR,A
...==..._<-1>
.IF NB	CHR
....==....!...
.ENDC
.ENDM

.IF NE	...-1
ERROR	\CURCHR
.ENDC

;...FOO==%XLIST
;.REPT ...FOO
;.LIST
;.ENDR
.BYTE	....
;.XLIST
;%XLIST=...FOO
.LIST
.ENDM

.MACRO CDEF A
.NLIST
CURCHR==''A
CDEF1	\CURCHR
.LIST
.ENDM

.MACRO	CDEF1 A
.NLIST
.XCREF ...'A
CURCHR==A
;...FOO==%XLIST
;.REPT ...FOO
;.LIST
;.ENDR
...'A==.
;.XLIST
;%XLIST=...FOO

.LIST
.ENDM

.MACRO	ERROR NUM
.IF1
.ERROR	;FONT LOSSAGE NUM
.ENDC
.ENDM
.ENDC
.XLIST
.IF NE FONTSW
.IF NE FONTMS
.XCREF CURCHR,FONT,CDEF1,CDEF

CDEF1 0
FONT <     >
FONT <     >
FONT <     >
FONT < *** >
FONT < *** >
FONT < *** >
FONT <     >
FONT <     >
FONT <     >
FONT <     >

CDEF1 1
FONT <     >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <* * *>
FONT < *** >
FONT <  *  >
FONT <     >
FONT <     >

CDEF1 2
FONT <     >
FONT <     >
FONT <     >
FONT < ** *>
FONT <*  * >
FONT <*  * >
FONT <*  * >
FONT < ** *>
FONT <     >
FONT <     >

CDEF1 3
FONT <     >
FONT <     >
FONT <     >
FONT < *** >
FONT <*   *>
FONT <**** >
FONT <*   *>
FONT <**** >
FONT <*    >
FONT <*    >

CDEF1 4
FONT <     >
FONT <     >
FONT <     >
FONT <  *  >
FONT < * * >
FONT <*   *>
FONT <     >
FONT <     >
FONT <     >
FONT <     >

CDEF1 5
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <*****>
FONT <    *>
FONT <    *>
FONT <     >
FONT <     >
FONT <     >

CDEF1 6
FONT <     >
FONT <     >
FONT <     >
FONT <  ** >
FONT < *   >
FONT < *** >
FONT < *   >
FONT <  ** >
FONT <     >
FONT <     >

CDEF1 7
FONT <     >
FONT <     >
FONT <     >
FONT <*****>
FONT < * * >
FONT < * * >
FONT < * * >
FONT < * * >
FONT <     >
FONT <     >

CDEF1 10
FONT <     >
FONT <     >
FONT <*    >
FONT <*    >
FONT < *   >
FONT <  *  >
FONT < * * >
FONT <*   *>
FONT <     >
FONT <     >

CDEF1 11
FONT <     >
FONT <*   *>
FONT < * * >
FONT <  *  >
FONT < * * >
FONT <*   *>
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF1 12
FONT <     >
FONT < *** >
FONT <    *>
FONT <   * >
FONT <  *  >
FONT < * * >
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF1 13
FONT <     >
FONT <  *  >
FONT < *** >
FONT <* * *>
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <     >
FONT <     >

CDEF1 14
FONT <     >
FONT <  *  >
FONT <  *  >
FONT <*****>
FONT <  *  >
FONT <  *  >
FONT <*****>
FONT <     >
FONT <     >
FONT <     >

CDEF1 15
FONT <     >
FONT <     >
FONT < *** >
FONT <* * *>
FONT <*****>
FONT <* * *>
FONT < *** >
FONT <     >
FONT <     >
FONT <     >

CDEF1 16
FONT <     >
FONT <     >
FONT <     >
FONT < * * >
FONT <* * *>
FONT <* * *>
FONT < * * >
FONT <     >
FONT <     >
FONT <     >

CDEF1 17
FONT <     >
FONT < **  >
FONT <   * >
FONT <    *>
FONT < ****>
FONT <*   *>
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF1 20
FONT <     >
FONT <     >
FONT < ****>
FONT <*    >
FONT <*    >
FONT <*    >
FONT < ****>
FONT <     >
FONT <     >
FONT <     >

CDEF1 21
FONT <     >
FONT <     >
FONT <**** >
FONT <    *>
FONT <    *>
FONT <    *>
FONT <**** >
FONT <     >
FONT <     >
FONT <     >

CDEF1 22
FONT <     >
FONT <     >
FONT < *** >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <     >
FONT <     >
FONT <     >
FONT <     >

CDEF1 23
FONT <     >
FONT <     >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >
FONT <     >
FONT <     >

CDEF1 24
FONT <     >
FONT <*   *>
FONT <*   *>
FONT <*****>
FONT <*   *>
FONT < * * >
FONT < * * >
FONT <  *  >
FONT <     >
FONT <     >

CDEF1 25
FONT <     >
FONT <*****>
FONT <    *>
FONT <    *>
FONT < ****>
FONT <    *>
FONT <    *>
FONT <*****>
FONT <     >
FONT <     >

CDEF1 26
FONT <     >
FONT <     >
FONT < *** >
FONT <** **>
FONT <* * *>
FONT <** **>
FONT < *** >
FONT <     >
FONT <     >
FONT <     >

CDEF1 27
FONT <     >
FONT <  *  >
FONT <   * >
FONT <*****>
FONT <   * >
FONT <  *  >
FONT < *   >
FONT <*****>
FONT < *   >
FONT <  *  >

CDEF1 30
FONT <     >
FONT <     >
FONT <  *  >
FONT < *   >
FONT <*****>
FONT < *   >
FONT <  *  >
FONT <     >
FONT <     >
FONT <     >

CDEF1 31
FONT <     >
FONT <     >
FONT <  *  >
FONT <   * >
FONT <*****>
FONT <   * >
FONT <  *  >
FONT <     >
FONT <     >
FONT <     >

CDEF1 32
FONT <     >
FONT <    *>
FONT <   * >
FONT <*****>
FONT <  *  >
FONT <*****>
FONT < *   >
FONT <*    >
FONT <     >
FONT <     >

CDEF1 33
FONT <     >
FONT <  *  >
FONT <  *  >
FONT < * * >
FONT <*   *>
FONT < * * >
FONT <  *  >
FONT <  *  >
FONT <     >
FONT <     >

CDEF1 34
FONT <     >
FONT <   * >
FONT <  *  >
FONT < *   >
FONT <  *  >
FONT <   * >
FONT <     >
FONT < *** >
FONT <     >
FONT <     >

CDEF1 35
FONT <     >
FONT < *   >
FONT <  *  >
FONT <   * >
FONT <  *  >
FONT < *   >
FONT <     >
FONT < *** >
FONT <     >
FONT <     >

CDEF1 36
FONT <     >
FONT <     >
FONT <*****>
FONT <     >
FONT <*****>
FONT <     >
FONT <*****>
FONT <     >
FONT <     >
FONT <     >

CDEF1 37
FONT <     >
FONT <     >
FONT <     >
FONT <*   *>
FONT < * * >
FONT <  *  >
FONT <     >
FONT <     >
FONT <     >
FONT <     >

CDEF < >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >

CDEF <!>
FONT <     >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <     >
FONT <  *  >
FONT <     >
FONT <     >

CDEF <">
FONT < * * >
FONT < * * >
FONT < * * >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >

CDEF <#>
FONT <     >
FONT <     >
FONT < * * >
FONT <*****>
FONT < * * >
FONT < * * >
FONT <*****>
FONT < * * >
FONT <     >
FONT <     >

CDEF <$>
FONT <  *  >
FONT < *** >
FONT <* * *>
FONT <* *  >
FONT < *** >
FONT <  * *>
FONT <* * *>
FONT < *** >
FONT <  *  >
FONT <     >

CDEF <%>
FONT <     >
FONT <*****>
FONT <**  *>
FONT <   * >
FONT <  *  >
FONT < *   >
FONT <*  **>
FONT <*  **>
FONT <     >
FONT <     >

CDEF <&>
FONT <     >
FONT < *   >
FONT <* *  >
FONT <* *  >
FONT < *   >
FONT <* * *>
FONT <*  * >
FONT < ** *>
FONT <     >
FONT <     >

CDEF <'>
FONT < **  >
FONT < **  >
FONT <**   >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >

CDEF <(>
FONT <     >
FONT <    *>
FONT <   * >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <   * >
FONT <    *>
FONT <     >
FONT <     >

CDEF <)>
FONT <     >
FONT <*    >
FONT < *   >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT < *   >
FONT <*    >
FONT <     >
FONT <     >

CDEF <*>
FONT <     >
FONT <  *  >
FONT <* * *>
FONT < *** >
FONT <  *  >
FONT < *** >
FONT <* * *>
FONT <  *  >
FONT <     >
FONT <     >

CDEF <+>
FONT <     >
FONT <     >
FONT <  *  >
FONT <  *  >
FONT <*****>
FONT <  *  >
FONT <  *  >
FONT <     >
FONT <     >
FONT <     >

CDEF <,>
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT < **  >
FONT < **  >
FONT <**   >
FONT <     >

CDEF <->
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <*****>
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >

CDEF <.>
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT < **  >
FONT < **  >
FONT <     >
FONT <     >

CDEF </>
FONT <     >
FONT <     >
FONT <    *>
FONT <   * >
FONT <  *  >
FONT < *   >
FONT <*    >
FONT <     >
FONT <     >
FONT <     >

CDEF 0
FONT <     >
FONT < *** >
FONT <*   *>
FONT <*  **>
FONT <* * *>
FONT <**  *>
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF 1
FONT <     >
FONT <  *  >
FONT < **  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT < *** >
FONT <     >
FONT <     >

CDEF 2
FONT <     >
FONT < *** >
FONT <*   *>
FONT <    *>
FONT <   * >
FONT <  *  >
FONT < *   >
FONT <*****>
FONT <     >
FONT <     >

CDEF 3
FONT <     >
FONT < *** >
FONT <*   *>
FONT <    *>
FONT <  ** >
FONT <    *>
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF 4
FONT <     >
FONT <   * >
FONT <  ** >
FONT < * * >
FONT <*  * >
FONT <*****>
FONT <   * >
FONT <   * >
FONT <     >
FONT <     >

CDEF 5
FONT <     >
FONT <*****>
FONT <*    >
FONT <**** >
FONT <    *>
FONT <    *>
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF 6
FONT <     >
FONT <  ** >
FONT < *   >
FONT <*    >
FONT <**** >
FONT <*   *>
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF 7
FONT <     >
FONT <*****>
FONT <    *>
FONT <   * >
FONT <   * >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <     >
FONT <     >

CDEF 8
FONT <     >
FONT < *** >
FONT <*   *>
FONT <*   *>
FONT < *** >
FONT <*   *>
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF 9
FONT <     >
FONT < *** >
FONT <*   *>
FONT <*   *>
FONT < ****>
FONT <    *>
FONT <   * >
FONT < **  >
FONT <     >
FONT <     >

CDEF <:>
FONT <     >
FONT <     >
FONT <     >
FONT < **  >
FONT < **  >
FONT <     >
FONT < **  >
FONT < **  >
FONT <     >
FONT <     >

CDEF <;>
FONT <     >
FONT <     >
FONT <     >
FONT < **  >
FONT < **  >
FONT <     >
FONT < **  >
FONT < **  >
FONT <**   >
FONT <     >

CDEF1 74
FONT <     >
FONT <     >
FONT <   * >
FONT <  *  >
FONT < *   >
FONT <  *  >
FONT <   * >
FONT <     >
FONT <     >
FONT <     >

CDEF <=>
FONT <     >
FONT <     >
FONT <     >
FONT <*****>
FONT <     >
FONT <*****>
FONT <     >
FONT <     >
FONT <     >
FONT <     >

CDEF1 76
FONT <     >
FONT <     >
FONT < *   >
FONT <  *  >
FONT <   * >
FONT <  *  >
FONT < *   >
FONT <     >
FONT <     >
FONT <     >

CDEF <?>
FONT <     >
FONT < *** >
FONT <*   *>
FONT <   * >
FONT <  *  >
FONT <  *  >
FONT <     >
FONT <  *  >
FONT <     >
FONT <     >

CDEF <@>
FONT <     >
FONT < *** >
FONT <*   *>
FONT <* ***>
FONT <* * *>
FONT <* ***>
FONT <*    >
FONT < *** >
FONT <     >
FONT <     >

CDEF A
FONT <     >
FONT < *** >
FONT <*   *>
FONT <*   *>
FONT <*****>
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <     >
FONT <     >

CDEF B
FONT <     >
FONT <**** >
FONT <*   *>
FONT <*   *>
FONT <**** >
FONT <*   *>
FONT <*   *>
FONT <**** >
FONT <     >
FONT <     >

CDEF C
FONT <     >
FONT < *** >
FONT <*   *>
FONT <*    >
FONT <*    >
FONT <*    >
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF D
FONT <     >
FONT <**** >
FONT < *  *>
FONT < *  *>
FONT < *  *>
FONT < *  *>
FONT < *  *>
FONT <**** >
FONT <     >
FONT <     >

CDEF E
FONT <     >
FONT <*****>
FONT <*    >
FONT <*    >
FONT <**** >
FONT <*    >
FONT <*    >
FONT <*****>
FONT <     >
FONT <     >

CDEF F
FONT <     >
FONT <*****>
FONT <*    >
FONT <*    >
FONT <**** >
FONT <*    >
FONT <*    >
FONT <*    >
FONT <     >
FONT <     >

CDEF G
FONT <     >
FONT < *** >
FONT <*   *>
FONT <*    >
FONT <*    >
FONT <*  **>
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF H
FONT <     >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <*****>
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <     >
FONT <     >

CDEF I
FONT <     >
FONT < *** >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT < *** >
FONT <     >
FONT <     >

CDEF J
FONT <     >
FONT <    *>
FONT <    *>
FONT <    *>
FONT <    *>
FONT <    *>
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF K
FONT <     >
FONT <*   *>
FONT <*  * >
FONT <* *  >
FONT <**   >
FONT <* *  >
FONT <*  * >
FONT <*   *>
FONT <     >
FONT <     >

CDEF L
FONT <     >
FONT <*    >
FONT <*    >
FONT <*    >
FONT <*    >
FONT <*    >
FONT <*    >
FONT <*****>
FONT <     >
FONT <     >

CDEF M
FONT <     >
FONT <*   *>
FONT <** **>
FONT <* * *>
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <     >
FONT <     >

CDEF N
FONT <     >
FONT <*   *>
FONT <*   *>
FONT <**  *>
FONT <* * *>
FONT <*  **>
FONT <*   *>
FONT <*   *>
FONT <     >
FONT <     >

CDEF O
FONT <     >
FONT < *** >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF P
FONT <     >
FONT <**** >
FONT <*   *>
FONT <*   *>
FONT <**** >
FONT <*    >
FONT <*    >
FONT <*    >
FONT <     >
FONT <     >

CDEF Q
FONT <     >
FONT < *** >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <* * *>
FONT <*  * >
FONT < ** *>
FONT <     >
FONT <     >

CDEF R
FONT <     >
FONT <**** >
FONT <*   *>
FONT <*   *>
FONT <**** >
FONT <* *  >
FONT <*  * >
FONT <*   *>
FONT <     >
FONT <     >

CDEF S
FONT <     >
FONT < *** >
FONT <*   *>
FONT <*    >
FONT < *** >
FONT <    *>
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF T
FONT <     >
FONT <*****>
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <     >
FONT <     >

CDEF U
FONT <     >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF V
FONT <     >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT < * * >
FONT < * * >
FONT <  *  >
FONT <     >
FONT <     >

CDEF W
FONT <     >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <* * *>
FONT <** **>
FONT <*   *>
FONT <     >
FONT <     >

CDEF X
FONT <     >
FONT <*   *>
FONT <*   *>
FONT < * * >
FONT <  *  >
FONT < * * >
FONT <*   *>
FONT <*   *>
FONT <     >
FONT <     >

CDEF Y
FONT <     >
FONT <*   *>
FONT <*   *>
FONT < * * >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <     >
FONT <     >

CDEF Z
FONT <     >
FONT <*****>
FONT <    *>
FONT <   * >
FONT <*****>
FONT < *   >
FONT <*    >
FONT <*****>
FONT <     >
FONT <     >

CDEF <[>
FONT <  ***>
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  ***>
FONT <     >

CDEF <\>
FONT <     >
FONT <     >
FONT <*    >
FONT < *   >
FONT <  *  >
FONT <   * >
FONT <    *>
FONT <     >
FONT <     >
FONT <     >

CDEF <]>
FONT <***  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <***  >
FONT <     >

CDEF <^>
FONT <  *  >
FONT < * * >
FONT <*   *>
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >

CDEF <_>
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <*****>

CDEF <`>
FONT <  ** >
FONT <  ** >
FONT <   **>
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >

CDEF a
FONT <     >
FONT <     >
FONT <     >
FONT < *** >
FONT <    *>
FONT < ****>
FONT <*   *>
FONT < ****>
FONT <     >
FONT <     >

CDEF b
FONT <     >
FONT <*    >
FONT <*    >
FONT <**** >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <**** >
FONT <     >
FONT <     >

CDEF c
FONT <     >
FONT <     >
FONT <     >
FONT < *** >
FONT <*   *>
FONT <*    >
FONT <*    >
FONT < ****>
FONT <     >
FONT <     >

CDEF d
FONT <     >
FONT <    *>
FONT <    *>
FONT < ****>
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT < ****>
FONT <     >
FONT <     >

CDEF e
FONT <     >
FONT <     >
FONT <     >
FONT < *** >
FONT <*   *>
FONT <**** >
FONT <*    >
FONT < *** >
FONT <     >
FONT <     >

CDEF f
FONT <     >
FONT <  ** >
FONT < *  *>
FONT < *   >
FONT <***  >
FONT < *   >
FONT < *   >
FONT < *   >
FONT <     >
FONT <     >

CDEF g
FONT <     >
FONT <     >
FONT <     >
FONT < *** >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT < ****>
FONT <    *>
FONT < *** >

CDEF h
FONT <     >
FONT <*    >
FONT <*    >
FONT <**** >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <     >
FONT <     >

CDEF i
FONT <     >
FONT <     >
FONT <  *  >
FONT <     >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <     >
FONT <     >

CDEF j
FONT <     >
FONT <     >
FONT <    *>
FONT <     >
FONT <    *>
FONT <    *>
FONT <    *>
FONT <    *>
FONT <*   *>
FONT < *** >

CDEF k
FONT <     >
FONT <*    >
FONT <*    >
FONT <*   *>
FONT <*  * >
FONT <***  >
FONT <*  * >
FONT <*   *>
FONT <     >
FONT <     >

CDEF l
FONT <     >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <     >
FONT <     >

CDEF m
FONT <     >
FONT <     >
FONT <     >
FONT <** * >
FONT <* * *>
FONT <* * *>
FONT <* * *>
FONT <* * *>
FONT <     >
FONT <     >

CDEF n
FONT <     >
FONT <     >
FONT <     >
FONT <* ** >
FONT <**  *>
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <     >
FONT <     >

CDEF o
FONT <     >
FONT <     >
FONT <     >
FONT < *** >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF p
FONT <     >
FONT <     >
FONT <     >
FONT <**** >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <**** >
FONT <*    >
FONT <*    >

CDEF q
FONT <     >
FONT <     >
FONT <     >
FONT < *** >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT < ****>
FONT <    *>
FONT <    *>

CDEF r
FONT <     >
FONT <     >
FONT <     >
FONT <* ** >
FONT <**  *>
FONT <*    >
FONT <*    >
FONT <*    >
FONT <     >
FONT <     >

CDEF s
FONT <     >
FONT <     >
FONT <     >
FONT < ****>
FONT <*    >
FONT < *** >
FONT <    *>
FONT <**** >
FONT <     >
FONT <     >

CDEF t
FONT <     >
FONT <  *  >
FONT <  *  >
FONT <*****>
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <   **>
FONT <     >
FONT <     >

CDEF u
FONT <     >
FONT <     >
FONT <     >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT < *** >
FONT <     >
FONT <     >

CDEF v
FONT <     >
FONT <     >
FONT <     >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT < * * >
FONT <  *  >
FONT <     >
FONT <     >

CDEF w
FONT <     >
FONT <     >
FONT <     >
FONT <*   *>
FONT <*   *>
FONT <* * *>
FONT <* * *>
FONT < * * >
FONT <     >
FONT <     >

CDEF x
FONT <     >
FONT <     >
FONT <     >
FONT <*   *>
FONT < * * >
FONT <  *  >
FONT < * * >
FONT <*   *>
FONT <     >
FONT <     >

CDEF y
FONT <     >
FONT <     >
FONT <     >
FONT <*   *>
FONT <*   *>
FONT <*   *>
FONT < * * >
FONT <  *  >
FONT < *   >
FONT <*    >

CDEF z
FONT <     >
FONT <     >
FONT <     >
FONT <*****>
FONT <   * >
FONT < *** >
FONT < *   >
FONT <*****>
FONT <     >
FONT <     >

CDEF1 173
FONT <    *>
FONT <   * >
FONT <   * >
FONT <   * >
FONT <  *  >
FONT <   * >
FONT <   * >
FONT <   * >
FONT <    *>
FONT <     >

CDEF1 174
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >

CDEF1 175
FONT <*    >
FONT < *   >
FONT < *   >
FONT < *   >
FONT <  *  >
FONT < *   >
FONT < *   >
FONT < *   >
FONT <*    >
FONT <     >

CDEF1 176
FONT < ** *>
FONT <* ** >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >
FONT <     >

CDEF1 177
FONT <   * >
FONT <  * *>
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <  *  >
FONT <* *  >
FONT < *   >
FONT <     >

CDEF1 200				;BLOB CHARACTER FOR CURSORS
FONT <*****>
FONT <*****>
FONT <*****>
FONT <*****>
FONT <*****>
FONT <*****>
FONT <*****>
FONT <*****>
FONT <*****>
FONT <*****>

.ENDC	;.IF NE FONTMS

.IF E FONTMS
...0==.
.BYTE 000,000,000,016,016,016,000,000,000,000
...1==.
.BYTE 000,004,004,004,004,025,016,004,000,000
...2==.
.BYTE 000,000,000,015,022,022,022,015,000,000
...3==.
.BYTE 000,000,000,016,021,036,021,036,020,020
...4==.
.BYTE 000,000,000,004,012,021,000,000,000,000
...5==.
.BYTE 000,000,000,000,037,001,001,000,000,000
...6==.
.BYTE 000,000,000,006,010,016,010,006,000,000
...7==.
.BYTE 000,000,000,037,012,012,012,012,000,000
...10==.
.BYTE 000,000,020,020,010,004,012,021,000,000
...11==.
.BYTE 000,021,012,004,012,021,021,016,000,000
...12==.
.BYTE 000,016,001,002,004,012,021,016,000,000
...13==.
.BYTE 000,004,016,025,004,004,004,004,000,000
...14==.
.BYTE 000,004,004,037,004,004,037,000,000,000
...15==.
.BYTE 000,000,016,025,037,025,016,000,000,000
...16==.
.BYTE 000,000,000,012,025,025,012,000,000,000
...17==.
.BYTE 000,014,002,001,017,021,021,016,000,000
...20==.
.BYTE 000,000,017,020,020,020,017,000,000,000
...21==.
.BYTE 000,000,036,001,001,001,036,000,000,000
...22==.
.BYTE 000,000,016,021,021,021,000,000,000,000
...23==.
.BYTE 000,000,021,021,021,016,000,000,000,000
...24==.
.BYTE 000,021,021,037,021,012,012,004,000,000
...25==.
.BYTE 000,037,001,001,017,001,001,037,000,000
...26==.
.BYTE 000,000,016,033,025,033,016,000,000,000
...27==.
.BYTE 000,004,002,037,002,004,010,037,010,004
...30==.
.BYTE 000,000,004,010,037,010,004,000,000,000
...31==.
.BYTE 000,000,004,002,037,002,004,000,000,000
...32==.
.BYTE 000,001,002,037,004,037,010,020,000,000
...33==.
.BYTE 000,004,004,012,021,012,004,004,000,000
...34==.
.BYTE 000,002,004,010,004,002,000,016,000,000
...35==.
.BYTE 000,010,004,002,004,010,000,016,000,000
...36==.
.BYTE 000,000,037,000,037,000,037,000,000,000
...37==.
.BYTE 000,000,000,021,012,004,000,000,000,000
...40==.
.BYTE 000,000,000,000,000,000,000,000,000,000
...41==.
.BYTE 000,004,004,004,004,004,000,004,000,000
...42==.
.BYTE 012,012,012,000,000,000,000,000,000,000
...43==.
.BYTE 000,000,012,037,012,012,037,012,000,000
...44==.
.BYTE 004,016,025,024,016,005,025,016,004,000
...45==.
.BYTE 000,037,031,002,004,010,023,023,000,000
...46==.
.BYTE 000,010,024,024,010,025,022,015,000,000
...47==.
.BYTE 014,014,030,000,000,000,000,000,000,000
...50==.
.BYTE 000,001,002,004,004,004,002,001,000,000
...51==.
.BYTE 000,020,010,004,004,004,010,020,000,000
...52==.
.BYTE 000,004,025,016,004,016,025,004,000,000
...53==.
.BYTE 000,000,004,004,037,004,004,000,000,000
...54==.
.BYTE 000,000,000,000,000,000,014,014,030,000
...55==.
.BYTE 000,000,000,000,037,000,000,000,000,000
...56==.
.BYTE 000,000,000,000,000,000,014,014,000,000
...57==.
.BYTE 000,000,001,002,004,010,020,000,000,000
...60==.
.BYTE 000,016,021,023,025,031,021,016,000,000
...61==.
.BYTE 000,004,014,004,004,004,004,016,000,000
...62==.
.BYTE 000,016,021,001,002,004,010,037,000,000
...63==.
.BYTE 000,016,021,001,006,001,021,016,000,000
...64==.
.BYTE 000,002,006,012,022,037,002,002,000,000
...65==.
.BYTE 000,037,020,036,001,001,021,016,000,000
...66==.
.BYTE 000,006,010,020,036,021,021,016,000,000
...67==.
.BYTE 000,037,001,002,002,004,004,004,000,000
...70==.
.BYTE 000,016,021,021,016,021,021,016,000,000
...71==.
.BYTE 000,016,021,021,017,001,002,014,000,000
...72==.
.BYTE 000,000,000,014,014,000,014,014,000,000
...73==.
.BYTE 000,000,000,014,014,000,014,014,030,000
...74==.
.BYTE 000,000,002,004,010,004,002,000,000,000
...75==.
.BYTE 000,000,000,037,000,037,000,000,000,000
...76==.
.BYTE 000,000,010,004,002,004,010,000,000,000
...77==.
.BYTE 000,016,021,002,004,004,000,004,000,000
...100==.
.BYTE 000,016,021,027,025,027,020,016,000,000
...101==.
.BYTE 000,016,021,021,037,021,021,021,000,000
...102==.
.BYTE 000,036,021,021,036,021,021,036,000,000
...103==.
.BYTE 000,016,021,020,020,020,021,016,000,000
...104==.
.BYTE 000,036,011,011,011,011,011,036,000,000
...105==.
.BYTE 000,037,020,020,036,020,020,037,000,000
...106==.
.BYTE 000,037,020,020,036,020,020,020,000,000
...107==.
.BYTE 000,016,021,020,020,023,021,016,000,000
...110==.
.BYTE 000,021,021,021,037,021,021,021,000,000
...111==.
.BYTE 000,016,004,004,004,004,004,016,000,000
...112==.
.BYTE 000,001,001,001,001,001,021,016,000,000
...113==.
.BYTE 000,021,022,024,030,024,022,021,000,000
...114==.
.BYTE 000,020,020,020,020,020,020,037,000,000
...115==.
.BYTE 000,021,033,025,021,021,021,021,000,000
...116==.
.BYTE 000,021,021,031,025,023,021,021,000,000
...117==.
.BYTE 000,016,021,021,021,021,021,016,000,000
...120==.
.BYTE 000,036,021,021,036,020,020,020,000,000
...121==.
.BYTE 000,016,021,021,021,025,022,015,000,000
...122==.
.BYTE 000,036,021,021,036,024,022,021,000,000
...123==.
.BYTE 000,016,021,020,016,001,021,016,000,000
...124==.
.BYTE 000,037,004,004,004,004,004,004,000,000
...125==.
.BYTE 000,021,021,021,021,021,021,016,000,000
...126==.
.BYTE 000,021,021,021,021,012,012,004,000,000
...127==.
.BYTE 000,021,021,021,021,025,033,021,000,000
...130==.
.BYTE 000,021,021,012,004,012,021,021,000,000
...131==.
.BYTE 000,021,021,012,004,004,004,004,000,000
...132==.
.BYTE 000,037,001,002,037,010,020,037,000,000
...133==.
.BYTE 007,004,004,004,004,004,004,004,007,000
...134==.
.BYTE 000,000,020,010,004,002,001,000,000,000
...135==.
.BYTE 034,004,004,004,004,004,004,004,034,000
...136==.
.BYTE 004,012,021,000,000,000,000,000,000,000
...137==.
.BYTE 000,000,000,000,000,000,000,000,000,037
...140==.
.BYTE 006,006,003,000,000,000,000,000,000,000
...141==.
.BYTE 000,000,000,016,001,017,021,017,000,000
...142==.
.BYTE 000,020,020,036,021,021,021,036,000,000
...143==.
.BYTE 000,000,000,016,021,020,020,017,000,000
...144==.
.BYTE 000,001,001,017,021,021,021,017,000,000
...145==.
.BYTE 000,000,000,016,021,036,020,016,000,000
...146==.
.BYTE 000,006,011,010,034,010,010,010,000,000
...147==.
.BYTE 000,000,000,016,021,021,021,017,001,016
...150==.
.BYTE 000,020,020,036,021,021,021,021,000,000
...151==.
.BYTE 000,000,004,000,004,004,004,004,000,000
...152==.
.BYTE 000,000,001,000,001,001,001,001,021,016
...153==.
.BYTE 000,020,020,021,022,034,022,021,000,000
...154==.
.BYTE 000,004,004,004,004,004,004,004,000,000
...155==.
.BYTE 000,000,000,032,025,025,025,025,000,000
...156==.
.BYTE 000,000,000,026,031,021,021,021,000,000
...157==.
.BYTE 000,000,000,016,021,021,021,016,000,000
...160==.
.BYTE 000,000,000,036,021,021,021,036,020,020
...161==.
.BYTE 000,000,000,016,021,021,021,017,001,001
...162==.
.BYTE 000,000,000,026,031,020,020,020,000,000
...163==.
.BYTE 000,000,000,017,020,016,001,036,000,000
...164==.
.BYTE 000,004,004,037,004,004,004,003,000,000
...165==.
.BYTE 000,000,000,021,021,021,021,016,000,000
...166==.
.BYTE 000,000,000,021,021,021,012,004,000,000
...167==.
.BYTE 000,000,000,021,021,025,025,012,000,000
...170==.
.BYTE 000,000,000,021,012,004,012,021,000,000
...171==.
.BYTE 000,000,000,021,021,021,012,004,010,020
...172==.
.BYTE 000,000,000,037,002,016,010,037,000,000
...173==.
.BYTE 001,002,002,002,004,002,002,002,001,000
...174==.
.BYTE 004,004,004,004,004,004,004,004,004,004
...175==.
.BYTE 020,010,010,010,004,010,010,010,020,000
...176==.
.BYTE 015,026,000,000,000,000,000,000,000,000
...177==.
.BYTE 002,005,004,004,004,004,004,024,010,000
...200==.
.BYTE 037,037,037,037,037,037,037,037,037,037
.ENDC	;.IF E FONTMS
.LIST

BLOB=...200			;BLOB IS THE CHAR THAT COVERS ENTIRE CHARACTER AREA.

.IIF E FONTSW,.=.+3000		;APPROXIMATE SIZE OF FONT

REPORT FONT SIZE=,\.-FNTORG
FNTEND==.
.NLIST
.ENDC	;.IF NE FONTSW
.LIST

.SBTTL LINE EDITOR AND PAGE PRINTER VARIABLES
VARORG==.

.MACRO ...TEN
.=<.+3>&<-4>
.ENDM

;LINE EDITOR VARIABLE BLOCK FORMAT:
;THIS DOESN'T REALLY HAVE ANYTHING TO WITH LINE-EDITING.  THIS BLOCK
;CONTAINS MOST OF THE VARIABLES FOR EACH TV-CHANNEL (OR VIRTUAL TTY),
;COMBINING THE OLD IDEAS OF DPY BUFFER, LINE EDITOR, AND PAGE PRINTER.
;THERE IS ALSO A TV-BUFFER NUMBER, WHICH GOES IN THE CREG, AND INDEXES
;SOME ARRAYS ON THE LAST PAGE, A DPY CHANNEL # WHICH = A PDP10 TTY # MINUS NF11TY
;AND INDEXES SOME 11-10 SHARED ARRAYS, AND A KBD# WHICH IS A HARDWARE KEYBOARD
;NUMBER AND INDEXES SOME ARRAYS ON THE LAST PAGE.

LEDFLT:		.OFFSET -.
;FIRST COMES THE 10-TO-11 DPY OUTPUT BUFFER.  NOTE THAT THE "DEFAULT VALUES
;FOR THIS PART ARE NOT USED IN INITIALIZATION.
DPY10B::	.=.+2		;WORD PDP-10 IS HACKING (USED FOR INITIALIZATION ONLY)
DPY11B::	.=.+2		;WORD PDP-11 IS HACKING
DPYFS1::	.=.+2		;WASTED WORD.
DPYLGL::	.=.+2		;HIGHEST LEGAL BUFFER CELL
DPYSIZ::	.=.+2		;SIZE OF DATA AREA
DPYFS::		.=.+2		;NOT USED
...TEN
DPDATA::	.BLKB DPSIZE	;DATA AREA OF BUFFER.

LECC::		TVLO		;ADDRESS OF CURSOR
LEPHS::		20-CHRWD	;PHASE OF CURSOR
LEX::		-BITPL		;X POSITON OF LE CURSOR
LECREG::	.BYTE -1	;CONSOLE REGISTER FOR THIS LE DISPLAY
		.BYTE 0		;UNUSED
...TEN

LEZER0::	0		;FAKE LINE BUFFER HEADER (SENT TO PDP10 IN RESPONSE TO ECOFLG)
LEZER1::	0
LEBUF::		0		;CURRENT TEXT BUFFER
LELIST::	0		;KEYBOARD BUFFER CHAIN
LECHN::		-1		;DPY CHANNEL NUMBER, SET UP AT INIT TIME.
LEKBD::		-1		;KEYBOARD DRIVING THIS LINE EDITOR
LEY::		-NLINS		;Y COORDINATE OF LINE EDITOR DISPLAY
LELCC::		TVLO		;ADDRESS OF START OF CURRENT CHARACTER LINE, IN VIDEO BUFFER.
;LEFONT::	CTAB		;FONT FOR WRITING WITH IN THIS L.E. (NOT USED)
LECPC::		0		;COROUTINE PC SAVED BY GETCHC.
LESVB::		0		;VALUE OF B SAVED OVER CALL TO GETCHC.
LEFREE::	LBCHRS		;FREE CHARACTER COUNT
LECHR::		0		;POINTS AT FREE CHARACTER IN BUFFER
;LEBLNK::	0		;LINE EDITOR BLINKER (NOT USED, THERE IS NO LINE EDITOR)
LERPT::		0		;0 NORMAL, -1 => INDEFINITE REPEAT, ELSE REPEAT COUNT.
				;REPEAT REFERS TO REPEAT-ACTION ON AN INPUT CHARACTER.
LELSTA::	0		;A AND B AT MOST RECENT CALL TO PUTCHR.
LELSTB::	0		;FOR THE SAKE OF REPEAT-ACTION ON INPUT.
...TEN
LELEN::		.OFFSET 0

;LINE EDITOR VARIABLE AREAS.

TENWRD
;HERE WE ASSEMBLE IN THE "DPY BUFFERS".
LEUVAR:	.REPT	MAXTV
	.+DPDATA
	.-2+DPDATA
	0
	.-6+DPDATA+DPSIZE-2
	DPSIZE
	0
	.BLKB LELEN-DPDATA
	.ENDR
LEUEND==.

;THE WHO-LINE LINE EDITOR IS DIFFERENT AND APART FROM ALL THE REST

WHOPP:	.=.+LELEN

;CLOCK QUEUE ENTRY

		.OFFSET -.	;CLOCK QUEUE ENTRY
CQNEXT::	.=.+2		;CDR OF QUEUE
CQTIME::	.=.+2		;HIGH ORDER OF TIME
CQTIM1::	.=.+2		;LOW ORDER
CQROUT::	.=.+2		;ROUTINE TO CALL AT CLOCK LEVEL
CQARG::		.=.+2		;ARGUMENT FOR CLOCK LEVEL ROUTINE
CQLEN::		.OFFSET 0



		.OFFSET -.	;LINE BUFFER HEADER AREA
				;DON'T ADD NEW VARS WITHOUT CHANGING PDP10 CODE
				;IN TT11IN.
LHFLAG::	.=.+2		;0=>FREE, POS=>BUSY, NEG=>ACTIVE.
LHZERO::	.=.+2		;BETTER BE ZERO SO THAT PDP-10 CAN TEST LHFLAG
LHNEXT::	.=.+2		;NEXT BUFFER ON RING OF TWO FOR THIS TTY
LHALST::	.=.+2		;NEXT BUFFER ON LIST OF ACTIVE BUFFERS.
LHCHN::		.=.+2		;PDP-10 LINE NUMBER (TTY NUMBER MINUS NF11TY).
LHFS::		.=.+2		;CHAINS FREE STORAGE BLOCKS
LHQUED::	.=.+2		;NON-ZERO => THIS BUFFER CLOCK QUEUED FOR ACTIVATION (SEE QBFR)
...TEN
LHLEN::		.OFFSET 0

		.OFFSET -.	;BLINKER VARIABLES
BLNEXT::	0		;NEXT BLINKER ON LIST
BLCURS::	0		;POINTS AT CURSOR VARIABLES
BLON::		.BYTE 0		;PHASE; 0=INVISIBLE, 377=VISIBLE
BLCHAR::	.BYTE 177	;UNUSED
BLLEN::		.OFFSET 0

BLKVAR:	.=.+<MAXBLK*BLLEN>
	.EVEN

		.OFFSET -.	;USER WHO LINE
WHJOB::		.=.+2		;job #
WHJOB1::	.=.+2		;if negative then clear who line
WHMODE::	.=.+2		;mode
				;-1=>who line is off
				; 0=>follow keyboard
				; 1=>freeze
				; 2=>next higher (when PDP-10 sees this state, it searches
				;   user variables for next higher job index number with same
				;   uname.  When it finds it, it stores the number in job #
				;   and changes mode to 1
				; 3=>next lower
				;any other=>system who line
WHMOD1::	.=.+2		;pads WHMODE
WHUNAM::	.=.+2		;uname in sixbit (left 18 bits in first two words, right in next two)
WHUNM1::	.=.+2
WHUNM2::	.=.+2
WHUNM3::	.=.+2
WHJNAM::	.=.+2		;jname in sixbit
WHJNM1::	.=.+2
WHJNM2::	.=.+2
WHJNM3::	.=.+2
WHSNAM::	.=.+2		;sname in sixbit
WHSNM1::	.=.+2
WHSNM2::	.=.+2
WHSNM3::	.=.+2
WHSTAT::	.=.+2		;status in sixbit, 0=>job does not exist
WHSTA1::	.=.+2
WHSTA2::	.=.+2
WHSTA3::	.=.+2
WHJ%RT::	.=.+2		;job % run time
WHJTRT::	.=.+2		;job total run time (in tenth's of seconds)
WHRPAG::	.=.+2		;job real pages (swapped in)
WHTPAG::	.=.+2		;job total pages
WHO1::		.=.+2		;user who mode control word
WHO1A::		.=.+2
WHO2::		.=.+2		;first user who line var
WHO2A::		.=.+2
WHO2B::		.=.+2
WHO2C::		.=.+2
WHO3::		.=.+2		;second user who line var
WHO3A::		.=.+2
WHO3B::		.=.+2
WHO3C::		.=.+2
...TEN
		.=.+30		;EXTRA SPACE SO NEW HACKS CAN SAFELY BE PUT IN PDP10.
WHLEN::		.OFFSET 0

;USER WHO LINE VARIABLES

TENWRD

WHVARS:	.=.+<WHLEN*MAXTV>

.SBTTL MISCELLANEOUS TABLES
MISORG==.

;KEYBOARD/VIDEO SWITCH DEFAULTS
;INDEXED BY KBD #, GIVES NEAREST VIDEO SWITCH OUTPUT, -1=>NO DEFAULT

KBDVSW:	.BYTE	 0	; 0	809 FAHLMAN, HOLLOWAY, KNIGHT
	.BYTE	23	; 1	810 LAVIN, KUIPERS, MILLER
	.BYTE	24	; 2	919 Very Small Data Bases NORTH (FAR END)
	.BYTE	20	; 3	812 YVONNE
	.BYTE	 6	; 4	813 HEWITT
	.BYTE	 7	; 5	814 SUSSMAN
	.BYTE	 3	; 6	808 FREILING, ULLMAN
	.BYTE	-1	; 7
	.BYTE	 4	;10	817 JABARI
	.BYTE	-1	;11
	.BYTE	-1	;12
	.BYTE	10	;13	819 GOLDSTEIN
	.BYTE	 1	;14	820 MINSKY
	.BYTE	-1	;15
	.BYTE	-1	;16
	.BYTE	11	;17	821A  MARR
	.BYTE	-1	;20
	.BYTE	 2	;21	824 RICH, DEKLEER
	.BYTE	 5	;22	825 Sjoberg
	.BYTE	26	;23	826 Fredkin
	.BYTE	31	;24	815 Horn
	.BYTE	-1	;25
	.BYTE	-1	;26
	.BYTE	-1	;27
	.BYTE	15	;30	925 MOON'S REFRIGERATOR
	.BYTE	16	;31	902 TAENZER, MASON
	.BYTE	17	;32	919 Very Small Data losers
	.BYTE	14	;33	334 EDWARDS, LEBEL
	.BYTE	13	;34	913 BAISLEY, GREENBLATT
	.BYTE	12	;35	914 COHEN, GOSPER, ETC.
	.BYTE	21	;36	912 9TH FLOOR LOUNGE
	.BYTE	22	;37	907 CHESS, LISP MACHINES
	.BYTE	-1	;40	906 Lisp Machines
	.BYTE	37	;41	3rd Floor #1
	.BYTE	36	;42	3rd Floor #2
	.BYTE	35	;43	3rd Floor #3
	.BYTE	34	;44	3rd Floor #4
	.BYTE	33	;45	3rd Floor #5
	.BYTE	30	;46	3rd Floor #6
	.BYTE	-1	;47	NOT CONNECTED
	.BYTE	-1	;50	NOT CONNECTED
	.BYTE	-1	;51	NOT CONNECTED
	.BYTE	-1	;52	NOT CONNECTED
	.BYTE	-1	;53	NOT CONNECTED
	.BYTE	-1	;54	NOT CONNECTED
	.BYTE	-1	;55	NOT CONNECTED
	.BYTE	-1	;56	NOT CONNECTED
	.BYTE	-1	;57	NOT CONNECTED
	.BYTE	-1	;60	NOT CONNECTED
	.BYTE	-1	;61	NOT CONNECTED
	.BYTE	-1	;62	NOT CONNECTED
	.BYTE	-1	;63	NOT CONNECTED
	.BYTE	-1	;64	NOT CONNECTED
	.BYTE	-1	;65	NOT CONNECTED
	.BYTE	-1	;66	NOT CONNECTED
	.BYTE	-1	;67	NOT CONNECTED
	.BYTE	-1	;70	NOT CONNECTED
	.BYTE	-1	;71	NOT CONNECTED
	.BYTE	-1	;72	NOT CONNECTED
	.BYTE	-1	;73	NOT CONNECTED
	.BYTE	-1	;74	NOT CONNECTED
	.BYTE	-1	;75	NOT CONNECTED
	.BYTE	-1	;76	NOT CONNECTED
	.BYTE	-1	;77	NOT CONNECTED
CHECK KBDVSW,MAXKBD


;THIS TABLE SAYS WHICH FLOOR TO CALL THE ELEVATOR TO FOR <ESC>E

ELETAB:	.BYTE	ELKMS8	; 0	809 FAHLMAN, HOLLOWAY, KNIGHT
	.BYTE	ELKMS8	; 1	810 LAVIN, KUIPERS, MILLER
	.BYTE	ELKMS9	; 2	919 Very Small Data Bases NORTH (FAR END)
	.BYTE	ELKMS8	; 3	812 YVONNE
	.BYTE	ELKMS8	; 4	813 HEWITT
	.BYTE	ELKMS8	; 5	814 SUSSMAN
	.BYTE	ELKMS8	; 6	808 FREILING, ULLMAN
	.BYTE	0	; 7
	.BYTE	ELKMS8	;10	817 JABARI
	.BYTE	0	;11
	.BYTE	0	;12
	.BYTE	ELKMS8	;13	819 GOLDSTEIN
	.BYTE	ELKMS8	;14	820 MINSKY
	.BYTE	0	;15
	.BYTE	0	;16
	.BYTE	ELKMS8	;17	821A  MARR
	.BYTE	0	;20
	.BYTE	ELKMS8	;21	824 RICH, DEKLEER
	.BYTE	ELKMS8	;22	825 Sjoberg
	.BYTE	ELKMS8	;23	826 Fredkin
	.BYTE	ELKMS8	;24	815 Horn
	.BYTE	0	;25
	.BYTE	0	;26
	.BYTE	0	;27
	.BYTE	ELKMS9	;30	925 MOON'S REFRIGERATOR
	.BYTE	ELKMS9	;31	902 TAENZER, MASON
	.BYTE	ELKMS9	;32	919 Very Small Data losers
	.BYTE	0	;33	334 EDWARDS, LEBEL
	.BYTE	ELKMS9	;34	913 BAISLEY, GREENBLATT
	.BYTE	ELKMS9	;35	914 COHEN, GOSPER, ETC.
	.BYTE	ELKMS9	;36	912 9TH FLOOR LOUNGE
	.BYTE	ELKMS9	;37	907 CHESS, LISP MACHINES
	.BYTE	ELKMS9	;40	906 Lisp Machines
	.BYTE	0	;41	NOT CONNECTED
	.BYTE	0	;42	NOT CONNECTED
	.BYTE	0	;43	NOT CONNECTED
	.BYTE	0	;44	NOT CONNECTED
	.BYTE	0	;45	NOT CONNECTED
	.BYTE	0	;46	NOT CONNECTED
	.BYTE	0	;47	NOT CONNECTED
	.BYTE	0	;50	NOT CONNECTED
	.BYTE	0	;51	NOT CONNECTED
	.BYTE	0	;52	NOT CONNECTED
	.BYTE	0	;53	NOT CONNECTED
	.BYTE	0	;54	NOT CONNECTED
	.BYTE	0	;55	NOT CONNECTED
	.BYTE	0	;56	NOT CONNECTED
	.BYTE	0	;57	NOT CONNECTED
	.BYTE	0	;60	NOT CONNECTED
	.BYTE	0	;61	NOT CONNECTED
	.BYTE	0	;62	NOT CONNECTED
	.BYTE	0	;63	NOT CONNECTED
	.BYTE	0	;64	NOT CONNECTED
	.BYTE	0	;65	NOT CONNECTED
	.BYTE	0	;66	NOT CONNECTED
	.BYTE	0	;67	NOT CONNECTED
	.BYTE	0	;70	NOT CONNECTED
	.BYTE	0	;71	NOT CONNECTED
	.BYTE	0	;72	NOT CONNECTED
	.BYTE	0	;73	NOT CONNECTED
	.BYTE	0	;74	NOT CONNECTED
	.BYTE	0	;75	NOT CONNECTED
	.BYTE	0	;76	NOT CONNECTED
	.BYTE	0	;77	NOT CONNECTED
CHECK ELETAB,MAXKBD

;CHCREG TABLE, INDEXED BY CHANNEL NUMBER, GIVES TV BUFFER NUMBER.
;NON-WORKING TV BUFFERS SHOULD NOT BE IN THE LIST.
;IF THERE ARE MORE CHANNELS THAN BUFFERS, PUT -1 IN FOR SOME CHANNELS.

CHCREG:	.BYTE 0,1,4,5,6,7,10,11,12,13,14,15,16,17,-1,-1


;VIDEO SWITCH INPUT INDEXED BY DPY #, HIGH ORDER BYTE GIVES SWITCH SECTION

DPYVSW:	1		; 0
	2		; 1
	3		; 2
	4		; 3
	5		; 4
	6		; 5
	7		; 6
	10		; 7
	21		;10 THESE INPUTS ARE IN SECOND SECTION
	22		;11
	23		;12
	24		;13
	11		;14 1ST SECTION AGAIN
	12		;15
	13		;16
	14		;17
CHECK DPYVSW,MAXTV*2

;AUDIO SWITCH TABLES (INDEXED BY KBD #, GIVES AUDIO SWITCH OUTPUT #)

KBDASW:	.BYTE 00	; 0
	.BYTE 01	; 1
	.BYTE 02	; 2
	.BYTE 03	; 3
	.BYTE 04	; 4
	.BYTE 05	; 5
	.BYTE 06	; 6
	.BYTE 07	; 7
	.BYTE 10	;10
	.BYTE 11	;11
	.BYTE 12	;12
	.BYTE 13	;13
	.BYTE 14	;14
	.BYTE 15	;15
	.BYTE 16	;16
	.BYTE 17	;17
	.BYTE 20	;20
	.BYTE 21	;21
	.BYTE 22	;22
	.BYTE 23	;23
	.BYTE 24	;24
	.BYTE 25	;25
	.BYTE 26	;26
	.BYTE 27	;27
	.BYTE 30	;30
	.BYTE 31	;31
	.BYTE 32	;32
	.BYTE 33	;33
	.BYTE 34	;34
	.BYTE 35	;35
	.BYTE 36	;36
	.BYTE 37	;37
	.BYTE -1	;40
	.BYTE -1	;41
	.BYTE -1	;42
	.BYTE -1	;43
	.BYTE -1	;44
	.BYTE -1	;45
	.BYTE -1	;46
	.BYTE -1	;47
	.BYTE -1	;50
	.BYTE -1	;51
	.BYTE -1	;52
	.BYTE -1	;53
	.BYTE -1	;54
	.BYTE -1	;55
	.BYTE -1	;56
	.BYTE -1	;57
	.BYTE -1	;60
	.BYTE -1	;61
	.BYTE -1	;62
	.BYTE -1	;63
	.BYTE -1	;64
	.BYTE -1	;65
	.BYTE -1	;66
	.BYTE -1	;67
	.BYTE -1	;70
	.BYTE -1	;71
	.BYTE -1	;72
	.BYTE -1	;73
	.BYTE -1	;74
	.BYTE -1	;75
	.BYTE -1	;76
	.BYTE -1	;77
CHECK KBDASW,MAXKBD

;POINTER AREA

TENWRD

POINTA:	ITSWHO
	CMDFLG
TENWHO:	0		;-1=>PDP-10 SHOULD UPDATE WHO LINES
TENWH1:	0		;FILLS OUT TENWHO
	MAXTV		;PUT # OF PDP-10 CHANNELS HERE FOR ITS.
	0
NF11TY:	0		;PDP-10 PUTS TTY # OF FIRST CHANNEL HERE.
	0
QPYDWN:	0		;THIS NEEDS TO BE READ BY THE 10 FOR LOCK TVQPY CMD.
	0		
.=.+10			;LEAVE A LITTLE ROOM FOR GROWTH

;10/11 CHANNEL HEADER AREA

TENWRD

CHA==.
KBDFLG:	0		;KEYBOARD ACTIVATED LIST (SET BY 11 CLEARED BY 10)
	0		;ALWAYS ZERO
DPYCHN:	LEUVAR		;THE CHANNEL VARS BLOCK ADDR
DPYKBD:	0		;.BYTE KBD #,DPY #, OR -1 FOR FREE CHANNEL.
.REPT MAXTV-1
	LEUVAR+<<.RPCNT+1>*LELEN>
	0
.ENDR
ECOFLG:	0
CHNCLS:	0		;FLAGS DPY CHANNEL AS OPEN (SET TO -1 BY TEN)
	.=.+<<MAXTV-1>*4>
WHOLIN:	0		;POINTS TO WHO LINE VARIABLES FOR THIS CHANNEL
	0		;NOT USED
	.=.+<<MAXTV-1>*4>

;PDP-10/PDP-10 COMMAND BUFFER

TENWRD

CMDFLG:	0		;0=>TEN CAN WRITE, POSITIVE=>ELEVEN CAN WRITE, NEGATVE=>TEN WON
	0		;FULL PDP-10 WORD BOUNDARY
CMDBUF:	.=.+<CMDARG*4>	;EACH ARG IN COMMAND BUFFER IS PDP-10 WORD

;SYSTEM WHO LINE

TENWRD

ITSWHO==.
ITSTDP:	0	;# total # dpy's (read only for PDP-10)
ITSFDP:	0	;# free  dpys (read only for PDP-10)
ITSVER:	0	;ITS version #
ITSJOB:	0	;total jobs
ITSCOR:	0	;total core
ITSRU:	0	;runnable users
ITSWBJ:	0	;# jobs swap blocked
ITSJWP:	0	;# jobs waiting for pages
ITSTRC:	0	;total runable core
ITSCFU:	0	;core available for users
ITSDAT:	0	;date [byte (7) year (4) month (5) day]
ITSDBG:	0	;system debug flag
ITSTIM:	0	;time of day (# half seconds since midnight) aligned on PDP-10 word
ITSTI1:	0	;low order of time
ITSUSR:	0	;total number of users
ITSFSH:	0	;fair share in %

.SBTTL MISCELLANEOUS VARIABLES AND FREE STORAGE

;CHANNEL USE FLAGS NON-ZERO MEANS CHANNEL IN USE
CHNUSE:	.BLKB MAXTV	;BYTES INDEXED BY DPY CHANNEL #
	.EVEN


;BLINKERS.  INDEXED BY TV-BUFFER # (CREG)
BLINKS:	.BLKW MAXTV	;ADDRESS OF 1ST BLINKER OF THIS TV'S BLINKER LIST.

BLKSWT:	.BLKB MAXTV	;NONZERO => DON'T DO ANY BLINKING ON THIS TV NOW.
	.EVEN

;BELLS PENDING COUNTS.  INDEXED BY TV-BUFFER #
BELCNT:	.BLKW MAXTV


;PER-KEYBOARD INFORMATION.  INDEXED BY KBD#.
KBDLE:	.BLKW MAXKBD	;KEYBOARD/LINE EDITOR ASSOCIATION

KBDESC:	.BYTE 0		;NON-ZERO => <ESC> KEY HAS BEEN TYPED, READING ARG
KBDARG:	.BYTE 0		;NUMERIC ARGUMENT FOR <ESC>
	.=.+<<MAXKBD-1>*2>	;THE ABOVE TWO BYTE ARRAYS ARE INTERLEAVED.

	0	;THIS ZERO WORD NEEDED - SEE CLKBR5
KBDDEF:	.BYTE 0		;DEFAULT VIDEO SOURCE FOR THIS KBD WHEN LOOKING AT ANOTHER
KBDCNT:	.BYTE 0		;COUNTDOWN UNTIL RESET TO DEFAULT VIDEO SOURCE, OR -1
	.=.+<<MAXKBD-1>*2>


;CLOCK QUEUE

CLOCKF:	0	;CLOCK QUEUE FREE LIST
CLOCKQ:	0	;FIRST ENTRY ON CLOCK QUEUE
CQUEUE:	.=.+<CQLEN*NCQSLT>

;MISCELLANEOUS VARIBLES

FSP:	0	;POINTS TO LEBUFS FREE SPACE
OLDKMA:	0	;LAST KMA
BLINK:	0	;TV-BUFFER # OF NEXT GUY TO BLINK.  ALSO, COUNTS CLOCK TICKS
		; UNTIL NEXT BLINK.  IT'S PRETTY KLUDGEY, SEE CODE AT CLKLOP.
FBLINK:	BLKVAR	;LIST OF FREE BLINKERS
TICKS:	0	;HIGH ORDER OF TIME
TICKS1:	0	;LOW ORDER OF TIME
SSCC:	.BYTE 0	;SEMI-SLOW CLOCK COUNTER (WRAPS AROUND EVERY 256./60. SEC)
	.BYTE 0	;UNUSED
QPYSWT:	0	;INTER LOCK TO SAVE COPY PAPER
BUZSWT:	0	;INTERLOCK FOR BUZZING 9TH FLOOR DOOR
ELESWT:	0	;INTERLOCKING THE ELEVATOR
RADIX:	0	;HOLDS OUTPUT RADIX
VERSE:	%FNAM2	;SOURCE FILE VERSION #
KBDACT:	0	;KEYBOARD ACTIVE LIST (NOT YET SEEN BY PDP-10)
KBDLAST:0	;POINTS TO LAST BUFFER ON ACTIVE LIST
KBDTSW:	0	;NON-ZERO => EXAMINE KBDCNT ARRAY AT SSC LEVEL.
WHOTIM:	0	;LAST TIME WE DID WHO LINES
WHOFLG:	0	;DO WHO LINES FLAG
DPYFRE:	0	;DPY # OF FREE-CONSOLE CHANNEL.
TYMSHR:	0	;# CLOCK TICKS TO GO BEFORE CHECKING NEXT DPY CHANNEL

;PATCH AREA
PATCH:	.=.+PATL

;******* TEMPORARY VARIABLES FOR FONT CHECKSUMS *******
CKSPNT:	0	;RUNNING POINTER
CKSSUM:	0	;RUNNING CHECKSUM
CKSSMG:	0	;GOOD CHECKSUM OF [FNTORG,FNTEND)

;LINE EDITOR BUFFER RINGS

TENWRD
NLBUFS==<RUGSA-.>/<LHLEN+LBLEN>

.IIF LT NLBUFS-<MAXTV*2>, .ERROR NOT ENOUGH LEBUFS
REPORT NLBUFS=,\NLBUFS

LEBUFS:	.=.+<NLBUFS*<LHLEN+LBLEN>>

REPORT HIGHEST USED=,\.

.END	GO
