PGM 8086 MONITOR
       TTL  MONITOR2
       REL
*
*   This version allows Tripos to start at absolute
*   location #500
*
*
BEGIN EQU $
*
*
*
CLKCTL   EQU #B6               SET UP TIMER 2 AS CLOCK
TIMCTL   EQU #D6               ADD OF TIMER CONTROL
TIM2     EQU #D4               ADD OF TIMER 2
CNCTL    EQU #DA               ADD OF ONBOARD USART
MODE     EQU #4E               USART  AS VDU
CMD      EQU #27               SET USART OFF
INT3     EQU #CC               INT3 COMMAND
*
*
UIO0   EQU     #B0             BUFFER OF USART 0
UST0   EQU     #B1             STATUS OF USART 0
UIO1   EQU     #B2
UST1   EQU     #B3
UIO2   EQU     #B4
UST2   EQU     #B5
UIO3   EQU     #B6
UST3   EQU     #B7
*
*
*
*
* TABLE OF VARIOUS BAUD RATES
*
*
RATET  EQU $
B38400 DW 2
B19200 DW 4
B9600  DW 8
B4800  DW 16
B2400  DW 32
B1200  DW 64
B600   DW 128
B300   DW 256
B150   DW 512
B110   DW 698
B75  DW 1024
NRATES EQU $-RATET             NUMBER OF RATES IN TABLE
*
*
*
*
*
*
*SET UP SOME CHARACTERS
*
*
*
CR EQU #D
LF EQU #A
ESC EQU #1B
BRCHR EQU #1B
*
*
*
*
CONST EQU #DE                  ADD OF CONSOLE STATUS
CONDR EQU #DC                  ADD OF INPUT-OUTPUT OF CONSOLE
TRDY  EQU 1                    DATA FOR CONSOLE
RBR   EQU 2                    CONSOLE READ READY
*
*
*
*CONSTANT DEFINITIONS
*
*
*
PRTY0 EQU #7F                  MASK TO BLANK OFF PARITY
*RSAV EQU --                   START ADD OF SAVED REGS-DEFINED LATER
*TABLE EQU --                  START OF RECOGNISED SYMBOLS-LATER
*CTAB EQU --                   START OF RECOGNISED COMMANDS
*NCMDS EQU --                  NO OF RECOGNISED COMMANDS
*CADR  EQU --                  START OF COMMAND ADDRESSES
*LSGNON EQU --                 LENGTH OF SIGN ON MESSAGE-DEFINED LATER
MSEG EQU #40                    MONITOR DATA SEGMENT AT #400
*MSEG EQU #500                  FOR TESTS AT 4000
LMSEG DW MSEG                  START OF MONITOR TABLES-DS,SS&ES
MSTAK EQU #80                  START OF MONITOR STACK
TOPINTLOC   EQU   #400
MCSEG EQU #FF80               START OF CODE SEG- TOP OF MEM-ROM (#FF800)
*MCSEG EQU #400                 TEMP FOR TESTS
*
       EJT
RTAB
       DB "SPSSCSIPFSESDSDISIBPDXCXBXAXCOSTS1S2#1#2ID"
LTAB EQU $-RTAB
*
*
*
SPSAV EQU 0
SSSAV EQU 2
CSSAV EQU 4
IPSAV EQU 6
FSSAV EQU 8
ESSAV EQU 10
DSSAV EQU 12
DISAV EQU 14
SISAV EQU 16
BPSAV EQU 18
DXSAV EQU 20
CXSAV EQU 22
BXSAV EQU 24
AXSAV EQU 26
SSCNTR EQU 28                  NUMBER OF CALLS BEFORE DISPLAYS
SSTEP EQU 30
S1 EQU 32
S2 EQU 34
STEPCNT EQU 36                 STEPCOUNTER TO BE USED
INTPRES EQU 38                 WE ARE IN MONITOR FOLLOWING AN INT
INTDIS  EQU 40                 IF INTERRUPTS ARE TO BE DISABLED BEFORE RETURN
CONSPD  EQU 42                 CURRENT VALUE FROM SPEED TABLE
TABLE EQU 44                   TOP OF RECOGNISED SYMBOLS
*
*
COMMBASE EQU #B0
CONIN    EQU CONDR
DELAYTIME EQU 2
*
*
*
*
*
CTAB    DB "!"
       DB "R"
       DB "M"
       DB "I"
       DB "G"
       DB "D"
       DB "L"
       DB "E"
       DB "X"
       DB "C"
       DB "F"
       DB "V"
NCMDS EQU $-CTAB               NO OF RECOGNISED COMMANDS
*
*
*
CADR
       DW SCMD                 TTY SPEED COMMAND-CALLED BY B
       DW RCMD                 RCMD-RETURN TO USER PROG
       DW MCMD                 MCMD
       DW ERROR                ICMD
       DW GCMD                 GO COMMAND
       DW DCMD                 DCMD
       DW LOAD                 LCMD
       DW RVIEW                REG DISPLAY COMMAND
       DW XCMD                 REGISTER DISPLAY AND CHANGE
       DW CCMD                 MEMORY DISPLAY AND CHANGE
       DW FCMD                 FAST CONNECTION TO 1270
       DW VCMD                 SET UP 1270 CONNECTION THEN AS FCMD
*
*
*
*
SGNON
     DB 14,CR,LF,"RL8086 MON",CR,LF
IPMES   DB 6,"IP/CS="
AXMES   DB 4,",AX="
BPMES   DB 4,",BP="
SPMES   DB 4,",SP="
FSMES   DB 4,",FS="
SIMES   DB 4,",SI="
BXMES  DB 4,",BX="
DIMES  DB 4,",DI="
LSGNON EQU $-SGNON             LENGTH OF SIGN ON MESSAGE
*      MACRO DEFINITIONS
*
*
****************************************************************
*
*
*
*
PUT MAC
:@
       MOV AL,!:1
       CALL ECHO               OUTPUT THE CH
   EMP
*
*
SRET MAC
:@
       STC                     SET CARRY FOR SUCCESS
       RET
    EMP
*
*
*
FRET  MAC
:@
       CLC                     CLEAR FOR FAILURE
       RET
   EMP
*
*
*
WRITE MAC
:@
       MOV SI,!:1
       CALL WRITES
       EMP
*
*
       EJT
       ORG BEGIN+#100
*
*
*
**************************************************************
*
*
START
       JMPS START1-BEGIN,MCSEG SET UP CORRECT IP&CS
