;
;IMSAI VIDEO DISPLAY DRIVER & SMP-80 MONITOR FOR VIO-C
;AS DIS-ASSEMBLED BY BARRY WATZMAN 7/17/78
;
	ORG	0F000H
VIDBF	DS	1920		;SCREEN BUFFERR
LF780	DS	1		;CURSOR ROW (0-23)
LF781	DS	1		;CURSOR COLUMN (0-79)
LF782	DS	1		;INVERSE VIDEO FLAG
LF783	DS	1		;INVERTED COPY OF STATUS MODE BYTES
LF784	DS	1		;INSERT MODE TOGGLE
LF785	DS	1		;ESCAPE FLAG
LF786	DS	1		;STORAGE FOR 2ND CHAR OF ESC SEQ
LF787	DS	2		;ADDR OF ALT CTL CHAR TABLE
LF789	DS	2		;ADDR OF ALT ESC CHAR TABLE
LF78B	DS	2		;ADDR OF ALT MONITOR CMD TABLE
LF78D	DS	2		;ADDR OF RAM FOR I/O CMDS
LF78F	DS	2		;ABSOLUTE CURSOR ADDRESS
LF791	DS	1		;0FFH HERE ==> BIT 80H=PROTECT
LF792	DS	1		;STORE CHAR UNDER CURSOR
LF793	DS	1		;STORE CHAR TO BE DISPLAYED
LF794	DS	1		;COPY OF STATUS W/EXTRA BITS
LF795	DS	10		;TAB STORAGE (BIT MAPPED)
LF79F	DS	2		;STORE MAX ALLOWED COL
LF7A1	DS	1		;STORE MAX ALLOWED ROW
LF7A2	DS	2		;NO OF CHARS IN CUR SCRN FORMAT
LF7A4	DS	1		;PROT FLD ENCOUNTERED FLAG FOR TAB FNCT
	DS	1
LF7A6	DS	2		;ABS. ADDR OF END OF SCREEN
STACK	DS	87		;RESERVED FOR MONITOR STACK
STATS	DS	1		;HARDWARE COMMAND BYTE
;
;PROGRAM ENTRY POINTS
;
START:	JMP	INITL		;INITIALIZATION ENTRY
	JMP	CHROT		;CHARACTER DISPLAY ENTRY
	JMP	MONTR		;MONITOR ENTRY POINT
	LXI	SP,STATS-1	;SELF TEST PROGRAM ENTRY
	CALL	INITL		;INITIALIZE VIO BOARD
LF80F:	CALL	GTCHR		;GET CHAR FM KEYBD & PUT ON SCRN
	JMP	LF80F		;DO IT FOREVER
;
;INITIALIZATION ROUTINE
;
INITL:	PUSH	H		;SAVE REGISTERS
	PUSH	D		;
	PUSH	B		; 
	PUSH	PSW		; 
	LXI	H,VIDBF+1920	;POINT TO START OF VAR. STORAGE
	MVI	B,1FH		;LENGTH OF STORAGE AREA
	XRA	A		;GET A ZERO
LF81F:	MOV	M,A		;CLEAR STORAGE
	INX	H		;POINT TO NEXT
	DCR	B		;DECR. COUNT
	JNZ	LF81F		;MORE IF NOT DONE
	LXI	H,VIDBF		;GET 1ST CHAR ADDRESS
	SHLD	LF78F		;SAVE ABSOLUTE CURSOR ADDR
	LXI	H,1920		;NO OF CHARS IN 80 X 24 SCRN
	SHLD	LF7A2		;SAVE NO CHRS IN CURRENT FORMAT
	CALL	CLEAR		;CLEAR SCREEN
	MVI	A,8		;ASCII TEXT MODE, POS VID, 80X24
	LXI	D,LF8DF		;RETURN ADDR FOR ALL COMMANDS
	PUSH	D		;PUT IT ON STACK TOP
LF83A:	STA	LF794		;SOFTWARE'S STATUS BYTE
	STA	STATS		;HARDWARE'S STATUS BYTE
	CMA			;REVERSE BITS
	ANI	03H		;MASK SCRN SIZE BITS
	RRC			;CARRY = CHRS/LINE BIT INVERTED
	LXI	H,40		;ASSUME 40 CHRS/LINE
	JNC	LF84B		;SKIP NEXT STEP IF REALLY 40
	DAD	H		;ELSE H,L = 80
LF84B:	SHLD	LF79F		;SAVE MAX PERMITTED COL.
	LXI	H,LF7A1		;POINT TO MAX. PERMITTED LINE #
	MVI	M,11		;ASSUME 12 LINES/PAGE
	RAR			;CARRY = INVERTED LINES/PG BIT
	JNC	LF859		;SKIP NEXT INST. IF REALLY 12
	MVI	M,23		;ELSE STORE MAX FOR 24 LINES/PG
LF859:	LXI	H,480		;ASSUME 12 X 40 SCRN
	JNC	LF860		;IF ONLY 12 LINES, SKIP NXT INST
	DAD	H		;ELSE AT LEAST 960 CHARS/SCRN
LF860:	ORA	A		;SET FLAGS
	JZ	LF865		;SKIP NEXT INST IF ONLY 40 COLS
	DAD	H		;ELSE 80 COLS, DOUBLE SCRN SIZE
LF865:	SHLD	LF7A2		;SAVE AS CHARS/SCRN
	LXI	D,VIDBF		;LOAD D,E WITH START OF SCRN
	DAD	D		;ADD NO CHRS/SCRN
	SHLD	LF7A6		;TO GET ABS. SCRN ADDRESS
	LDA	LF794		;GET CURRENT EXTENDED MODE
	ANI	0CH		;MASK MODE BITS
	XRI	0CH		;INVERT THEM
	STA	LF783		;AND SAVE
;
;COME HERE AFTER PROCESSING AN ESCAPE SEQ.
;
LF879:	XRA	A		;GET A ZERO
	STA	LF785		;CLEAR ESCAPE OUTSTANDING FLAG
	RET			;DONE