START1
       MOV   DX,!MSEG          NOTE THAT DX CANNOT BE SEEN AFTER RESET
       MOV   DS,DX             RELOAD MONITOR DATA SEGMENT
       MOV   AXSAV,AX          SAVE ALL THE REGISTERS
       MOV   BXSAV,BX          FOLLOWING
       MOV   CXSAV,CX          A RESTART
       MOV   BPSAV,BP
       MOV   SISAV,SI          INCLUDE STACK
       MOV   DISAV,DI
       MOV   SPSAV,SP
       MOV   FSSAV,!0          CLEAR THE USERS FLAGS
       MOV   DSSAV,DX          SET UP SEGMENTS
       MOV   ESSAV,DX          TO POINT TO MONITOR SEGEMENTS
       MOV   CX,!7             CLEAR THE REST OF THE FLAGS
       MOV   SI,!SSCNTR        IN THE MONITOR TABLE
START3  MOV   (SI),!0          CLEAR
       ADD   SI,!2             TO TOP OF TABLE
       LOOP  START3
*
       MOV   AX,!0             SET UP THE INTERRUPT
       MOV   DS,AX             LOCATIONS IN THE BOTTOM
       MOV   SI,AX             OF MEMORY
       MOV   BX,!INTENT        THIS IS THE DEFAULT TRPA LOCATION
       MOV   AX,!MCSEG         AND THIS IS MONITOR CODE SEGMENT
START2
       MOV   (SI),BX
       MOV   2(SI),AX
       ADD   SI,!4
       CMP   SI,!TOPINTLOC
       JL    START2
*
       OUT COMMBASE+#F          RESET 4 CHANNEL EXPANSION BOARD
*
       MOV AX,!MSEG            START OTHER SEGS AT FF800
       MOV SS,AX
       MOV AX,!MCSEG
       MOV DS,AX
       MOV ES,AX
       MOV SP,!MSTAK           START MONITOR STACK HERE
       CLI                     TEMP TURN OFF INTS
*
*
*
       MOV BX,B4800
       MOV CONSPD,BX[SS]
       CALL TTYON              SET UP CONSOLE
*
*
MSGL
       WRITE   SGNON
*
*
*
*
*
****************************************************************
*
*
*****************************************************************
*
*
*      COMMAND RECOGNISING ROUTINE
*
*
****************************************************************
*FUNCTION: GETCM
*INPUTS : NONE
*OUTPUTS : NONE
*CALLS : GETCH,ECHO,EEROR
*DESTROYS : A,C,DI,SI,FFS
*DESCRIPTION:GETM RECIEVES AN INPUT CH FROM THE USER AND TRIES TO LOCATE
*      THIS CH IN THE COMMAND CHARACTER TABLE . IF SUCCESSFUL,
*      THE ROUTINE CORRESPONDING TO THIS CH IS SELECTED FROM
*      A TABLE OF COMMAND ROUTINE ADDRESSES, AND CONTROL IS
*      TRANSFERRED . IF NO MATCH THEN ERROR.
*
*
*
GETCM   MOV    SP,!MSTAK     ALWAYS WANT TO RESET SP TO MONITOR
       MOV AX,!MSEG
       MOV SS,AX
       MOV AX,!MCSEG           NB SCAW USES ES
       MOV DS,AX
       MOV ES,AX
       PUT   "."               PROMPT CH TO TTY
       CALL    GETCH           COMMAND CH TO A
       CALL    ECHO            BACK TO USER
       CMP     AL,!ESC
       JNE     GCM20
       MOV     AX,INTPRES[SS]     IF INTERRUPT PRESENT
       CMP     AX,!0           AND ESC HIT
       JE     GCM20            THEN RETURN TO USER
       JMP     INTRES          ELSE IGNORE
GCM20
       MOV     CX,!NCMDS     DI GETS LOOP & INDEX COUNT
       MOV     DI,!CTAB      DI POINTS INTO COMM TABLE
       CLD                     MAKE SURE INCREMENTS
       REP                     LOOP THRO CX COMMANDS
       SCAB                    DOES IT MATCH
       JE  GCM10               OK FOUND IT
       JMP  ERROR              COMM IS ILLEGAL
GCM10
       MOV  SI,!NCMDS-1
       SUB SI,CX
       SHL SI                  EACH BIT IS 2 BYTES LONG
       CALLI CADR(SI)          NEXT INSTR COMES FROM COMM ROUTINE
       JMP GETCM               BACK FOR NEXT COMMAND
*
*
*
*
***********************************************************************
*
* ROUTINE : DUMP
* INPUTS  : NONE
* OUTPUTS : NONE
* DESTROYS : A,BP,SI,CX
* DESCRIPTION : READS TWO HEX NUMBERS AND DUMPS THE MEMORY OFFSET
*      BY S1 (USUALLY DEFAULTED TO USERS DI ).HALTS IF
*      ON 16TH LINE BOUNDARY TO DISPLAY THE PAGE-CR CAUSES
*      RETURN TO MONITOR ANY OTHER CH GIVES NEXT PAGE.
*
*
*
DCMD
       PUSH ES                 USED AS DUMP SEGMENT REG
       PUSH DS
       MOV AX,!MSEG
       MOV DS,AX
       MOV CL,!2               GET TWO NUMBERS
       CALL GETNM
       JCC DCM15               FAILED TO GET CORRECT ANS
       POP BP                  END ADD
       POP SI                  START ADD
       SAR SI                  MAKE SI EVEN
       SHL SI                  AND LOWER
       MOV ES,S1               LOAD SEG REG
DCM05
       CALL CROUT              NEWLINE
       MOV AX,SI
       CALL PUT4H              TYPE THE ADDRESS
DCM10
       PUT " "                 TYPE SPACER
       MOV AX,(SI)[ES]         PICK UP CONTENTS
       XCHG AL,AH              MAKE BYTES APPEAR CORRECT WAY ROUND
       CALL PUT4H              TYPE THEM
       PUT " "                 TYPE SPACER
       ADD SI,!2               NEXT WORD
       CMP SI,BP               FINISHED
       JA DCM15                SO END
       TEST SI,!#FF            PAGE TYPED
       JNZ DCM12               NO
       PUT "?"                 QUERY AND CAUSES WAIT FOR CH
       CALL GETCH              HOLDS PAGE UP
       CMP AL,!CR              IF CR THEN BACK TO MON
       JE DCM15                QUIT
DCM12
       TEST SI,!#F             AT END OF LINE
       JZ DCM05                ANOTHER LINE
       JMP DCM10               ANOTHER CONTENTS
DCM15
       CALL CROUT              ENDING
       POP DS                  REPLACE SAVED SEGMENTS
       POP ES
       RET
*
*
*
*
*
*
***********************************************************************
*
* FUNCTION : GO
* DESCRIPTION : GETS SEG,INSTR POINTER AND GOES THERE
*
*
*
GCMD
       MOV   CL,!2             GET 2 NUMBERS
       CALL  GHXNM             FROM INPUT
       JCC   GCMDERR           TWAS IN ERROR
       POP   BX
       POP   AX
       MOV   CSSAV,BX[SS]     SET UP USERS BLOCK
       MOV   IPSAV,AX[SS]     FOR A RETURN
RCMD
       JMP   INTRES            AND RETURN
GCMDERR
       JMP   ERROR             AS ALWAYS
*
*
*
***********************************************************************
*
* ROUTINE : MOVE
* INPUTS NOTHING
*OUTPUTS NOTHING
* DESTROYS A,C,SI,DI,BP,FFS
* DESCRIPTION MOVES THE MEMORY POINTED TO BY S1/IST NO UPTO (INC)
*      S1/2ND NO INTO S2/3RD NO. NB S1&S2 USUALLY DEFAULTED TO
*      THE USERS DS.
*
*
*
MCMD
       MOV CL,!3               GET THREE NUMBERS
       CALL GETNM              START-UPTO-DEST
       JCC MERROR              ERROR IN READ ROUTINE
       POP DI                  DEST ADD
       POP BP                  LAST SOURCE ADD
       POP SI                  START SOURCE ADD
       PUSH ES                 USED AS SOURCE SEG
       PUSH DS                 USED AS DEST ADD
       MOV AX,!MSEG
       MOV DS,AX
       MOV ES,S1               SET UP SEGS
       MOV AX,S2
       MOV DS,AX
MCM10
       MOV AL,(SI)[ES]         GET SOURCE BYTE
       MOV (DI),AL             PUT IT AWAY
       INC SI                  NEXT LOC
       INC DI
       CMP SI,BP               ALL DONE
       JBE MCM10               NO SO AGAIN
       POP DS
       POP ES
       CALL CROUT
       RET
MERROR
       JMP ERROR
*
*
*
*
******************************************************************
*
* ROUTINE : RCMD
* DESCRIP : RETURNS TO USER PROG
*
*
*
*
*
*
*****************************************************************
*
*
*  SCMD : SETS UP TTY AT DESIRED SPEED
*
*
SCMD
       XOR BP,BP               COUNTER FOR NUMBER OF RATES TRIED
S05
       CMP BP,!NRATES          ALL DONE
       JGE SCMD                HAVEN'T FOUND SO TRY COMMAND AGAIN
       MOV SI,!RATET           POINTER TO START OF TABLE
       ADD SI,BP
       MOV BX,(SI)             GET THE RATE
       XOR DI,DI               NUMBER OF SUCCESSFUL TRIES
       ADD BP,!2               POINT TO THE NEXT RATE
       CALL TTYSP              SET UP THE CONSOLE
S10
       CALL GETCH              TRY TO READ A CH
       CALL GETCH              DO ANOTHER IN CASE THE FIRST WAS RUBBISH
       CMP AL,!#5              IS IT CONTROL E?
       JNE S05                 NO SO ONTO NEXT
       INC DI                  ANOTHER SUCCESS
       CMP DI,!4
       JL S10                  NOT SECOND SO CHECK
       MOV BP,(SI)
       MOV CONSPD,BP[SS]
       RET                     SUCCESS
*
*
*
*
       EJT
*
*
*
**********************************************************
*
*
*
*      UTILITY ROUTINES
*
**************************************************************************
*
* FUNCTION:BREAK
* INPUTS:NONE
* OUTPUTS: CARRY - 1 IF ESCAPE CHAR
*      - 0 IF ANY OTHER CHAR OR NO CHAR PENDING
* CALLS:NOTHING
* DESTROYS: AL,F/F'S
* DESCRIPTION: BREAK IS USED TO SENSE AN ESCAPE CHAR FROM
*      THE PENDING USER. IF NO CHAR IS PENDING OR IF
*      THE PENDING CHAR IS NOT ESCAPE THEN A FAILURE
*      RETURN (CARRY=0) IS TAKEN. IN THIS CASE THE
*      PENDING CHAR(IF ANY) IS LOST. IF THE PENDING CHAR
*      IS AN ESCAPE CHAR THEN BREAK TAKES A SUCSSESFUL RETURN
*      CARRY=1
*
BREAK
       IN   CONST              GET CONSOLE STATUS
       TEST AL,!RBR            SEE IF CHAR IS PENDING
       JZ   BREF               NO TAKE FAILURE RETURN
       IN   CONDR              YES PICK UP CHAR
       AND AL,!PRTY0           STRIP OFF PARITY BIT
       CMP AL,!BRCHR           IS IT ESCAPE CHAR
       JNE BREF                FAILURE RET
       SRET                    SUCCESS RET
BREF    FRET                   FAILURE RET
*
*
**************************************************************************
*
*
* FUNCTION: WRITES
* INPUTS: SI - ADRESS OF STRING (IN BCPL FORMAT) I.E LENGTH,STRING
* OUTPUTS: STRING TO CONSOLE
* DESTROYS - SI IN MACRO FORM
* DESCRIPTION : WRITE OUT A CHRACTER STRING
*
WRITES
       PUSH  AX
       PUSH  CX
       XOR   CX,CX             CLEAR CX
       MOV   CL,(SI)           MOV COUNT INTO LOWER BYTE OF CX
       INC   SI                POINT AT FIRST CHARACTER
WLOOP
       MOV   AL,(SI)           NEXT CHARACTER => AL
       CALL  CO                OUTPUT IT
       INC  SI                 BUMP CHARACTER POINTER
       LOOP  WLOOP             FOR CX CHARACTERS
       POP   CX
       POP   AX
       RET
*
*
************************************************************************
*
* FUNCTION:CI
* INPUTS : NONE
* OUTPUTS A CHAR FROM THE CONSOLE
* CALLS: NOTHING
* DESTROYS: AL, F/F'S
* DESCRIPTION:
* CI WAITS UNTIL A CHAR IS READY FROM THE CONSOLE AND RETURNS
* WITH THE CH IN AL
* THIS ROUTINE IS CALLED BY THE USER VIA A JMP TABLE IN RAM
*
CI
       IN   CONST              GET STATUS OF THE CONSOLE
       AND AL,!RBR             CHECK FOR RECEIVE BUFFER READY
       JZ   CI                 NOT YET -- WAIT
       IN   CONDR              READY SO GET CHAR
       RET                     NB HAVENT GOT RID OF PARITY BIT
*
*
************************************************************************
*
* FUNCTION: CNVBN
* INPUTS: AL --ASCII CHAR '0'-'9' OR 'A'-'F'
* OUTPUTS AL -- 0 - F HEX
* CALLS : NOTHING
*DESTROYS : AL,FFS
* DESCRIPTION: CONVERTS CHAR TO HEX DOES NOT CHECK INPUT
*
CNVBN
       SUB AL,!"0"             SUB CODE FOR ZERO
       CMP  AL,!9              TEST FOR 0-9
       JLE CNV05               OK SO RET
       SUB AL,!7               THIS IS RIGHT FOR ASCII ONLY
CNV05   RET
*
*
************************************************************************
*
* FUNCTION: CO
* INPUTS: AL -- CHAR TO OUTPUT TO CONSOLE
* OUTPUTS : AL TO CONS
* CALLS : NOTHING
* DESTROYS F/F'S
*DESCRIPTION:
* CO WAITS TILL CONSOLE IS READY THEN WRITES CHAR
*
CO
       PUSH AX