;
;CHARACTER OUTPUT ENTRY POINT
;
CHROT:	PUSH	H		;SAVE ALL REGISTERS
	PUSH	D		;
	PUSH	B		;
	PUSH	PSW		;
	STA	LF793		;SAVE CHAR TO DISPLAY
	LHLD	LF78F		;GET ABS. CURSOR ADDR
	LDA	LF792		;GET CHAR UNDER CURSOR
	MOV	M,A		;PUT IT BACK
	LXI	H,LF793		;POINT AT CURRENT CHAR
	MOV	A,M		;GET IT BACK
	CPI	1BH		;ESCAPE ?
	JZ	LF94D		;YES - PROCESS ESCAPE
	LDA	LF785		;NO - PREV ESC OUTSTANDING ?
	ORA	A		;SET FLAGS
	JNZ	LF94D		;YES - PROCESS ESCAPE
	MOV	A,M		;GET CHAR AGAIN
	CPI	7FH		;DELETE ?
	JZ	LF93C		;YES - PROCESS
	LDA	LF783		;GET INVERTED STATUS
	ORA	A		;ZERO - E.G. USING ALL 256 CHARS
	JZ	LF8D6		;YES - HANDLE SEPARATELY
	MOV	A,M		;GET CHAR AGAIN
	CPI	0FFH		;PAD CHARACTER ?
	JZ	LF8DF		;SKIP PROCESSING
	ANI	7FH		;MASK PARITY
	MOV	M,A		;SAVE IT THAT WAY
	SBI	20H		;SEE IF CNTL CHAR
	JM	LF929		;WE DON'T DISPLAY CNTL CHARS
	LDA	LF794		;GET EXTENDED STATUS BYTE
	MOV	B,A		;SAVE IN B
	ANI	0CH		;MASK TWO MODE BITS
	CPI	8		;USING STD CHAR SET (0-7F)
	JNZ	LF8D6		;DISPLAY CHAR IF NOT
	MOV	A,B		;ELSE GET STATUS BACK
	ANI	20H		;MASK UPPPER CASE ONLY BIT
	JNZ	LF8D6		;DISPLAY IF USING LOWER CASE
	MOV	A,M		;ELSE GET CHAR AGAIN
	SBI	61H		;SEE IF UPPER CASE
	JM	LF8D6		;YES, PROCESS
	SBI	26		;NO, CONVERT TO UPPER CASE
	JP	LF8D6		;DISPLAY UPPER CASE LETTERS
	ADI	5BH		;CONVERT 7B-7F CNTL CHRS BACK
	MOV	M,A		;AND LEAVE THEM ALONE IN MEMORY
;
;GET HERE TO DISPLAY CHARS
;
LF8D6:	CALL	LFB63		;PUT CHARACTER ON SCREEN
	CALL	RIGHT		;MOVE CURSOR RIGHT 1 POSITION
LF8DC:	CALL	LFB0C		;CALC ABS CUR ADDR FROM ROW, COL
LF8DF:	CALL	LFA95		;TURN CURSOR BACK ON
	POP	PSW		;RESTORE REGISTERS
	POP	B		;
	POP	D		;
	POP	H		;
	RET			;AND GO HOME
;
;ROUTINE TO MOVE CURSOR RIGHT
;
RIGHT:	CALL	LFB26		;ADV. COL. NO.
	CZ	LF8F9		;UPDATE ROW ON OVERFLOW
	LDA	LF791		;GET PROTECT ON/OFF FLAG
	XCHG			;NEW CUR ADDR TO H,L
	ANA	M		;SEE IF THIS CHAR PROT.
	JM	RIGHT		;CUR CAN'T STOP ON PROT. FIELD
	RET			;DONE, CUR ON UPPROT. FIELD
;
;ROUTINE TO DO LINE-FEED (CURSOR DOWN)
;
LINFD:	LXI	H,LF780		;POINT TO CURRENT ROW
LF8F9:	INR	M		;INCREMENT IT
	LDA	LF7A1		;GET MAX ALLOWED ROW
	CMP	M		;OVERFLOW ?
	RP			;NO-DONE
	DCR	M		;OVERFLOW - DCR ROW
	LDA	LF794		;GET EXTENDED STATUS BYTE
	ANI	8CH		;MASK MODE & SCROLL/PG BITS
	JM	LF90D		;JUMP IF IN PAGE MODE
	CPI	0CH		;SEE IF IN GRAPHICS OPT.
	JNZ	LF912		;SCROLL UNLESS IN GRAPHICS
LF90D:	XRA	A		;GET A ZERO
	MOV	M,A		;MAKE IT THE NEW ROW
	INX	H		;POINT TO COLUMN
	MOV	M,A		;GET IT
	RET			;RETURN W/COLUMN IN ACC
;
;COME HERE TO SCROLL SCREEN UP 1 LINE
;
LF912:	LHLD	LF79F		;GET MAX ALLOWED COLUMN
	PUSH	H		;SAVE IT
	XCHG			;AND MOVE TO D,E
	LHLD	LF7A2		;GET NO. CHRS IN CUR FORMAT
	MOV	A,L		;LOW ORDER BYTE TO A
	SUB	E		;SUBTRACT CHARS/LINE
	MOV	C,A		;PUT NO. CHRS - 1 LINE IN B,C
	MOV	B,H		;
	XCHG			;H,L = CHARS/SCREEN
	LXI	D,VIDBF		;GET ADDR OF VIDEO BUFFER
	DAD	D		;H,L = ADDRESS OF SCREEN END
	CALL	LFDDD		;BLOCK MOV BC CHRS FROM HL TO DE
	JMP	LFA31		;CLEAR LAST LINE AND RETURN
;
;PROCESS CONTROL CHARS -- H,L=POINTER TO CURRENT CHARACTER
;
LF929:	XCHG			;CHAR POINTER TO D,E
	LHLD	LF787		;GET ADDR OF ALT. TABLE
	MOV	A,H		;GET HIGH BYTE
	ORA	A		;SET FLAGS
	LDAX	D		;GET CHAR IN ACCUM.
	JZ	LF939		;SKIP NEXT IF USING STD. TABLE
	CALL	LFA11		;ELSE DO SEARCH OF ALT. TABLE
	JNZ	LF945		;AND DISPATCH IF MATCH FOUND
LF939:	LDA	LF793		;GET CURRENT CHARACTER
LF93C:	LXI	H,LFB92		;POINT TO STD. TABLE
	CALL	LFA11		;SEARCH IT
	JZ	LF8DF		;IF NO MATCH FOUND
LF945:	LXI	D,LF8DC		;GET RET POINT FOR CNTL CHR ROUTINES
	PUSH	D		;AND PUT IT ON STACK TOP
	LXI	D,LF781		;LET D,E POINT TO CURSOR COLUMN
	PCHL			;AND DISPATCH TO ROUTINE