CO05    IN   CONST             GET STATUS OF CONSOLE
       TEST  AL,!TRDY          IS IT READY TO GO
       JZ   CO05               NO THEN WAIT
       POP AX                  REPLACE THE CH
       OUT  CONDR              SEND TO CONSOLE
       RET
*
************************************************************************
*
* FUNCTION : CROUT
* INPUTS : NONE
* OUTPUTS: NONE
* CALLS:ECHO
* DESTROYS :F/F'S
* DESCRIPTION:
*  CROUT SENDS A CR ( AND HENCE A LF) TO CONSOLE
*
CROUT
       PUT CR
       RET
*
************************************************************************
*
* FUNCTION : ECHO
* INPUTS: AL - CHAR TO ECHO TO TERMINAL
* OUTPUTS: NONE
* DESTROYS :F/F'S
* DESCRIPTION:
*  ECHO SENDS A SINGLE CHAR AS INPUT AND VIA THE MONTOR SENDS THAT CHAR
*  TO THE USERS TERMINAL. A CR IS ECHOED AS CR + LF AND ESCAPE AS $
*
*
ECHO
       PUSH AX                 SAVE ARG
       CMP  AL,!ESC
       JNZ  ECH05              NO BRANCH
       MOV  AL,!"$"
ECH05
       CALL CO                 DO OUTPUT THRU MONITOR
       CMP  AL,!CR
       JNE  ECH10              NO NEED FOR SPECIAL ACTION
       MOV AL,!LF              YES ECHO LF ASWELL
       CALL CO
ECH10
       POP AX                  RESTORE ARG
       RET
*
************************************************************************
*
* FUNCTION :ERROR
* INPUTS : NONE
* OUTPUTS: NONE
* CALLS: ECHO, CROUT, GETCM
* DESTROYS: F/F'S
* DESCRIPTION:
*  ERROR PRINTS THE ERROR CHAR (CURRENTLY AN ASTERISK)
*  FOLLOWED BY CR + LF
*  AND THE RETURNS CONTROL TO THE COMMAND REGOGNISER
*
ERROR
       PUT "*"                 SEND * TO CONSOLE
       CALL CROUT              NEWLINE
       JMP  GETCM              TRY FOR ANOTHER COMMAND
*
************************************************************************
*
* FUNCTION : GETCH
* INPUTS: NONE
* OUTPUTS: AL -- CHAR FROM INPUT STREAM
* CALLS : CI
*
* DESTROYS AL,F/F
* DESCRIPTION:
*  GETCH GETS NEXT CHAR FROM THE INPUT
*
GETCH
       CALL CI                 GET CHAR
       AND  AL,!PRTY0          TURN OFF PARITY BIT
       RET
*
*
*
************************************************************************
*
* FUNCTION GETHX
* INPUTS: NONE
* OUTPUTS : BP -- 16 BIT INTEGER
*      AL - CHAR TERMINATING THE INTEGER
*      AH - FF IF FIRST CH DELIMETER
*      CARRY - 1 IF SUCCESS
*      0 IF FAILURE
* CALLS: ECHO,GETCH,VALDL,VALDG,CNVBN,ERROR
* DESTROYS: AX,BP,F/F'S
* DESCRIPTION:
*  GETHX ACCEPTS A STREAM OF HEX DIGITS AS A 16 BIT INTEGER.IF MORE THAN
* 4 HEX DIGITS ARE ENTERED ONLY THE LAST 4 ARE USED. THE NUMBER ENDS
*  WHEN A VALID DELEIMETER IS FOUND.THE DELIMETER IS ALSO RETURNED AS AN
*  OUTPUT OF THE FUNCTION. ILLEGAL CHARS ( NOT HEX OR DELIMETERS) CAUSE
*  AN FLAG. IF THE FIRST VALID CHAR IN INPUT IS NOT DELIMETER
* AH SET TO 0
*
GETHX
       PUSH CX                 SAVE CX
       MOV CL,!#FF             FLAG FOR FIRST DIGIT
       XOR BP,BP               INIT ANS TO 0
GHX05
       CALL GETCH              GET A CHAR
GHX06
       CALL ECHO               ECHO IT
       CALL VALDL              SEE IF DELIMETER
       JCS GHX15               YES SO END
       CALL VALDG              IF NOT DELIM WAS IT A DIGIT
       JCC GHX20               NO SO INVALID DIGIT
       CALL CNVBN              CONVERT TO BINARY
       MOV CX,!4               ROTATE ANS BY 1 DIGIT
GHX10
       SHL BP,CX
       MOV AH,!0               ADD IN THIS DIGIT
       ADD BP,AX
       B GHX05
GHX15
       MOV AH,CL               SET UP FIRST DIGIT FLAG
       STC                     FLAG TO SAY NO ERROR
GHX20
       POP CX                  RESTORE
       RET
*
*
*
************************************************************************
*
* FUNCTION: GETNM
* INPUTS: CL- COUNT OF NUMBER TO BE FOUND IN INPUT STREAM
* OUTPUTS: TOP OF STACK: NUMBERS TO BE FOUND IN REVERSE ORDER
* CALLS: GETHX,HILO,ERROR
* DESTROYS : AX,BP,SI,DI,CX,FFS
* DESCRIPTION:
*  GETNM FINDS A CNT OF NUMBERS BETWEEN 1 AND 3 INCLUSIVE IN THE
*  INPUT STREAM AND RETURNS THEIR VALUES ON THE STACK
*  IF 2 OR MORE ARE REQUIRED THEN THE FIRST MUST BE LESS THAN OR EQUAL
*  TO 2ND OR 1ST IS SET EQ TO 2ND. THE LAST NUMBER MUST BE TERMINATED
* BY CR OR AN ERROR IS GIVEN-C IS SET
* REGS ARE STACKED IN REVERSE ORDER TO THAT READ IN
*
GETNM
       MOV SI,SP               SAVE CORRECT SP IF ROUTINE FAILS
       AND  CL,!3              FORCE TO MAX OF 3
       JZ GNM30                IF 0 DONT BOTHER
       MOV CH,CL               SAVE NUMBER OF NUMBERS
GNM05
       CALL GETHX              GET A NUMBER FROM THE INPUT STREAM
       JCC GNM30               ERROR IF NOT THERE TOO FEW NUMBERS
       PUSH BP                 ELSE SAVE NUMBER ON STACK
       DEC  CL                 DECR ARG CNT
       JZ   GNM10              NO MORE NUMBERS WANTED
       CMP  AL,!CR             WAS IT CR
       JZ   GNM30              ERROR IF SO TOO FEW
       JMP  GNM05              ELSE PROCESS NEXT NUMBER
GNM10
       CMP AL,!CR              WHEN CNT 0 CHECK LAST TERM
       JNE  GNM30              ERROR IF NOT CR
       MOV BP,!#FFFF           BP GETS LARGEST NUMBER
       MOV AL,!3               MAKE SURE HAVE STACKED THREE NUMBERS
       SUB AL,CH
GNM15
       JZ   GNM20              IF YES 3 NUMBERS WERE INPUT
       PUSH BP                 IF NOT FILL OUT REST WITH FFFF
       DEC  AL
       B  GNM15                LOOP TILL DONE
GNM20
       POP SI
       POP  BP                 GET THE 3 ARGS OUT
       POP  AX
       CMP AX,BP               SEE IF 1ST >= 2ND
       JBE GNM25               NO -- BRANCH JMP IF OK
       MOV AX,BP               FORCE THEM =
GNM25
       POP DI                  REMOVE RETURN ADDRESS
       PUSH AX
       PUSH BP
       PUSH SI                 3RD
       PUSH DI                 PUT RET ADDRESS ON STACK
       NEG CH
       ADD CH,!3               FIND NO OF EXTRA REGS STACKED
GNM26
       JZ GNM28                WHEN 0 FINISH
       POP DI
       POP BP                  TAKE EXTRA FROM UNDER RET ADD
       PUSH DI
       DEC CH
       B GNM26                 LOOP
GNM28
       SRET                    SUCCESS
GNM30
       MOV SP,SI               REPLACE CORRECT SP
       FRET                    FAILURE RET
*
*
*
******************************************************************
*
* GHXNM SAME AS GETNM BUT NO SWAPPING OF NUMBERS
*
*
*
GHXNM
       MOV SI,SP               SAVE CORRECT SP IF ROUTINE FAILS
       AND  CL,!3              FORCE TO MAX OF 3
       JZ GXM30                IF 0 DONT BOTHER
       MOV CH,CL               SAVE NUMBER OF NUMBERS
GXM05
       CALL GETHX              GET A NUMBER FROM THE INPUT STREAM
       JCC GXM30               ERROR IF NOT THERE TOO FEW NUMBERS
       PUSH BP                 ELSE SAVE NUMBER ON STACK
       DEC  CL                 DECR ARG CNT
       JZ   GXM10              NO MORE NUMBERS WANTED
       CMP  AL,!CR             WAS IT CR
       JZ   GXM30              ERROR IF SO TOO FEW
       JMP  GXM05              ELSE PROCESS NEXT NUMBER
GXM10
       CMP AL,!CR              WHEN CNT 0 CHECK LAST TERM
       JNE  GXM30              ERROR IF NOT CR
       MOV BP,!#FFFF           BP GETS LARGEST NUMBER
       MOV AL,!3               MAKE SURE HAVE STACKED THREE NUMBERS
       SUB AL,CH
GXM15
       JZ   GXM20              IF YES 3 NUMBERS WERE INPUT
       PUSH BP                 IF NOT FILL OUT REST WITH FFFF
       DEC  AL
       B  GXM15                LOOP TILL DONE
GXM20
       POP SI
       POP  BP                 GET THE 3 ARGS OUT
       POP  AX
GXM25
       POP DI                  REMOVE RETURN ADDRESS
       PUSH AX
       PUSH BP
       PUSH SI                 3RD
       PUSH DI                 PUT RET ADDRESS ON STACK
       NEG CH
       ADD CH,!3               FIND NO OF EXTRA REGS STACKED
GXM26
       JZ GXM28                WHEN 0 FINISH
       POP DI
       POP BP                  TAKE EXTRA FROM UNDER RET ADD
       PUSH DI
       DEC CH
       B GXM26                 LOOP
GXM28
       SRET                    SUCCESS
GXM30
       MOV SP,SI               REPLACE CORRECT SP
       FRET                    FAILURE RET
*
*
*
*
************************************************************************
*
* FUNCTION NMOUT
* INPUTS: AL - 8 BIT INTEGER
* OUTPUTS: NONE
* CALLS : ECHO,PRVAL
* DESTROYS: F/F'S
* DESCRIPTION:
*  NMOUT CONVERTS THE 8 BIT INTEGER INTO 2 ASCII CHARS AND PRINTS THEM
*
NMOUT
       PUSH AX                 SAVE AX DESTROYED HERE
       SHR AL
       SHR AL
       SHR AL
       SHR AL
       CALL PRVAL              CONVERT TO ASCII
       CALL ECHO               TYPE
       POP  AX                 RESTORE
       PUSH AX                 AND SAVE IT AGAIN
       AND AL,!#F              BOTTOM 4 BITS ONLY
       CALL PRVAL
       CALL ECHO
       POP  AX                 RESTORE AX
       RET
*
***********************************************************************
*
* FUNCTION : PRVAL
* INPUTS : AL - INTEGER 0-F
*
* OUTPUTS: AL -ASCII CHAR
* CALLS: NOTHING
*DESCRIPTION:
*  CONVERTS TO ASCII WITHOUT CHECK ON VALUE
*
PRVAL
       ADD AL,!"0"             CONVERT TO ASCII
       CMP AL,!"9"
       JLE PRV05               IF <10 OK
       ADD AL,!7               WORKS ONLY FOR ASCII
PRV05   RET
*
************************************************************************
*
* FUNCTION: PUT4H
* INPUT : AX 16 BIT INTEGER
* OUTPUT : TYPES 4 HEX DIGITS
* DESTROYS : NOTHING ?
* DESCRIPTION : TYPES 4 HEX DIGITS
*
*
PUT4H
       PUSH AX                 SAVE THE ARG
       XCHG AL,AH              TYPE TOP BITS FIRST
       CALL NMOUT
       POP AX
       PUSH AX                 MAKE SURE ITS UNCHANGED
       CALL NMOUT              TYPE BOTTTOM BITS
       POP AX
       RET
****************************************************************
*
*
* FUNCTION : TTYON
* DESCRIP : SETS TTY SPEED TO BX
*
*
*
TTYSP
       IN CONST
       TEST AX,!1              OK TO PROCEED
       JZ TTYSP
       PUSH BX
       MOV BX,!1
       CALL DELAY
       POP BX
       MOV AL,!#40             SET CMD WORD BACK TO INSTRUCTION MODE
       OUT CNCTL
TTYON
       MOV AL,!CLKCTL
       OUT TIMCTL
      PUSH AX
      POP AX
       MOV AX,BX               PUT IN SPEED READY FOR OUT
       OUT TIM2
       MOV AL,AH
       OUT TIM2
       MOV AL,!MODE
       OUT CNCTL
       PUSH AX
       POP AX                  WASTE TIME FOR USART TO SET UP
       MOV AL,!CMD
       OUT CNCTL               START IT OFF
       PUSH AX
       POP AX
       RET