;
;COME HERE TO PROCESS ESCAPE SEQUENCE, BOTH ON
;ESC. ITSELF & SUBSEQUENT CHARS.  H,L POINTS A LF793.
;
LF94D:	LXI	D,LF8DC		;GET RETURN ADDR FOR WHEN DONE
	PUSH	D		;PUSH IT ON STACK
	XCHG			;SAVE CURRENT CHAR ADDR IN D,E
	LXI	H,LF785		;POINT TO ESCAPE FLAG
	MOV	A,M		;GET IT
	INR	M		;INCREMENT IT IN MEMORY ONLY
	ORA	A		;SET FLAGS
	RZ			;NO ESC WAS OUTSTANDING, NOW IS
	DCR	A		;ESC WAS OUTSTANDING, DCR OLD FLAG
	INX	H		;POINT TO 2ND CHAR OF ESC. SEQ
	LDAX	D		;GET CHAR UNDER CURSOR
	JNZ	LF960		;SKIP NXT IF ON 3RD OR 4TH CHAR (DCA)
	MOV	M,A		;ALL OTHERS, SAVE 2ND ESC. SEQ CHAR
LF960:	LHLD	LF789		;POINT TO ALT. ESC. TABLE
	MOV	A,H		;GET HIGH ADDRESS BYTE
	ORA	A		;SET FLAGS
	LDAX	D		;GET ESC. SEQ 2ND CHAR
	JZ	LF96F		;USE STD. TABLE
	CALL	LFA11		;ELSE SEARCH ALT. TABLE
	JNZ	LF97D		;EXEC. ROUTINE IF MATCH FOUND
LF96F:	LDA	LF786		;ELSE RESTORE 2ND CHAR OF ESC. SEQ
	ANI	0DFH		;MASK OUT 20H BIT
	LXI	H,ESCTB		;POINT TO ESCAPE TABLE
	CALL	LFA11		;SEARCH IT
	JZ	LF879		;NO MATCH FOUND, CLR ESC. FLAG
LF97D:	LDA	LF794		;GET EXTENDED STATUS BYTE
	LXI	D,LF83A		;RET ADDR TO UPDATE STATUS BYTES
	PCHL			;EXECUTE ESCAPE SUBROUTINE
;
;ROUTINES TO MOVE CURSOR UP/LEFT ONE POSITION
;
UP:	DCX	D		;POINT AT ROW INSTEAD OF COL
LEFT:	LDAX	D		;GET COLUMN (ROW)
	ORA	A		;SET FLAGS
	RZ			;CAN'T BE LESS THAN ZERO, DONE
	DCR	A		;ELSE DECREMENT
LF989:	STAX	D		;AND PUT BACK
	RET			;THEN RETURN
;
;ROUTINE TO DO A CARRIAGE RETURN
;
CRET:	XRA	A		;GET A ZERO
	STA	LF784		;CLEAR INSERT MODE
	JMP	LF989		;STORE ZERO AS COLUMN & RET.
;
;ROUTINES TO TOGGLE THE PROTECT AND INSERT MODES
;
PROT:	LXI	H,LF791		;POINT AT PROTECT ON/OFF FLAG
	JMP	LF99B		;COMPLEMENT IT & RETURN
INTOG:	LXI	H,LF784		;POINT AT INSERT MODE FLAG
LF99B:	MOV	A,M		;GET IT
	CMA			;COMPLEMENT IT
	MOV	M,A		;PUT IT BACK
	RET			;DONE
;
;ROUTINE TO CLEAR SCREEN
;
CLEAR:	LHLD	LF7A2		;GET NO CHRS ON SCREEN
	XCHG			;TO D,E
	LXI	H,VIDBF		;POINT TO START OF BUFFER
LF9A6:	LDA	LF791		;GET PROTECT FLAG
	ANI	80H		;MASK HIGH ORDER BIT
	ANA	M		;AND WITH CHAR
	JM	LF9B1		;DON'T CLEAR PROTECTED
	MVI	M,' '		;ELSE REPLACE WITH SPACE
LF9B1:	INX	H		;INCREMENT POINTER
	DCX	D		;DECR. COUNT OF CHARS TO CLEAR
	MOV	A,D		;SEE IF COUNT IS 0
	ORA	E		;
	JNZ	LF9A6		;NO - DO MORE,ELSE HOME CURSOR
;
;ROUTINE TO HOME CURSOR
;
HOME:	LXI	H,0		;MAKE H,L ZERO
	SHLD	LF780		;SAVE 0 AS BOTH ROW & COL
	RET			;DONE
;
;ROUTINE TO ERASE TO END OF LINE OR FIELD
;
EREOF:	CALL	LF9EE		;GET COUNT OF CHRS TO CLEAR IN C
LF9C2:	LDA	LF791		;GET PROTECT FLAG
	ORA	A		;ZERO ?
	JZ	LF9CE		;YES - CLEAR TO END OF LINE
	MOV	A,M		;NO - GET CHAR
	ORA	A		;SET FLAGS
	JM	LF9D1		;DON'T CLEAR IF PROTECTED
LF9CE:	MVI	A,' '		;ELSE GET SPACE
	MOV	M,A		;AND REPLACE CHAR WITH IT
LF9D1:	INX	H		;INCREMENT POINTER
	DCR	C		;DECR. COUNT
	JNZ	LF9C2		;CONTINUE IF NOT DONE
	RET			;ELSE RETURN
;
;CONTROL-V (TOGGLE INVERSE VIDEO) ROUTINE
;
LF9D7:	LXI	H,LF782		;POINT TO INVERSE VIDEO FLAG
	JMP	LF99B		;TOGGLE IT & RETURN
;
;ROUTINE TO DELETE A CHAR & CLOSE UP LINE
;
CHDEL:	CALL	LF9EE		;SPACES TO END OF FIELD IN C
	LHLD	LF78F		;GET CURRENT CURSOR ADDR
	MOV	D,H		;DUPLICATE IN D,E
	MOV	E,L		;
	INX	H		;POINT TO NEXT CHAR
	CALL	LFDDD		;MOVE LINE UP
	MVI	A,' '		;GET SPACE
	DCX	D		;POINT TO LAST POS. IN FIELD
	STAX	D		;PUT SPACE THERE
	RET			;DONE
;
;ROUTINE TO COMPUTE NO. OF SPACES TO END OF LINE OR
;START OF NEXT PROTECTED FIELD & LEAVE ANS. IN REG. C
;
LF9EE:	LDA	LF791		;GET PROTECT STATUS
	ANI	80H		;MASK 80H BIT
	MOV	D,A		;SAVE IN D
	LHLD	LF78F		;GET CURSOR ADDRESS
	PUSH	H		;SAVE ON STACK
	LDA	LF781		;GET CURRENT COLUMN
	MOV	E,A		;SAVE IN E.
	LXI	B,0		;MAKE B,C ZERO
LF9FF:	LDA	LF79F		;GET MAX ALLOWED COLUMN
	SUB	E		;SUBTRACT CUR COLUMN
	INR	E		;INR CUR COLUMN
	INX	H		;INR CURSOR ADDR
	INR	C		;INR COUNT OF SPACES TO CLR
	DCR	A		;DCR COUNT SPACES LEFT THIS LINE
	JZ	LFA0F		;DONE IF WENT TO END OF LINE
	MOV	A,M		;ELSE GET CHAR AT CUR POSITION
	ANA	D		;SEE IF PROTECTED
	JP	LF9FF		;CONTINUE IF NOT PROTECTED
LFA0F:	POP	H		;RESTORE CUR CURSOR ADDR TO H,L
	RET			;DONE
;
;COMMAND TABLE SEARCH ROUTINE FOR SINGLE CHAR COMMANDS
;
LFA11:	MOV	B,A		;SAVE COMMAND TO LOOK UP IN B
LFA12:	MOV	A,M		;GET TABLE ENTRY
	LXI	D,LF780		;LET D POINT TO ROW,COL
	ORA	A		;SET FLAGS
	RZ			;END OF TABLE, RETN W/ZERO SET
	CMP	B		;ELSE CHECK FOR MATCH
	JNZ	LFA23		;AND INR. PAST ADDR. IF NO MATCH
	INX	H		;MATCH - POINT AT ADDR
	MOV	E,M		;GET LOW ADDR IN E
	INX	H		;POINT TO HIGH
	MOV	D,M		;GET IT IN D
	XCHG			;XCHG - ADDR TO H,L
	ORA	A		;SET FLAGS NON-ZERO
	RET			;AND RETURN
LFA23:	INX	H		;POINT TO LOW ADDR
	INX	H		;POINT TO HIGH ADDR
	INX	H		;POINT TO NEXT TABLE ENTRY
	JMP	LFA12		;AND TEST IT
;
;ROUTINE TO DELETE A LINE
;
DELIN:	CALL	LFA4D		;PUT CUR AT COL. 0 OF CUR LINE
	PUSH	H		;NO. OF COLS. PER LINE
	DAD	D		;H,L POINTS TO 1ST CHAR NEXT LINE
	CALL	LFDDD		;BLK MOVE BC CHARS FROM HL TO DE
LFA31:	POP	B		;RESTORE LINE SIZE TO B,C
	XCHG
	JMP	LFA45		;FILL WITH SPACES
INLIN:	CALL	LFA4D		;B,C = NO CHRS AFTER CURSOR - 1 LINE
	PUSH	H		;MAX COL SIZE
	DAD	D		;ADD LINE LEN TO CURSOR
	DAD	B		;ADD IN NO CHARS AFTR CUR - 1 LINE = END SCRN
	XCHG			;TO D,E (END OF SCREEN)
	DAD	B		;H,L=CUR, B,C=NO CHR AFTER - 1 LINE
	DCX	H		;DCR BY 1 FOR EA CHAR
	DCX	D
	CALL	LFB87		;BLOCK MOVE
	POP	B		;MAX COL SIZE
	INX	H		;POINT TO 1ST CHAR OF "NEW" LINE
LFA45:	MVI	M,20H		;BLANK OUT CHAR
	INX	H		;INR POINTER
	DCR	C		;DCR COUNT
	JNZ	LFA45		;DO TILL DONE
	RET
;
LFA4D:	XRA	A		;GET A ZERO
	STAX	D		;NEW COLUMN
	CALL	LFA5D		;BC=NO CHARRS AFTER CURSOR, DE=-CUR, HL=CUR
	XCHG			;DE = CUR
	LHLD	LF79F		;MAX ALLOWED COL.
	MOV	A,L		;TO A
LFA57:	DCX	B		;DCR B, NO CHRS
	DCR	A		;CONTINUE TILL B,C REDUCED BY 1 LINE
	JNZ	LFA57
	RET
;
LFA5D:	CALL	LFB0C		;UPDATE ABS CURR ADDR
	PUSH	H		;SAVE ON STACK
	XCHG			;AND IN D,E
	LHLD	LF7A6		;GET END OF SCRN ADDR
	MOV	A,D		;NEGATE CURSOR
	CMA
	MOV	D,A
	MOV	A,E
	CMA
	MOV	E,A
	INX	D
	DAD	D		;HL = NO CHARS AFTER CURSOR
	PUSH	H		;SAVE ON STACK
	POP	B		;RESTORE BC (NO CHARS AFTER CUR)
	POP	H		;CURSOR IN HL
	RET
;
;EXTENDED TEXT MODE (UPPER CHAR SET)
;
EXTXT:	ANI	0F3H		;CLEAR MODE BITS
	ORI	04H		;SET TO EXTENDED TEXT
	XCHG
	PCHL
;
;GRAPHICS MODE (ALL 256 BYTES AVAIL)
;
GRAPH:	ORI	0CH		;SET GRAPHICS BITS
	XCHG
	PCHL
;
;ASCII TEXT MODE (LOWER CHAR SET)
;
TXT:	ANI	0F3H		;CLEAR MODE BITS
	ORI	08H		;SET TO TEXT MODE
	XCHG
	PCHL
;
;TOGGLE SCROLL/PAGE MODE
;
SCTOG:	XRI	80H		;INVERT SCROLL BIT
	XCHG
	PCHL
;
;TOGGLE UPPER CASE ONLY/UPPER-LOWER CASE MODE
;
ULTOG:	XRI	20H		;INVERT U/L CASE TOGGLE
	XCHG
	PCHL
;
;TOGGLE INVERSE VIDEO BIT
;
INVRT:	XRI	10H		;INVERT POLARITY BIT
	XCHG
	PCHL
;
;TOGGLE PAGE LENGTH BETWEEN 12/24 LINES
;
PGLEN:	XRI	02H
	XCHG
	PCHL
;
;TOGGLE WIDTH BETWEEN 40/80 CHARS
;
WIDTH:	XRI	01H
	XCHG
	PCHL