*
*
*
*****************************************************************
*
*
* FUNCTION : VALDG
* INPUTS: AL-- ASCII CHAR
* OUTPUTS: CARRY = 1   IF REPRESENTS A HEX DIGIT
*      = 0   IF NOT
*
*CALLS : NOTHING
* DESTROYS: F/FS
* DESCRIPTION :
*  CHECK FOR A VALID HEX DIGIT '0'-'9' AND 'A' TO 'F'
*
VALDG
       CMP AL,!"0"             AGAINST "0"
       JB   VDGF               IF LOWER CANT BE VALID
       CMP AL,!"9"             WAS IT 0-9
       JBE   VDGS              BETWEEN 0 AND 9
       CMP AL,!"A"             WAS IT A TO F
       JB   VDGF               NO
       CMP AL,!"F"
       JA   VDGF               NO
VDGS    SRET                   WAS A TO F INCLUSIVE
VDGF    FRET                   FAILURE RET
*
************************************************************************
*
* FUNCTION : VALDL
* INPUTS : AL-- CHARACTER
* OUTPUTS:   CARRY = 1 VALID DELIMETER
*      =0  INVALID DELIMETER
* CALLS :NOTHING
* DESTROYS F/FS
* DESCRIPTION:
*  VALID IF ( SPACE ,COMMA,CR) FAILURE IF NOT
*
VALDL
       CMP AL,!","             COMMA
       JZ   VDLS               SUCCESS
       CMP   AL,!"."           ALSO PERIOD
       JZ   VDLS
       CMP AL,!"/"             ALSO A STOKE
       JZ  VDLS                IS GOOD
       CMP  AL,!CR             CARRIAGE RETURN
       JZ   VDLS               SUCCESS
       CMP AL,!" "             SPACE
       JZ   VDLS
       FRET                    ALL ELSE INVALID
VDLS    SRET                   SUCCESS RET
*
************************************************************************
*
*
* FUNCTION: CCMD
* INPUTS:  NONE
* OUTPUTS: NONE
* DESTROYS: PROBABLY EVERYTHING
* DESCRIPTION: ALOWWS THE USER TO LOOK AND MODIFY MEMORY
*
CCMD
       CALL   GETHX            WHAT IS THE LOCATION
       JCC    CERR
       MOV    SI,BP            FOR THE BYTE POINTER
       CMP    AL,!"/"          WAS DELIMETER SLASH
       JNE    CC1              IF SO WE OVERRIDE SEGMENT
       CALL   GETHX            WITH A VALUE AFTER THE SLASH
       JCC    CERR             THIS REPLACES S1
       MOV    S1,BP[SS]        CHANGE
CC1     MOV    ES,S1[SS]       ES IS USED TO ACCES MEMORY
*
CC0     CALL   CROUT           FRESH LINE
       MOV    AX,SI            NOW OUTPUT THE LOCATION
       CALL   PUT4H
       PUT    "-"              SEPERATE
       PUT    " "
       MOV    AL,(SI)[ES]     THIS IS
       CALL   NMOUT            THE BYTE
       PUT    " "
       PUT    "-"              DO WE WANT TO CHANGE
       CALL   GETHX            IF SO
       JCC    CC2              MUST BE SUCCESS
       CMP    AH,!#FF          AND 1ST CHAR NOT DELIMETER
       JE    CC2               BEFORE WE DO
       MOV    BX,BP
       MOV    (SI),BL[ES]     CHANGE IT
CC2
       CMP    AL,!CR           IF RETURN
       JNE    CC3              TIME TO GO HOME
       RET
CC3
       CMP    AL,!"↑"          IF "↑" THEN
       JNE    CC4              MOVE BACK
       DEC    SI
       JMP    CC0
CC4
       CMP    AL,!"."          IF "." THEN STAY
       JNE    CC5              AS YOU WERE
       JMP    CC0
CC5
       INC    SI               IN ALL OTHER CASES
       JMP    CC0              GO TO NEXT
*
CERR
       JMP    ERROR
*
******************************************************
*
*
* FUNCTION : XCMD
* INPUT & OUTPUT : NONE
* DESTROYS : ALL
* DESCRIPTION: DISPLAYS USERS REGISTERS AND ALLOWS YOU TO CHANGE
*
XCMD
       PUT   "-"               THIS ALLOWS
       PUT   " "               THE USER
       CALL   GETCH            TO SET
       CALL  ECHO              EVERYTHING IN THE USER BLOCK
       XCHG  AH,AL
       CALL   GETCH
       CALL   ECHO             GET 2 CHAR IDENTIFIER
       XCHG  AH,AL
*
       MOV   CX,!LTAB/2        NOW SCAN THE TABLE
       MOV   DI,!RTAB          FOR A MATCH
       CLD                     RIGHT DIRECTION
       REP
       SCAW
       JNZ   XERR              DID NOT FIND MATCH
       MOV   SI,!LTAB/2        BYTE ADDRESSING
       SUB   SI,CX
       DEC    SI
       ADD   SI,SI             COMPLICATED
       PUT  " "
       MOV   AX,SPSAV(SI)[SS]   THIS SHOULD GET IT
       CALL  PUT4H             DISPLAY IT
       PUT   " "
       PUT   "-"
       CALL  GETHX             DO WE NEED A CHANGE
       JCC   XC1
       CMP   AH,!#FF
       JE   XC1
       MOV   SPSAV(SI),BP[SS]  CHANGE IT
XC1
       CMP   AL,!CR            IF DELIMETER RETURN
       JNE   XC2               WE HAVE FINISHED
       RET
XC2
       CALL  CROUT             NEWLINE
       PUT   " "               NEW LOOK
       PUT   " "
       JMP   XCMD
*
XERR    JMP   ERROR
*
*
*********************************************************************
*
*
* FUNCTION: RVIEW
* INPUT & OUTPUT :NONE
* DESTROYS : ALL
* DESCRIPTION : DISPLAYS IP/CX,AX,SP,BP,SI,FLAGS
*
RVIEW
       CALL  CROUT             FRESH LINE
       WRITE IPMES
       MOV   AX,IPSAV[SS]      NOTE THAT
       CALL  PUT4H             AS USUAL WE USE
       PUT   "/"               WE USE MONITOR
       MOV   AX,CSSAV[SS]      TO ACCESS THE
       CALL  PUT4H             USERS
       WRITE SPMES             REGISTER BLOCK
       MOV   AX,SPSAV[SS]      VIA STACK SEGMENT
       CALL  PUT4H
       WRITE AXMES
       MOV   AX,AXSAV[SS]
       CALL  PUT4H
       WRITE BXMES
       MOV AX,BXSAV[SS]
       CALL PUT4H
       WRITE BPMES
       MOV   AX,BPSAV[SS]
       CALL  PUT4H
       WRITE SIMES
       MOV   AX,SISAV[SS]
       CALL  PUT4H
       WRITE DIMES
       MOV AX,DISAV[SS]
       CALL PUT4H
       WRITE FSMES
       MOV   AX,FSSAV[SS]
       CALL  PUT4H
       CALL  CROUT
       RET