;
LFA95:	LHLD	LF78F		;GET CURSOR ADDRESS
	MOV	A,M		;GET CHAR
	STA	LF792		;SAVE IT
	ORI	80H		;TURN CURSOR ON
	MOV	M,A		;PUT IT BACK
	LDA	LF783		;GET STATUS BYTE
	ORA	A		;SET FLAGS
	RNZ
	MVI	M,7FH		;IN GRAPHICS MODE, DEL IS CURSOR
	RET
;
;CLEAR ALL TABS
;
CATAB:	LXI	H,LF795		;POINT TO 80 BIT TAB TABLE
	MVI	B,0AH		;10 BYTES OF 8 TAB STOPS EA.
	XRA	A		;GET ZERO
LFAAD:	MOV	M,A		;CLEAR 8 TABS
	INX	H		;POINT TO NEXT BLOCK OF 8 TABS
	DCR	B		;DCR COUNT
	JNZ	LFAAD		;CONTINUE TILL DONE
	JMP	LF879		;THEN CLR ESC FLAG & GO HOME
;
;SET OR CLEAR TAB STOPS
;
SCTAB:	CALL	LFAC4		;GET TAB BYTE, BIT NO. & BYTE COUNT
	XRI	80H		;CHANGE 80H BIT
LFABB:	RRC
	DCR	B		;DCR COUNT OF BIT OFFSET
	JNZ	LFABB		;KEEP ROTATING IF NOT DONE
	STAX	D		;PUT BYTE BACK
	JMP	LF879		;CLEAR ESC. FLAG & GO HOME
;
LFAC4:	LDA	LF781		;GET CURRENT COLUMN TO H
	MOV	H,A		;TO H
	INR	H		;INITIALIZATION FOR FOLLOWING ROUTINE
	LXI	D,LF795		;POINT TO TAB TABLE
LFACC:	MVI	C,8		;NO TAB STOPS PER BYTE IN TABLE
LFACE:	DCR	H		;POINT TO PREV. COLUMN
	JZ	LFADA		;JUMP IF COL. EQ. ZERO
	DCR	C		;ELSE DCR. BIT COUNT
	JNZ	LFACE		;AND REPEAT IF NOT ZERO
	INX	D		;BIT COUNT = 0, GET NEXT BYTE
	JMP	LFACC		;GO UNTIL COL. EQ. ZERO
LFADA:	LDAX	D		;GET TAB TABLE BYTE
	MOV	B,C		;SAVE BIT COUNT
LFADC:	RLC
	DCR	C		;DCR BIT COUNT
	JNZ	LFADC		;DO UNTIL BIT COUNT EQ. ZERO
	RET
;
;TAB TO NEXT TAB STOP OR UNPROTECTED FIELD
;
TAB:	XRA	A		;GET A ZERO
	STA	LF7A4		;CLEAR PROT. FIELD ENCOUNTERED FLAG
LFAE6:	CALL	LFB26		;ADVANCE 1 POSITION
	JNZ	LFAF1		;JUMP IF NOT ON LAST COL. OF LINE
	INR	M		;ELSE INR. ROW
	CMP	M		;ROW = MAX. ALLOWED ROW ?
	JM	LF90D		;YES, OFF SCREEN, DO HOME
LFAF1:	LDA	LF791		;GET PROTECT FIELD ON-OFF FLAG
	XCHG
	ANA	M		;SET SIGN FLAG
	MOV	A,M		;GET CHAR UNDER CURSOR
	LXI	D,LF7A4		;POINT TO PROTECTED FIELD ENCOUNTERED FLAG
	JP	LFB01		;IF CURRENT POSITION NOT PROTECTED
	STAX	D		;ELSE SET PROT. FIELD ENCOUNTERED FLAG
	JMP	LFAE6		;AND TRY NEXT COL.
LFB01:	LDAX	D		;SEE IF PROT FIELD PREV. ENCOUNTERED
	ORA	A
	RM			;YES, NOW ON 1ST UNPROT AFTER PROTECTED FIELD
	CALL	LFAC4		;SEE IF TAB STOP AT CUR. POSITION
	ORA	A		;SET FLAGS
	RM			;DONE IF TAB STOP SET
	JMP	LFAE6		;TAB STOP NOT SET & STILL IN UNPROT FIELD
;
;UPDATE ABSOLUTE CURSOR ADDR
;
LFB0C:	LHLD	LF79F		;MAX. ALLOWED COLUMN
	XCHG
	LHLD	LF780		;CUR ROW, COLUMN
	MOV	C,H		;DUPE IN B,C
	MOV	B,L
	LXI	H,VIDBF		;POINT TO DISPLAY BUFFER
	INR	B		;INITIALIZE LOOP
LFB19:	DCR	B		;FOR EA. ROW AFTER FIRST
	JZ	LFB21
	DAD	D		;ADD NO. OF COLS/ROW TO SCREEN
	JMP	LFB19		;UNTIL DONE
LFB21:	DAD	B		;THEN ADD CURRENT COL. NO
	SHLD	LF78F		;AND SAVE RESULT = NEW CURSOR ADDR
	RET
;
;BUMP CURSOR POSITION BY 1
;
LFB26:	LHLD	LF78F		;GET CUR ADDR
	INX	H		;INCREMENT IT
	SHLD	LF78F		;PUT IT BACK
	XCHG
	LXI	H,LF781		;POINT TO CUR. COL. NO
	INR	M		;INCREMENT IT
	LDA	LF79F		;GET MAX ALLOWED COL.
	SUB	M		;COMPARE TO NEW COLUMN
	RNZ
	MOV	M,A		;GONE OFF LINE, MAKE COL=0
	DCX	H		;POINT TO CURRENT ROW
	LDA	LF7A1		;GET MAX ALLOWED ROW IN A
	RET
;
;DIRECT CURSOR ADDRESSING
;
LFB3D:	LXI	H,LF785		;ESCAPE SEQ. FLAG
	LXI	D,LF780		;CURSOR ROW
	LDA	LF793		;CUR. CHAR
	SUI	20H
	MOV	B,A		;SAVE CURRENT CHAR
	MOV	A,M		;GET ESC. FLAG
	SUI	3		;3RD CHAR OF ESC. SEQ ?
	RM			;NO, 1ST OR 2ND
	JNZ	LFB59		;IF 4TH CHAR OF ESC SEQ
	LDA	LF7A1		;MAX ALLOWED ROW
LFB53:	STAX	D		;SAVE AS CURRENT ROW
	CMP	B		;SEE IF SAME AS STRED CHAR
	RM			;DONE IF STORED CHAR > MAX. ROW
	MOV	A,B		;ELSE GET STORED CHAR
	STAX	D		;MAKE IT CUR ROW
	RET			;DONE
;
LFB59:	MVI	M,0		;CLEAR ESC FLAG
	LDA	LF79F		;GET MAX ALLOWED COL
	INX	D		;POINT TO CUR COL
	DCR	A		;DCR MAX ALLOWED COL
	JMP	LFB53		;UPDATE COL
;
;PUT CHAR ON SCREEN
;
LFB63:	LHLD	LF78F		;GET CUR ADDR
	PUSH	H		;SAVE ON STACK
	LDA	LF784		;GET INSERT MODE SWITCH
	ORA	A		;SET FLAGS
	JZ	LFB7A		;IF NOT USING INSERT
	CALL	LF9EE		;COMPUTE SPACES TO END OF FIELD
	DCX	B		;DCR BY 1
	DAD	B		;ADD TO H,L = END ADDR
	MOV	D,H		;DUPE H,L IN D,E
	MOV	E,L
	DCX	D		;DCR D,E BY 1
	XCHG
	CALL	LFB87		;MOVE RIGHT
LFB7A:	POP	H		;RESTOR CURSOR ADDR
	LDA	LF782		;GET CURSOR ON-OFF FLAG
	ANI	80H		;MASK REV. VIDEO BIT
	MOV	B,A		;SAVE IN B
	LDA	LF793		;GET CHAR
	ORA	B		;TURN CURSOR ON (MAYBE)
	MOV	M,A		;STORE CHAR
	RET
;
;BLOCK MOVE B,C CHARS FROM H,L TO D,E
;
LFB87:	MOV	A,C
	ORA	B
	RZ
	MOV	A,M
	STAX	D
	DCX	H
	DCX	D
	DCX	B
	JMP	LFB87
;
;CONTROL CODE TABLE FOR VIDEO DISPLAY
;
LFB92:	DB	0DH
	DW	CRET
	DB	0AH
	DW	LINFD
	DB	0BH
	DW	UP
	DB	0CH
	DW	RIGHT
	DB	08H
	DW	LEFT
	DB	1EH
	DW	HOME
	DB	1AH
	DW	CLEAR
	DB	15H
	DW	EREOF
	DB	16H
	DW	LF9D7
	DB	09H
	DW	TAB
	DB	7FH
	DW	CHDEL
	DB	14H
	DW	INTOG
	DB	04H
	DW	DELIN
	DB	05H
	DW	INLIN
	DB	10H
	DW	PROT
	DB	0
;
;ESCAPE SEQUENCE TABLE FOR VIDEO DISPLAY
;
ESCTB:	DB	1DH
	DW	LFB3D
	DB	'I'
	DW	SCTAB
	DB	09H
	DW	CATAB
	DB	'T'
	DW	TXT
	DB	'E'
	DW	EXTXT
	DB	'G'
	DW	GRAPH
	DB	'S'
	DW	SCTOG
	DB	'U'
	DW	ULTOG
	DB	'V'
	DW	INVRT
	DB	'L'
	DW	PGLEN
	DB	'C'
	DW	WIDTH
	DB	0
MONTR:	LXI	SP,STATS
	MVI	A,0AAH		;INITIALIZATION FOR 8251 IN SIO CARD
	OUT	3
	CMA
	OUT	3
	CMA
	OUT	3
	MVI	A,27H
	OUT	3
	CALL	INITL		;INITIALIZE VIO
	LXI	H,LFC29		;SIGNON MESSAGE
	CALL	LFFB6		;PRINT IT
LFBFC:	LXI	SP,STATS
	CALL	CRLF		;DO CR/LF
	MVI	A,'?'		;PROMPT
	CALL	CHROT
	CALL	GTCHR		;WAIT FOR INPUT
	MOV	B,A		;SAVE CHAR IN B
	LXI	D,LFBFC		;PUSH RETURN ADDR ON STACK
	PUSH	D
	LHLD	LF78B		;ADDR OF ALTERNATE COMMAND TABLE
	MOV	A,H
	ORA	A		;SEE IF IN USE
	MOV	A,B		;RESTORE INPUT CHAR TO A
	JZ	LFC1E		;USE STD. TABLE
	CALL	LFA11		;USE ALT. TABLE
	JNZ	LFC28		;EXECUTE CMD IF MATCH FOUND
LFC1E:	MOV	A,B		;ELSE RESTORE CHAR
	LXI	H,LFFC0		;AND NOW TRY STD. TABLE
	CALL	LFA11
	RZ			;NO MATCH
	MVI	B,1
LFC28:	PCHL			;GO TO ROUTINE
;
;SIGN-ON MESSAGE & COPYRIGHT NOTICE
;
LFC29:	DB	'IMSAI SMP/80.0'
	DB	0
	DB	'COPYRIGHT 6/77'
;
;JUMP COMMAND - JUMPS TO MEMORY ADDRESS
;
JUMP:	POP	D		;REMOVE RET. ADDR FROM STACK
CALLM:	CALL	LFF5B		;GET ADDR TO JMP TO IN H,L
	PCHL			;GO TO IT
ENTR:	CALL	LFF5B		;GET ADDR IN H,L
LFC4E:	CALL	CRLF		;START ON NEW LINE
	CALL	LFCB6		;OUTPUT ADDR IN H,L TO SCREEN
	MOV	A,M		;GET CHAR
	MOV	E,A		;SAVE IN A
	CALL	LFCAD		;DUMP IT FOLLOWED BY A SPACE
	XCHG
	CALL	LFF5E		;GET HEX VALUE IN H,L
	XCHG
	MOV	M,E		;STORE NEW VALUE IN MEMORY
	DCX	H		;POINT TO PREV. LOCATION
	CPI	0AH		;CR/LF TYPED ?
	RZ			;YES, DONE
	CPI	'-'		;'-' TYPED ?
	JZ	LFC4E		;YES, DO PREV. LOCATION
	INX	H		;POINT TO ORIG. LOCATION
	INX	H		;POINT TO NEXT LOCATION
	JMP	LFC4E		;DO IT