*
*
*
*************************************************************************
*
*
*
*  INTENT :::: FOR ALL UNDEFINED  AND INTERRUPT 3
*  IF SSTEP IS SET THEN IT WILL CALL RVIEW EVERY SSCNTR TIMES
*  SSCNTR-1 IN FACT
*  IT COMPLETELY SAVES THE USERS ENVIROMENT INCLUDE HIS CORRECT STACK
*  POSITION
*  IT IS A LITTLE TRICKY AS IT MUST USE THE USERS STACK INITIALLY
*  IT THEN COMPLETELY SWAPS TO THE MONITORS ENVIRONMENT
*
*
INTENT
       PUSH  DS                WE MUST USE
       PUSH  AX                THE USERS STACK INITIALLY
       MOV   AX,!MSEG          NOW THE MONITORS
       MOV   DS,AX             DATA SEGMENT
       CMP   SSTEP,!1          IF THE SINGLE STEP
       JNE   INT2              FLAG IS UNSET OR COUNTER IS 0
       CMP   STEPCNT,!0        THEN WE DIPLAY AND GO
       JE   INT2               THIS IS OK
       DEC   STEPCNT           MAYBE OK NEXT TIME
       JMP   INTEXIT           BUT OFF FOR NOW
INT2
       MOV   AX,SSCNTR         NOW  RELOAD COUNT
       MOV   STEPCNT,AX        IT MAY WELL BE ZERO
*
       POP   AX                AX RESTORED
       MOV   AXSAV,AX          NOW WE CAN
       MOV   BXSAV,BX          SAVE ALL THE
       MOV   CXSAV,CX          THE USERS
       MOV   DXSAV,DX          REGISTERS
       MOV   BPSAV,BP          THAT ARE  STRAIGHT
       MOV   SISAV,SI          FORWARD
       MOV   DISAV,DI
       MOV   ESSAV,ES
       MOV   SSSAV,SS
*
       POP   AX                THIS WAS THE USERS
       MOV   DSSAV,AX          DATA SEGMENT
       POP   AX                IP  USER
       POP   BX                CS -- USER
       POP   CX                FLAGS -- USER
       MOV   IPSAV,AX
       MOV   CSSAV,BX
       MOV   FSSAV,CX
       MOV   SPSAV,SP          AFTER ALL THIS SP IS CORRECT
       MOV   AX,DSSAV          SET DEFAULT SEGMENT
       MOV   S1,AX             POINTER 1 & 2
       MOV   S2,AX
       MOV   INTPRES,!1        INDICATE WE HAVE AN INTERRUPT
*
*
************************************************************
*
*
*  NOW WE HAVE  SAVED THE USERS ENVIRONMENT ENTIRELY
*  WE CAN SET UP THE MONITOR ENVIRONMENT
*  WITH NO FEARS FOR A SCREW UP
*
*
       MOV   AX,!MSEG          NOTE THAT WE CAN USE
       MOV   SS,AX             THE MONITOR STACK SEGMENT
       MOV   AX,!MCSEG         FOR ACCESSING USER DATA BLOCK
       MOV   DS,AX
       MOV   ES,AX
       MOV   SP,!MSTAK         RESET THE STACK
*
       CALL  RVIEW             FOR A QUICK LOOK
       JMP   GETCM             FOR FURTHER WORK
*
*
*************************************************************
*
*
INTEXIT
       POP   AX                NOWT TO DO
       POP   DS                THIS TIME
       IRET
*
*
*******************************************************************
*
*
*
* INTRES:
* THIS RESETS THE USER ENVIRONMENT
* INCLUDES SETTING OR RESETTING THE SINGLE STEP COUNTER
*
INTRES
       MOV   AX,!MSEG          SET UP DATA SEGMENT
       MOV   DS,AX             FOR EASY ACCESS
       CMP   INTDIS,!1         SHOULD WE TURN OFF INTERRUPTS
       JNE   IR5               NOT IF RESET
       AND   FSSAV,!#FDFF      OFF IT GOES
IR5
       AND   FSSAV,!#FEFF      CLEAR SINGLE STEP BIT
       CMP   SSTEP,!1          IF WE WISH TO
       JNE   IR3               HAVE SINGLE STEP
       OR    FSSAV,!#0100      SET BIT ON
       MOV   SI,IPSAV          THIS COMPLICATED BIT
       MOV   AX,CSSAV          SEES IF THE NEXT INSTRUCTION IS
       MOV   ES,AX             IS AN INT3 IF SO
IR4     MOV   AL,(SI)[ES]      IF SO AND IN SINGLE STEP
       CMP   AL,!INT3          WE IGNORE
       JNE   IR2               UNTIL NOT THIS INTRUCTION
       INC   SI
       JMP   IR4
IR2
       MOV   IPSAV,SI          CLEVER STUFF HEY
IR3
       MOV   SP,SPSAV          FIRST USERS STACK
       MOV   SS,SSSAV          SET UP
       PUSH  FSSAV             NOW RETURN
       PUSH  CSSAV
       PUSH  IPSAV
       MOV   ES,ESSAV
       MOV   DI,DISAV
       MOV   SI,SISAV
       MOV   BP,BPSAV
       MOV   DX,DXSAV
       MOV    CX,CXSAV
       MOV   BX,BXSAV
       MOV   AX,AXSAV
       MOV   INTPRES,!0        WE HAVE FINISHED
       MOV   DS,DSSAV          AFTER THIS IT IS USER DATA SEGMENT
       IRET
*
*
***********************************************************************
*
*
*
* USE THE 9.6 KB MAST LINK
*
*  SELECT 'CONTROL BLOCK'
VCMD    OUT #BC
*  INITIALIZE PIT (TIMER)
*    PIT 1, TIMER 3 ( SO IT USES BDG3 )
*
* SC1,SC0 = 0,0    COUNTER 3
* RL1,RL0 = 1,1    LOAD L.S. BYTE THEN M.S.
* M2,M1,M0 = 0,1,1 MODE 3 FOR B.R.G.
* BCD = 0         BINARY
*  SO,
        MOV AL,!#T00110110
*  WRITE TO CONTROL (7)
        OUT #B7
* FOR B.R. OF 9600 AND DIV. BY 1 CLOCK LOAD COUNTER WITH 128
       MOV AX,CONSPD[SS]
       MOV CL,!4
       SHL AX,CL             BECAUSE DIVIDE BY 1, NOT 16
        OUT #B4
        MOV AL,AH
        MOV AL,AH               WASTE TIME
        OUT #B4
* B.R.G. IS NOW GOING
* SELECT 'DATA BLOCK'
        OUT #BD
* INITIALIZE UART
        MOV AL,!#40
        OUT #B7           INTERNAL RESET
       MOV BX,!2
       CALL DELAY