DUMP:	CALL	LFD20		;GET STARTING ADDR IN H,L
LFC70:	LDA	LF794		;GET STATUS BYTE
	RRC			;SHIFT NO LINES/SCREEN INTO CARRY
	RRC
	MVI	D,0CH		;ASSUME 12
	JC	LFC7C		;WAS INDEED 12
	MVI	D,18H		;WAS 24
LFC7C:	CALL	CRLF		;DO CR/LF
	IN	3		;TERMINATE ON ANY CHAR
	ANI	02H
	RNZ
	MVI	E,8		;ASSUME 8 BYTES/LINE
	LDA	LF794		;GET STATUS
	RRC			;SHIFT WIDTH INTO CARRY
	JC	LFC8F		;JUMP IF 40 COL. SCREEN
	MVI	E,16		;80 COLS, USE 16 BYTES/LINE
LFC8F:	CALL	LFCB6		;WRITE ADDR FOLLOWED BY SPACE
LFC92:	MOV	A,M		;GET BYTE
	CALL	LFCAD		;DUMP BYTE FOLLOWED BY SPACE
	INX	H		;INR POINTER
	DCX	B		;DCR COUNT
	MOV	A,B		;TEST FOR DONE
	ORA	C
	RZ			;DONE
	DCR	E		;DCR BYTES THIS LINE
	JNZ	LFC92		;MORE IF NOT DONE
	DCR	D		;DCR LINES THIS PAGE
	JNZ	LFC7C		;MORE LINES IF NOT DONE
	CALL	GTCHR		;ELSE PAUSE FOR ANY CHAR
	JMP	LFC70		;THEN DO NEXT PAGE
ESCAP:	CALL	GTCHR
	RET
LFCAD:	CALL	LFF9A		;MOVE H TO A
	MVI	A,' '
	CALL	CHROT
	RET
LFCB6:	MOV	A,H		;MOV H TO A
	CALL	LFF9A		;OUTPUT AS HEX ASCII
	MOV	A,L		;MOVE L TO A
	CALL	LFCAD		;OUTPUT AS HEX ASCII
	RET
PROTM:	INR	B
UNPRT:	CALL	LFF3A
	MOV	A,D
	ANI	0FCH
	ORA	B
	MOV	D,A
	MOV	A,H
	ANI	0FCH
	ORA	B
LFCCC:	OUT	0FEH
	CMP	D
	RZ
	ADI	4
	JMP	LFCCC
HEXLD:	CALL	GTCHR
	SBI	':'
	JNZ	HEXLD
	MOV	D,A
	CALL	LFD04
	ORA	A
	RZ
	MOV	B,A
	CALL	LFD04
	MOV	H,A
	CALL	LFD04
	MOV	L,A
	CALL	LFD04
LFCEF:	CALL	LFD04
	MOV	M,A
	INX	H
	DCR	B
	JNZ	LFCEF
	CALL	LFD04
	JZ	HEXLD
	MVI	A,'C'
	CALL	CHROT
	RET
LFD04:	CALL	GTCHR
	CALL	LFF74
	JC	LFE07
	ADD	A
	ADD	A
	ADD	A
	ADD	A
	MOV	E,A
	CALL	GTCHR
	CALL	LFF74
	JC	LFE07
	ADD	E
	MOV	E,A
	ADD	D
	MOV	D,A
	RET
LFD20:	CALL	LFF3A
	PUSH	PSW
	MOV	A,E
	SUB	L
	MOV	C,A
	MOV	A,D
	SBB	H
	MOV	B,A
	INX	B
	POP	PSW
	RET
MOVEM:	CALL	LFDD7
LFD30:	CALL	LFDDD
	RET
FILL:	CALL	LFDD7
	MOV	A,E
	MOV	M,A
	DCX	B
	MOV	D,H
	MOV	E,L
	INX	D
	JMP	LFD30
MEMCK:	CALL	LFD20
	DCX	B
LFD44:	XRA	A
	MOV	D,M
LFD46:	MOV	M,A
	CMP	M
	JNZ	LFD5D
	DCR	A
	JNZ	LFD46
	MOV	M,D
	IN	3
	ANI	02H
	RNZ
	INX	H
	DCX	B
	MOV	A,B
	ORA	C
	JNZ	LFD44
	RET
LFD5D:	INX	H
	MOV	E,A
	CALL	LFF8D
	MOV	A,E
	JMP	LFF89
INPUT:	DCR	B
OUTPT:	CALL	LFF3A
	MOV	A,B
	RLC
	RLC
	RLC
	XRI	08H
	ORI	0D3H
	MOV	D,L
	LHLD	LF78D
	MOV	M,A
	CMP	M
	RNZ
	PUSH	H
	INX	H
	MOV	M,D
	INX	H
	MVI	M,0C9H
	LXI	H,LFD87
	XTHL
	MOV	A,B
	ORA	A
	MOV	A,E
	PCHL
LFD87:	RNZ
	CALL	LFCAD
	RET
LFD8C:	CALL	LFF5B
	SHLD	LF78D
	RET
MEMCP:	CALL	LFDD7
LFD96:	LDAX	D
	CMP	M
	INX	H
	INX	D
	JZ	LFDA5
	CALL	LFF8D
	XCHG
	CALL	LFF90
	XCHG
LFDA5:	DCX	B
	MOV	A,B
	ORA	C
	RZ
	IN	3
	ANI	02H
	RNZ
	JMP	LFD96
SERCH:	CALL	LFDD7
	PUSH	H
	LXI	H,0FFFFH
	CPI	0AH
	CNZ	LFF5B
	XTHL
LFDBE:	MOV	A,M
	XTHL
	ANA	H
	CMP	D
	XTHL
	INX	H
	JNZ	LFDCF
	MOV	A,M
	XTHL
	ANA	L
	CMP	E
	XTHL
	CZ	LFF85
LFDCF:	DCX	B
	MOV	A,B
	ORA	C
	JNZ	LFDBE
	POP	B
	RET
LFDD7:	CALL	LFD20
	JMP	LFF4A
LFDDD:	MOV	A,B
	ORA	C
	RZ
	MOV	A,M
	STAX	D
	DCX	B
	INX	H
	INX	D
	JMP	LFDDD
GOXEQ:	DCR	B
LDTAP:	PUSH	B
	CALL	LFF3A
	MOV	A,D
	ORA	E
	JZ	LFE04
	PUSH	H
	PUSH	D
	CALL	LFF5B
	PUSH	H
	CALL	LFE66
	JNZ	LFE12
	POP	PSW
	POP	PSW
	POP	PSW
	JMP	LFE12