*  FIRST SEND MODE INSTRUCTION (7)
*
* S2,S1 = 0,1       1 STOP BIT
* EP = 1            EVEN PARITY
* PEN = 1           ENABLE PARITY
* L2,L1 = 1,0       7 BITS OF DATA
* B2,B1 = 0,1       BAUD RATE FACTOR = 1
*  SO,
        MOV AL,!#T01111001
        OUT #B7
        PUSH AX
        POP AX
* SEND COMMAND INSTRUCTION (7)
*
* EH = 0            NOT HUNT MODE
* IR = 0            NOT INTERNAL RESET
* RTS = 1           RTS TRUE
* ER = 1            CLEAR ERROR FLAGS
* SBRK = 0          NOT BREAK
* RXE = 1           RECEIVE ENABLE
* DTR = 1           DTR ON TO START WITH
* TXEN = 1          TRANSMIT ENABLE
*  SO,
        MOV AL,!#T00110111
        OUT #B7
        PUSH AX
        POP AX
*
FCMD   MOV DX,!UST3
       B DLL                  USE THE LINK
*
*
SETUP   CLI                    ;DISABLE INTS
       OUT     COMMBASE+#0C    SELECT CONTROL WORD
       MOV     AL,!#36         HOW TO READ
       OUT     COMMBASE+#03      FOR USART0
       MOV     AL,!#40         BR=1200 LSB
       OUT     COMMBASE+#00
       MOV     AL,!0           MSB
       OUT     COMMBASE+#00
       OUT     COMMBASE+#0D    SELECT DATA WORD
       MOV AL,!#40
       OUT UST0                 INTERNAL RESET
       PUSH AX
       POP AX
       MOV     AL,!#7A         SET UP USART AS COMPUTER
       OUT     UST0
       PUSH AX
       POP AX
       MOV     AL,!#27         START IT OFF
       OUT     UST0
       PUSH AX
       POP AX
       RET
*
*
*
*
LOAD    CALL    SETUP          START UP COMMS
        MOV DX,!UST0
DLL     MOV     AL,!#37        CLEAR TTY ERROR FLAGS
       OUT     CNCTL
DLL1    IN      CONST          CH FROM CONSOLE
       TEST  AL,!#20
       JZ      DLL2            NO SO IT IS CH
 TEST AL,!#10                  IF PARITY ERROR THEN IGNORE THE CH
 JNE DLLA
       MOV     AL,!#2F         SEND BREAK ON THE LINE
       OUT
       MOV     BX,!DELAYTIME     LOAD DELAY >300MS FOR GANDALF
       CALL    DELAY
DLLA
       MOV     AL,!#37         RESET FLAGS
       OUT
       CALL   DELAY            LET THINGS SETTLE
       JMP     DLL             RESET TTY
DLL2
       TEST  AL,!RBR
       JZ      DLL10           NO SO CHECK LINK
       IN      CONIN           GET IT
       AND  AL,!PRTY0          PARITY OFF
       MOV     BX,AX
       CMP  AL,!#01            IS IT CONT  A
       JZ      FILL            GET THE PROGRAM FROM LINK
       CMP  AL,!#02            IS IT CONT B
       JZ      GO              YES BACK TO MONITOR
DLL5    IN                     SEND IT TO LINK
       TEST  AL,!1             IS IT READY
       JZ      DLL5            LOOP TILL IS
       MOV     AX,BX
       DEC DX
       OUT                 SEND TO LINK
       INC DX
       CMP DX,!UST3        IF 1270 CONN. THEN ECHO TO CONSOLE
       JE DLL11
DLL10   IN                 ANYTHING FROM THE LINE
       TEST   AL,!2
       JZ      DLL1            NO SO CHECK CONSOLE
       DEC DX
       IN                  GET CH FROM LINK
       INC DX
DLL11  AND  AL,!PRTY0
       CALL    CO
       JMP     DLL1            GO AND LOOK AT CONSOLE
GO      JMP     GETCM          START AGAIN
FILL
FILL1   CALL    GETLIN         GET CH FROM LINE
       CMP  AL,!"O"            IS IT AN O
       JNZ     FILL1           LOOP UNTIL IT IS
FILL5   CALL    GETLIN         GET THE NEXT
       CMP  AL,!"R"            IS IT THE R FROM "STORE"
       JZ      DLL1            IF SO BACK TO TRANSPARENT MODE
       CMP  AL,!"G"            IS IT THE G FROM "PROG"
       JZ      FILL8           START OF PROGRAM
       CMP  AL,!"C"            C INTROS OFFSET
       JNZ     FILL5           NOT TRUE CH SO BACK FOR ANOTHER
       CALL    RADD            GET OFFSET
       MOV     CX,!4
       SHR     AX,CX           FOR SEGMENT ACCESS
       MOV     ES,AX           FROM EXTRA SEGEMNT
       JMP     FILL1           GET NEXT LINE
FILL8   CALL    RADD           GET TRUE ADD
       MOV  SI,AX              POINTER FOR ACCESS VIA SEGMENT
FILL10  CALL    RDATA          GET THE CONTENTS
       JCC     FILL1           CARRY DENOTES CR
       MOV   (SI),AL[ES]
       INC   SI
       JMP     FILL10          GET NEXT CONTENTS
GETLIN  IN                 CH IN LINE
       TEST   AL,!2
       JZ     GETLIN           NO SO LOOP
       DEC DX
       IN
       INC DX
       AND  AL,!PRTY0          STRIP OF PARITY
       CALL   CO
       RET                     RETURN WITH CH IN C AND A
*RNO READS A VALID HEX DIGIT OR SETS CARRY IF CR
RNO     CALL    GETLIN         GET A CH
       CALL     VALDG          IS IT VALID HEX
       JCC   RNO1
       RET
RNO1    CMP   AL,!CR
       JNZ   RNO
       CLC
       RET
*RDATA GETS 2 HEX DIGITS INTO A
RDATA
       PUSH CX
       CALL  RNO
       JCC  RDATA1
       CALL  CNVBN
       SHL   AX
       SHL   AX
       SHL   AX
       SHL   AX
       MOV   CX,AX
       CALL  RNO
       JCC    GO
       CALL  CNVBN
       ADD   AX,CX
       STC
RDATA1 POP   CX
       RET
* RADD LOAD AN ADDRESS INTO AX
RADD
       PUSH CX
       CALL RDATA
       MOV  CH,AL
       CALL RDATA
       MOV  AH,CH
       POP   CX
       RET
*DELAY  THE VALUE IN BX TIME 40 MSEC
DELAY PUSH BX
       PUSH CX
DEL1  MOV  CX,!0
       LOOP $
       DEC  BX
       JNZ  DEL1
       POP  CX
       POP  BX
       RET
*
*
*
*
**********************************************************************
*
*
* JUMP FROM POWER UP TO MONITOR
*
*
       ORG #7F0                POWER UP START
       JMPS START-BEGIN,MCSEG  TO START OF MONITOR
*
*
*
       END