LFE04:	CALL	LFE66
LFE07:	MVI	A,'T'
	JZ	LFE12
LFE0C:	CALL	CHROT
	JMP	LFBFC
LFE12:	POP	B
	POP	H
	POP	D
	PUSH	B
	PUSH	H
	PUSH	D
	MOV	A,L
	SUB	E
	MOV	L,A
	MOV	A,H
	SBB	D
	MOV	H,A
	DAD	H
	MOV	C,H
	INR	C
LFE21:	CALL	LFEC2
	CPI	81H
	JNZ	LFE07
	CALL	LFEC2
	MOV	B,A
	LXI	H,0
LFE30:	CALL	LFED0
	STAX	D
	INX	D
	DCR	B
	JNZ	LFE30
	PUSH	D
	XCHG
	CALL	LFF07
	MOV	H,L
	MOV	L,A
	DAD	D
	MOV	A,H
	ORA	L
	MVI	A,'C'
	CNZ	CHROT
	JNZ	LFE50
	MVI	A,'*'
	CALL	CHROT
LFE50:	POP	D
	DCR	C
	JNZ	LFE21
	CALL	CRLF
	MVI	C,3
LFE5A:	POP	H
	CALL	LFCB6
	DCR	C
	JNZ	LFE5A
	POP	PSW
	RAR
	RC
	PCHL
LFE66:	CALL	LFE8E
	CALL	LFEC2
	CPI	1
	RNZ
	CALL	LFEC2
	MVI	C,5
LFE74:	CALL	LFEC2
	CALL	CHROT
	DCR	C
	JNZ	LFE74
	MVI	C,3
LFE80:	CALL	LFF07
	XTHL
	PUSH	H
	DCR	C
	JNZ	LFE80
	CALL	LFF07
	XRA	A
	RET
LFE8E:	CALL	LFEF6
	MVI	B,1FH
LFE93:	CALL	LFEC2
	CPI	0E6H
	MVI	A,'I'
	JNZ	LFE0C
	DCR	B
	JNZ	LFE93
	RET
LFEA2:	PUSH	PSW
LFEA3:	IN	3
	ANI	04H
	JZ	LFEA3
	POP	PSW
	OUT	0
	RET
GNSYN:	CALL	LFF5B
	MVI	A,10H
	OUT	3
LFEB5:	MVI	A,0E6H
	CALL	LFEA2
	IN	3
	ANI	02H
	RNZ
	JMP	LFEB5
LFEC2:	IN	3
	RRC
	RRC
	JC	LFBFC
	RRC
	JNC	LFEC2
	IN	0
	RET
LFED0:	CALL	LFEC2
	PUSH	B
	MOV	C,A
	MVI	B,0
	DAD	B
	POP	B
	RET
ALIGN:	CALL	GTCHR
	CALL	LFEF6
LFEE0:	LXI	H,VIDBF
	LXI	D,01E1H
LFEE6:	DCX	D
	MOV	A,D
	ORA	E
	JZ	LFEE0
	MVI	M,7FH
	CALL	LFEC2
	MOV	M,A
	INX	H
	JMP	LFEE6
LFEF6:	MVI	A,60H
	OUT	3
LFEFA:	CALL	LFEC2
	CPI	0E6H
	JNZ	LFEFA
	MVI	A,' '
	OUT	3
	RET
LFF07:	CALL	LFEC2
	MOV	L,A
	CALL	LFEC2
	MOV	H,A
	RET
GTCHR:	CALL	KEYIN
	CPI	3
	JZ	MONTR
	CALL	CHROT
	CPI	0DH
	CZ	CRLF
	RET
KEYIN:	IN	3
	ANI	02H
	JZ	KEYIN
	IN	2
	ANI	7FH
	RET
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
LFF3A:	CALL	LFF5B
	MOV	D,H
	MOV	E,L
	CPI	0AH
	RZ
	CPI	','
	JZ	LFF4A
	CPI	' '
	RNZ
LFF4A:	XCHG
	CALL	LFF5B
	XCHG
	RET
;
;CARRIAGE RETURN/LINFEED ROUTINE
;
CRLF:	MVI	A,0DH
	CALL	CHROT
	MVI	A,0AH
	CALL	CHROT
	RET
LFF5B:	LXI	H,0
LFF5E:	CALL	GTCHR
	PUSH	PSW
	CALL	LFF74
	JNC	LFF6A
	POP	PSW
	RET
LFF6A:	DAD	H
	DAD	H
	DAD	H
	DAD	H
	ADD	L
	MOV	L,A
	POP	PSW
	JMP	LFF5E
LFF74:	SUI	30H
	RC
	CPI	0AH
	JC	LFF83
	SUI	11H
	RC
	ADI	0AH
	CPI	10H
LFF83:	CMC
	RET
LFF85:	CALL	LFF8D
	MOV	A,M
LFF89:	CALL	LFF9A
	RET
LFF8D:	CALL	CRLF
LFF90:	DCX	H
	CALL	LFCB6
	MOV	A,M
	CALL	LFCAD
	INX	H
	RET
LFF9A:	PUSH	PSW
	RRC
	RRC
	RRC
	RRC
	CALL	LFFA7
	POP	PSW
	CALL	LFFA7
	RET
LFFA7:	ANI	0FH
	ADI	90H
	DAA
	ACI	40H
	DAA
	CALL	CHROT
	RET
	CALL	CRLF
LFFB6:	MOV	A,M
	ORA	A
	RZ
	CALL	CHROT
	INX	H
	JMP	LFFB6
LFFC0:	DB	'H'
	DW	HEXLD
	DB	'R'
	DW	LFD8C
	DB	'G'
	DW	GNSYN
	DB	'A'
	DW	ALIGN
	DB	'V'
	DW	MEMCP
	DB	'I'
	DW	INPUT
	DB	'O'
	DW	OUTPT
	DB	'T'
	DW	MEMCK
	DB	'J'
	DW	JUMP
	DB	'C'
	DW	CALLM
	DB	'D'
	DW	DUMP
	DB	'E'
	DW	ENTR
	DB	'M'
	DW	MOVEM
	DB	'F'
	DW	FILL
	DB	'U'
	DW	UNPRT
	DB	'P'
	DW	PROTM
	DB	'L'
	DW	LDTAP
	DB	'S'
	DW	SERCH
	DB	'X'
	DW	GOXEQ
	DB	1BH		;1BH = ESCAPE
	DW	ESCAP
	DB	0
	DB	'VI0'