; Disassembly of the file "C:\lab\if1-2.rom"
;
; CPU Type: Z80
;
; Created with dZ80 1.50
;
; on Sunday, 28 of April 2002 at 12:35 PM
;

; ------------------------
; last updated 14-JAN-2004
; ------------------------

#define DEFB .BYTE
#define DEFW .WORD
#define DEFM .TEXT
#define EQU  .EQU
#define ORG  .ORG

        ORG     $0000

; ---------------------------------------
; FLAGS3 System Variable - IY+$7C ($5CB6)
; ---------------------------------------
; Bit 0 - set when executing an extended command.
; Bit 1 - set during CRT-VARS and CLEAR #, CLOSE etc.
; Bit 2 - settable by User to force the ERR_SP routine to handle errors.
; Bit 3 - set when networking.
; Bit 4 - set during LOAD and MOVE
; Bit 5 - set during SAVE
; Bit 6 - set during MERGE
; Bit 7 - set during VERIFY
;
; Note. before initialization of FLAGS_3, this is considered to be the first
; byte of channels and so PEEK 23734 gives 244 decimal (%11110100) the high
; order byte of the Main ROM address PRINT-OUT - $09F4.
;
; -------------------------------------------

; --------------------------------
; THE 'RETURN TO MAIN ROM' ROUTINE
; --------------------------------
;   The system is initialized by the Main ROM so this address is accessed 
;   solely by a RST 00H instruction.  It is used from five locations to return 
;   to the Main ROM.

;; MAIN-ROM
L0000:  POP     HL              ; discard the return address in this ROM.
        LD      (IY+$7C),$00    ; reset all the bits of FLAGS_3.
        JP      L0700           ; jump forward to UNPAGE address.

; -------------------
; THE 'START' ROUTINE
; -------------------
;   An instruction fetch on address $0008 pages in this ROM.
;   The three-byte instruction at this location must exist on both sides of
;   the looking-glass.  The value fetched is immediately discarded.
;   It follows that this restart should never be invoked from this ROM.

;; ST-SHADOW
L0008:  LD      HL,($5C5D)      ; fetch character address from CH_ADD.
        POP     HL              ; pop return address to HL register.
        PUSH    HL              ; and save again on machine stack.

        JP      L009A           ; jump forward to continue at START-2.

; -----------------------------
; THE 'CALL A MAIN ROM' ROUTINE
; -----------------------------
;   Call an address in the main ROM. The address follows the restart so this
;   is as convenient and as brief as a CALL instruction.
;   The SBRT routine within the system variables area reads
;
;   L5CB9         LD      HL,value
;   L5C5C         CALL    addr
;   L5C5F         LD      (L5CB9+1),HL
;   L5CC2         RET
;
;   By immediately placing the current value of HL in the subroutine, then
;   all registers before the call are as they were before the RST
;   instruction.  The value of HL after the call is stored immediately in
;   this now redundant location so that, after this ROM is paged back in,
;   the registers, after the RST instruction has executed, are as they were
;   immediately after the CALL.
;   see START-2.

;; CALBAS
L0010:  LD      ($5CBA),HL      ; insert the current value of HL in the
                                ; Z80 code to be picked up later.

        POP     HL              ; drop the return address - the location
                                ; of address to be called.
        PUSH    DE              ; preserve the DE register contents.

        JR      L0081           ; forward to continue at CALBAS-2.

        DEFB    $FF             ; unused.

; ---------------------------------------------
; THE 'TEST IF SYNTAX IS BEING CHECKED' ROUTINE
; ---------------------------------------------
;   On the ZX80, testing the syntax flag was done with the 4-byte
;   instruction that tests the System Variable FLAGS.  On the ZX81 and
;   ZX Spectrum, a call to SYNTAX-Z reduced the invocation to a three-byte
;   CALL.   Here it is reduced to a one-byte restart.

;; CHKSYNTAX
L0018:  BIT     7,(IY+$01)      ; test most significant bit of FLAGS
        RET                     ; return the result.
                                ; (Z = Syntax, NZ = Run-time)

        DEFB    $FF             ; unused.
        DEFB    $FF             ; unused.
        DEFB    $FF             ; unused.

; --------------------------
; THE 'SHADOW-ERROR' ROUTINE
; --------------------------
;   This is similar to the Main ROM error handler and the following byte 
;   indicates the type of error and in runtime the message that should be
;   printed.  If checking syntax then the error pointer is set before a
;   return is made to the Main ROM.

;; SH-ERR
L0020:  RST     18H             ; checking syntax ?
        JR      Z,L0068         ; forward, if so, to ST-ERROR

        JR      L003A           ; forward, in run-time, to TEST-SP,
                                ; and then REP-MSG

        DEFB    $FF             ; unused.
        DEFB    $FF             ; unused.
        DEFB    $FF             ; unused.

; ------------------------------------
; THE 'MAIN ROM ERROR RESTART' ROUTINE
; ------------------------------------
;   This restart invokes the error handler of the Main 16K ROM.  The required 
;   error number is usually first placed in the System Variable ERR_NR.  In 
;   some cases the error code is already present and this restart is used when 
;   the error situations handled by this ROM have been eliminated.
;   Since the exit from this point is by manipulating the stack, the return 
;   address is of no importance as that route is never taken.  There are also
;   three conditional jumps back to this point.

;; ROMERR
L0028:  RES     3,(IY+$02)      ; update TV_FLAG - signal no change in mode.
        JR      L0040           ; forward to RMERR-2.

        DEFB    $FF             ; unused.
        DEFB    $FF             ; unused.

; -------------------------------------------------
; THE 'CREATE NEW SYSTEM VARIABLES RESTART' ROUTINE
; -------------------------------------------------
;    This restart is used the first time that that the ROM is paged in to
;    create the System Variables.  This will be either by an instruction
;    fetch on $0008 or $1708.

;; NEWVARS
L0030:  JP      L01F7           ; jump to CRT-VARS

        DEFB    $FF             ; unused.
        DEFB    $FF             ; unused.
        DEFB    $FF             ; unused.
        DEFB    $FF             ; unused.
        DEFB    $FF             ; unused.

; --------------------------------
; THE 'MASKABLE INTERRUPT' ROUTINE
; --------------------------------
;   There is no service routine but should the routine be called either
;   directly or by straying into a RST $38 instruction, then interrupts are
;   enabled.

;; INT-SERV
L0038:  EI                      ; Enable Interrupts
        RET                     ; return.


; ------------------------
; THE 'TEST SYSTEM' BRANCH
; ------------------------
;   This branch allows the user to trap errors before this ROM is used to print
;   the error report. 

;; TEST-SP
L003A:  CALL    L0077           ; routine CHECK-SP
                                ; usually returns.
        JP      L0260           ; jump to REP-MSG

; ----------------------------
; THE 'MAIN ROM ERROR' ROUTINE
; ----------------------------
;   a continuation of RST 28H.
;   This ROM has inserted a Main ROM error code into ERR_NR and the routine in 
;   the Main ROM is now invoked.
;   First a check is made to see if the user wishes to trap errors using a 
;   custom routine in ERR_SP.  This will be used in the syntax path anyway.
; 

;; RMERR-2
L0040:  RST     18H             ; checking syntax ?
        JR      Z,L0068         ; forward, if so, to ST-ERROR.

        CALL    L0077           ; routine CHECK-SP allows the user to trap 
                                ; run-time errors at this point but normally 
                                ; returns here.

        CALL    L17B7           ; routine RCL-T-CH reclaims any temporary
                                ; channels and stops all microdrive motors.

        BIT     1,(IY+$7C)      ; test FLAGS_3.
        JR      Z,L0068         ; forward, if executing CLOSE, to ST-ERROR.

        BIT     4,(IY+$7C)      ; test FLAGS_3 - loading filename 'run' ?
        JR      Z,L0068         ; forward, if not, to ST-ERROR.

;   As a security measure, the file 'run' can not be hacked.

        LD      A,(IY+$00)      ; fetch error number from the System Variable
                                ; ERR_NR.
        CP      $14             ; is it "CODE error" ?
        JR      NZ,L0068        ; forward, if not, to ST-ERROR.

;   The user has pressed BREAK while trying to load the program 'run'.

        LD      HL,$0000        ; cause a system reset.
        PUSH    HL              ; place address zero on machine stack.
        RST     00H             ; switch to MAIN-ROM.

;

        DEFB    $FF             ; unused
        DEFB    $FF             ; unused
        DEFB    $FF             ; unused
        DEFB    $FF             ; unused
        DEFB    $FF             ; unused

; ------------------------------------
; THE 'NON-MASKABLE INTERRUPT' ROUTINE
; ------------------------------------
;   There is no NMI functionality.

;; NMINT-SRV
L0066:  RETN                    ; return to previous interrupt state.


; --------------------------
; THE 'SYNTAX ERROR' ROUTINE
; --------------------------
;   An error has occurred during syntax checking so the position must be 
;   highlighted when a return is made to the Editor in the Main ROM.

;; ST-ERROR
L0068:  LD      HL,($5C5D)      ; fetch character address from CH_ADD.
        LD      ($5C5F),HL      ; set X_PTR to same to position error cursor.

        LD      SP,($5C3D)      ; set the Stack Pointer from ERR_SP.

        LD      HL,$16C5        ; prepare address of main SET-STK.
        PUSH    HL              ; push on the machine stack.

        RST     00H             ; switch to MAIN-ROM where SET-STK will clean up 
                                ; the work areas before returning to the Error 
                                ; Routine obtained from ERR_SP.

; ---------------------------------------
; THE 'CHECK ERROR STACK POINTER' ROUTINE
; ---------------------------------------
;   This allows the user's software to trap any errors at this point by setting 
;   the otherwise unused bit 2 of FLAGS_3 after inserting a custom error 
;   handler in the System Variable ERR_SP.
;   Both Shadow ROM situations and Main ROM situations can be trapped and the 
;   routine is called from BOTH RST 20H and RST 28H.

;; CHECK-SP
L0077:  BIT     2,(IY+$7C)      ; test FLAGS_3 has the user set up a custom
                                ; error handler in Main RAM ?
        RET     Z               ; return if not.

;   Otherwise the user, or the third party software, has set up a custom routine
;   in the system variable ERR_SP and set bit 2 of FLAGS_3 so that it is invoked
;   at this point.

        LD      SP,($5C3D)      ; set stack pointer from ERR_SP.
        RST     00H             ; switch to MAIN-ROM.

; ----------------------
; THE 'CALBAS-2' ROUTINE
; ----------------------
;   A continuation of the code at $0010.
;   Continue by picking up the address to be called, located after the RST
;   instruction and placing after the CALL instruction in the SBRT sequence.

;; CALBAS-2
L0081:  LD      E,(HL)          ; fetch low byte of called address
        INC     HL              ; advance pointer.
        LD      D,(HL)          ; fetch high byte.

        LD      ($5CBD),DE      ; place in the Z80 code SBRT
        INC     HL              ; increment pointer.

        EX      (SP),HL         ; transfer continuation address to machine
                                ; stack - and the stack value (was DE) to HL.

        EX      DE,HL           ; original DE value now restored.

        LD      HL,$0000        ; signal CALBAS routine in use.
        PUSH    HL              ; place on stack.

        LD      HL,$0008        ; address of main ERROR restart
        PUSH    HL              ; place on stack

        LD      HL,$5CB9        ; address of calling SBRT subroutine.
        PUSH    HL              ; place on stack.

        JP      L0700           ; jump to UNPAGE

; ---------------------
; THE 'CONTROL' ROUTINE
; ---------------------
;   A continuation of code at L0008. The return address has been dropped off
;   the machine stack into HL.
;
;   First see if this ROM was paged in as a result of the $0008 address
;   stacked during the CALBAS routine. (see above)

;; START-2
L009A:  PUSH    AF              ; preserve accumulator and status flags.

        LD      A,H             ; test HL for zero - the CALBAS
        OR      L               ; indicator value.
        JR      NZ,L00A5        ; forward, if not, to START-3.

        POP     AF              ; restore accumulator and flags.

        POP     HL              ; discard address stacked by RST 08.
        LD      HL,($5CBA)      ; pick up post-CALL HL value from SBRT.
        RET                     ; return.

;------------------------------------------------------------------------------
;   Now consider that the address $0008 may have been an input or output
;   routine that precedes the letter of one of the new channels.  These
;   paging addresses ensure that this ROM is paged in so that the real
;   input/output addresses can be read from the locations after the
;   channel's letter. In this case, the return address is towards the end
;   of the CALL-SUB routine in the Main ROM, i.e.
;   L15FB         CALL    $162C   ; routine CALL-JUMP (a JP (HL) instr.)
;   L15FE         POP     HL      ; return address
;------------------------------------------------------------------------------

;; START-3
L00A5:  PUSH    DE              ; preserve DE.
        LD      DE,$15FE        ; test against possible return address 0x15FE
        SBC     HL,DE           ; subtract (carry is clear)
        POP     DE              ; restore DE.
        JR      NZ,L00BC        ; forward with no match to START-4.

;   This ROM has been paged by an attempt to use a stream.

        POP     AF              ; restore accumulator.

        LD      HL,L0700        ; stack the address UNPAGE to switch to 
        PUSH    HL              ; the Main ROM afterwards.

        LD      HL,$0004        ; the shadow routine is 4 bytes forward
        ADD     HL,DE           ; adjust input/output address pointer.
        LD      E,(HL)          ; pick up low-order byte of I/O routine.
        INC     HL              ; bump pointer.
        LD      D,(HL)          ; pick up high-order byte of routine.
        EX      DE,HL           ; transfer I/O address to HL.

        JP      (HL)            ; jump to routine and then to UNPAGE

; ---

;   By elimination, the address $0008 has been reached as a result of a
;   RST 08 instruction in the Main ROM.  This may be the very first time
;   that this ROM has been paged in after startup or NEW.

;; START-4
L00BC:  RST     30H             ; create new system variables if first time.

        LD      A,$01           ; %00000001
        OUT     ($F7),A         ;

        LD      A,$EE           ; %11101110
        OUT     ($EF),A         ;

        POP     AF              ; temporarily drop the accumulator.
        POP     HL              ; fetch address of error code/hook code to HL.
        PUSH    AF              ; save accumulator again.

;   Note. the address of the code could be anywhere in the 64K address space
;   but it is not in this ROM.  Luckily in the Main ROM at $007B is the
;   sequence ld a,(hl) ; ret which will fetch the unknown error code from
;   the known address.

        RST     10H             ; CALBAS
        DEFW    $007B           ; main TEMP-PTR3

        LD      ($5C3A),A       ; place the error code in sysvar ERR_NR

;   The error code at this stage is one less than actual code.

        CP      $FF             ; is it 'OK'
        JR      NZ,L00E9        ; forward, if not, to TEST-CODE

        BIT     1,(IY+$7C)      ; test FLAGS_3  - first time ?
        JR      Z,L00E7         ; forward, if not, to NREPORT-2
                                ; 'Program finished'

        BIT     7,(IY+$0C)      ; test PPC_hi - a direct command ?
        JR      Z,L00E7         ; forward, if not, to NREPORT-2

        LD      HL,($5C59)      ; use E_LINE to address the first character of 
                                ; the edit buffer.
        LD      A,(HL)          ; searching for RUN without whitespace.

        CP      $F7             ; is character the token 'RUN' ?
        JP      Z,L0A99         ; jump forward, if so, to LOAD-RUN

;; NREPORT-2
L00E7:  RST     20H             ; Shadow Error Restart
        DEFB    $FF             ; 'Program finished'

; ---

;   Continue to consider the error code.  This may have occurred after the
;   Error RESTART in the Main ROM - range $00 (NEXT without FOR) to
;   $1A (Tape Loading Error) or a RESTART in RAM which could also include
;   the Hook Codes.

;; TEST-CODE
L00E9:  SUB     $1B             ; subtract lowest Hook Code (PAUSE)
        JP      NC,L1E71        ; jump, if same or higher, to HOOK-CODE

        CP      $F0             ; was it $0B 'Nonsense in basic'
        JR      Z,L00FB         ; forward to COPYCHADD

        CP      $F3             ; was it $0D 'Invalid file name'
        JR      Z,L00FB         ; forward to COPYCHADD

        CP      $FC             ; was it $17 'Invalid stream'
        JP      NZ,L0028        ; jump, if not, to ROMERR

;   If one of the above three reports, then this is possibly an extended
;   command and further investigation is required. A number of situations
;   may apply. The error could have occurred -
;
;   1) In INPUT - just pass control back to Main ROM. This is just a normal
;      Nonsense in BASIC and will not be due to anything new.
;   2) While already investigating an error. Too much - just use Main ROM.
;   3) While entering a new or modified line and syntax failed.
;   4) While running the program and an error was encountered.
;
;   The character address CH_ADD is not much use as that is the place
;   after the command where the standard ROM encountered an error.
;   It will be required by the Main ROM if control is passed back so, in
;   order that the Main ROM parsing routines can be used, make a copy of the
;   error character position. We will have to work forward from the
;   beginning of the line if checking syntax or from the start of the
;   program in run-time so that the errant command can be found. It may also
;   be necessary to remove hidden characters from the BASIC line.

;; COPYCHADD
L00FB:  LD      HL,($5C5D)      ; fetch character address from CH_ADD and
        LD      ($5CCB),HL      ; store in shadow system variable CHADD_

        POP     AF              ; restore accumulator.

        BIT     5,(IY+$37)      ; test FLAGX - in INPUT mode ?

        JP      NZ,L0028        ; jump back, if so, to ROMERR

;   Continue if in Editing or Run-time Mode.

        BIT     0,(IY+$7C)      ; test FLAGS_3 - already extended command ?
        JP      NZ,L0028        ; jump, if so, to ROMERR

;   else signal - handling an extended command - so that such a double error
;   can be trapped.

        SET     0,(IY+$7C)      ; update FLAGS_3 - signal executing an
                                ; extended command.

        RST     18H             ; checking syntax ?

        JR      NZ,L011B        ; skip forward, if not, to RUNTIME

        LD      (IY+$0C),$FF    ; set bit 7 of PPC_hi to indicate a line
                                ; entry situation.

;    In both cases, load B with the statement number where the error was
;    encountered.  Previous validated statements are not to be disturbed.

;; RUNTIME
L011B:  LD      B,(IY+$0D)      ; load B with statement number from SUBPPC
        LD      C,$00           ; and set C to zero for a quotes flag.

        BIT     7,(IY+$0C)      ; test PPC_hi - line entry ?
        JR      Z,L0130         ; forward, if not, to PROG-LINE

;   An edit line may have a line number at start and whitespace. We need to
;   set CH_ADD at the first command.

        PUSH    BC              ; save BC

        RST     10H             ; CALBAS
        DEFW    $19FB           ; main E-LINE-NO fetches any line number to
                                ; BC, setting CH_ADD at the command token.

        POP     BC              ; restore BC - discarding line number.

        RST     10H             ; CALBAS
        DEFW    $0018           ; main GET-CHAR gets first command of the
                                ; first statement of the errant line.

        JR      L016F           ; forward to statement loop - S-STAT to find
                                ; the errant statement.

; ---

;; PROG-LINE
L0130:  LD      HL,($5C53)      ; set pointer to start of program from PROG.

;; SC-L-LOOP
L0133:  LD      A,($5C46)       ; fetch high byte of errant line from PPC_hi
        CP      (HL)            ; compare with tested high byte.
        JR      NC,L013B        ; forward, if errant line higher or same,
                                ; to TEST-LOW

; else, unusually, the current line is not there so let Main ROM handle.

;; NREPORT-1
L0139:  RST     20H             ; Shadow Error Restart
        DEFB    $00             ; Nonsense in BASIC

; ---

;; TEST-LOW
L013B:  INC     HL              ; increment program pointer to address low byte.
        JR      NZ,L0144        ; forward, if high bytes not same, to LINE-LEN

        LD      A,($5C45)       ; fetch low byte of current line from PPC_lo
        CP      (HL)            ; compare to addressed byte.
        JR      C,L0139         ; back, if not in program area, to NREPORT-1


;; LINE-LEN
L0144:  INC     HL              ; increment program
        LD      E,(HL)          ; pointer and
        INC     HL              ; pick up the
        LD      D,(HL)          ; length of the BASIC line
        INC     HL              ; resting at the first character.

        JR      Z,L016F         ; forward, if line numbers matched, to S-STAT
                                ; the mid-entry point of the statement loop.

        ADD     HL,DE           ; else add length to current address.
        JR      L0133           ; loop back to SC-L-LOOP

; --------------------
; THE 'STATEMENT LOOP'
; --------------------
;    Entered at mid-point S-STAT with statement counter in B and a quotes
;    counter, C, set at an even zero.

;; SKIP-NUM
L014E:  LD      DE,$0006        ; a hidden floating point number has six bytes.
        ADD     HL,DE           ; add to skip to next character.

; -> The Looping Point.

;; EACH-ST
L0152:  LD      A,(HL)          ; fetch addressed BASIC character.
        CP      $0E             ; is it the hidden number indicator ?
        JR      Z,L014E         ; back to SKIP-NUM to ignore.

        INC     HL              ; else increase pointer.

        CP      $22             ; is it quotes character '"' ?
        JR      NZ,L015D        ; skip forward, if not, to CHKEND

        DEC     C               ; decrement quotes counter.

;; CHKEND
L015D:  CP      $3A             ; is character ':' ?
        JR      Z,L0165         ; skip forward to CHKEVEN

        CP      $CB             ; is character 'THEN' ?
        JR      NZ,L0169        ; skip forward to CHKEND-L


;; CHKEVEN
L0165:  BIT     0,C             ; are quotes balanced ?
        JR      Z,L016F         ; forward, if so, to S-STAT
                                ; for next statement.

;   A carriage return must not appear within quotes.

;; CHKEND-L
L0169:  CP      $0D             ; carriage return ?
        JR      NZ,L0152        ; back, if not, to EACH-ST

        JR      L0139           ; back to NREPORT-1
                                ; 'Nonsense in BASIC'


;    The Statement Loop Entry Point -->

;; S-STAT
L016F:  DJNZ    L0152           ; decrement statement counter and loop back
                                ; to EACH-ST.

;    The errant statement has been located and CH_ADD is set to start.

        DEC     HL              ; point to start or ':'

        LD      ($5C5D),HL      ; set the Main ROM system variable CH_ADD

        RST     18H             ; checking syntax ?

        JR      NZ,L01AA        ; forward, if not, to CL-WORK

        BIT     7,(IY+$0C)      ; test PPC_hi - is it an Edit Line ?
        JP      Z,L01F0         ; jump forward, if not, to ERR-6.

        DEC     HL              ; prepare to enter loop below.

        LD      C,$00           ; ??

;   It is well to reflect on what has been achieved up to this point.  At
;   each statement, the first attempt at validation is made by the Main ROM.
;   Then if that should encounter something not to its liking, this ROM has
;   a bash.  There could be ten or more statements before this one and each
;   will have been validated by the Main ROM or by this routine.  As part of
;   that validation process, when a number is parsed, then the integer or
;   floating point form of the number is inserted after the digits, rendered
;   invisible by a CHR$(14).
;
;   Once a statement has passed validation by either ROM, then it is not
;   undone.  If, say, the Main ROM has failed on the third statement of
;
;   10 PRINT "Hi :" : LET vat = 15 : OPEN# 7, "T" : LET tax = cost * (vat/100)
;
;   then it will have already inserted six bytes after the '7' before raising
;   the error 'Invalid stream'.  This ROM has located the separator before
;   the command but needs to remove the hidden numbers before parsing the
;   statement as the latter process will put them back in and we can't
;   double up.  The easiest way to do this is to search for hidden numbers
;   right to the end of the line.  There won't be any after this statement
;   but stopping at a CHR$(13) is easier than considering end of statement
;   markers in quotes.  It seems that this neat solution was not arrived at
;   immediately and the instruction, above, sets C to the quotes flag again
;   and it is needlessly preserved on the stack.
;
;   The end-user is oblivious to this elegant toing and froing between ROMS
;   and the unseen error code generation and cancellation. All that is
;   apparent is that when the RETURN key is pressed, the line simply enters
;   the program.

;; RCLM-NUM
L0182:  INC     HL              ; increment character pointer
        LD      A,(HL)          ; fetch the character.

        CP      $0E             ; is it the number marker ?
        JR      NZ,L01A5        ; forward, if not, to NEXTNUM

        PUSH    BC              ; preserve BC (zero)

        LD      BC,$0006        ; six bytes to reclaim.

        RST     10H             ; CALBAS
        DEFW    $19E8           ; main RECLAIM-2

        PUSH    HL              ; preserve character pointer.

        LD      DE,($5CCB)      ; fetch error pointer from CHADD_
        AND     A               ; prepare for true subtraction.
        SBC     HL,DE           ; test if character position less than error.
        JR      NC,L01A3        ; forward, if not, to NXT-1

        EX      DE,HL           ; transfer CHADD_ value to HL.
        LD      BC,$0006        ; 
        AND     A               ;
        SBC     HL,BC           ; reduce by six.
        LD      ($5CCB),HL      ; store back in system variable CHADD_

;; NXT-1
L01A3:  POP     HL              ; restore character pointer.
        POP     BC              ; and restore BC (zero)

;; NEXTNUM
L01A5:  LD      A,(HL)          ; fetch character.
        CP      $0D             ; carriage return ?
        JR      NZ,L0182        ; loop back, if not, to RCLM-NUM

;  The run-time path rejoins here

;; CL-WORK
L01AA:  RST     10H             ; CALBAS
        DEFW    $16BF           ; main SET-WORK

        CALL    L0255           ; routine RES-VARS sets new system variables
                                ; from that following CHADD_ to that preceding
                                ; COPIES to the value $FF.

        RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR advances CH_ADD and fetches
                                ; the command character.

        SUB     $CE             ; reduce tokens - why?

        CP      $01             ; 'CAT' ?
        JP      Z,L0486         ; jump to CAT-SYN

        CP      $02             ; 'FORMAT' ?
        JP      Z,L04B4         ; jump to FRMT-SYN

        CP      $03             ; 'MOVE' ?
        JP      Z,L053D         ; jump to MOVE-SYN

        CP      $04             ; 'ERASE' ?
        JP      Z,L0531         ; jump to ERASE-SYN

        CP      $05             ; 'OPEN #' ?
        JP      Z,L04ED         ; jump to OPEN-SYN

        CP      $2A             ; 'SAVE' ?
        JP      Z,L082F         ; jump to SAVE-SYN

        CP      $21             ; 'LOAD' ?
        JP      Z,L0898         ; jump to LOAD-SYN

        CP      $08             ; 'VERIFY' ?
        JP      Z,L08A2         ; jump to VERIF-SYN

        CP      $07             ; 'MERGE' ?
        JP      Z,L08AC         ; jump to MRG-SYN

        CP      $2D             ; 'CLS' ?
        JP      Z,L0559         ; jump to CLS#-SYN

        CP      $2F             ; 'CLEAR' ?
        JP      Z,L057F         ; jump to CLR#-SYN

;   If none of the new extended commands then load HL from the VECTOR
;   system variable which normally points to the error routine below.
;   However the user, or a third party software publisher, may have
;   altered the vector to point to their own extended BASIC routines.

;; ERR-V
L01EC:  LD      HL,($5CB7)      ; fetch address from system variable VECTOR
        JP      (HL)            ; jump to address.

; ---

;; ERR-6
L01F0:  LD      HL,($5CCB)      ; fetch original character address from
                                ; CHADD_
        LD      ($5C5D),HL      ; and place in standard CH_ADD
        RST     28H             ; Error Main ROM.

; -----------------------------------------
; THE 'CREATE NEW SYSTEM VARIABLES' ROUTINE
; -----------------------------------------
;   A continuation of the restart code at $0030. A check is made to see if
;   the 58 variables already exist and the stack is set up to create the
;   room using the main ROM routine. If there isn't 58 free bytes available
;   then an 'Out of memory' report is generated by the Main ROM.

;; CRT-VARS
L01F7:  LD      HL,($5C4F)      ; system variable CHANS normally   $5CB6.
        LD      DE,$A349        ; add test value                   $A349.
                                ;                                   ----
        ADD     HL,DE           ; add - if uninitialized will give $FFFF.
        JR      C,L023D         ; forward, if higher, to VAR-EXIST

        LD      HL,L0224        ; prepare address of DEFAULT routine
        PUSH    HL              ; push on machine stack

        LD      HL,($5C63)      ; use system variable STKBOT
        LD      ($5C65),HL      ; to set system variable STKEND

        LD      HL,$5C92        ; use system variable MEMBOT
        LD      ($5C68),HL      ; to set system variable MEM

        LD      HL,$5CB5        ; the last standard system variable.
                                ; P-RAMT_hi - the location before new area.
        LD      BC,L003A        ; 58 bytes to allocate.

;   Now call MAKE-ROOM in the Main ROM by placing a sequence of addresses
;   on the machine stack as it is not possible to use the CALBAS routine yet.

        LD      DE,$0000        ; indicator - signals Main ROM has been used.
        PUSH    DE              ; stack word.

        LD      E,$08           ; form address $0008 in Main ROM.
        PUSH    DE              ; stack word.

        LD      DE,$1655        ; the Main ROM address MAKE-ROOM.
        PUSH    DE              ; stack word.

;   The machine stack now has the hierarchy DEFAULT; $0000; ERROR-1;
;   MAKE-ROOM which will be handled in reverse order.

        JP      L0700           ; jump to UNPAGE.

;   After creating room and paging this ROM back in, 'return' to the next
;   address which was the first in the sequence pushed on machine stack
;   earlier.

;; DEFAULT
L0224:  LD      HL,L0242        ; default system variable values.
        LD      BC,$0013        ; nineteen bytes to move.
        LD      DE,$5CB6        ; old CHANS area, new sysvar FLAGS_3.
        LDIR                    ; copy the bytes.

;   Note. So far the value in the accumulator, which may be the number of a
;   stream to close, has not been altered.  This next instruction is worded 
;   wrongly and 
;
;   OPEN #7,"s" : CLOSE #7 
;
;   may not work.
;   The fix would be to use 'ld hl $5cef ; ld (hl), $01' (5 bytes)
;   or even 'dec h ; ld ($5cee),hl' (4 bytes)
;   The next pair of instructions would have been better if executed using
;   the HL register pair also.

        LD      A,$01           ; set accumulator to 1.
        LD      ($5CEF),A       ; set system variable COPIES.

        LD      (IY+$77),$50    ; set NMI_ADD_hi to eighty.
        LD      (IY+$76),$00    ; set NMI_ADD_lo to zero.

        RET                     ; return.

; ---

;   The extended System Variables already exist.

;; VAR-EXIST
L023D:  RES     1,(IY+$7C)      ; reset indicator in FLAGS_3.
        RET                     ; return.


; -------------------------------------------
; THE 'SYSTEM VARIABLES DEFAULT VALUES' TABLE
; -------------------------------------------
;   These are the initial values of the first section of the extended System
;   Variables that are copied, once only, to a newly opened area following
;   the standard 48K Spectrum System Variables.  The memory area that was at
;   this location (CHANS) is moved upwards to make room.
;   The first new location (which was the first byte of CHANS) is now
;   FLAGS_3, accessible by the IY register, and normally zero when the Main
;   ROM becomes active again.  Bit 1 is set when a CLEAR# is active and also
;   by the copy itself.

;; SV-DEFS
L0242:  DEFB    $02             ; FLAGS3 (with bit 1 already set).
        DEFW    $01F0           ; VECTOR

        LD      HL,$0000        ; SBRT located at $5CB9
        CALL    $0000           ;
        LD      ($5CBA),HL      ;
        RET                     ;

        DEFW    $000C           ; BAUD
        DEFB    $01             ; NTSTAT
        DEFB    $00             ; IOBORD - black.
        DEFW    $0000           ; SER_FL


; ----------------------------------------
; THE 'RESET NEW SYSTEM VARIABLES' ROUTINE
; ----------------------------------------
;   The central area is filled with $FF bytes.
;   This occurs whenever a new extended command is invoked.

;; RES-VARS
L0255:  LD      HL,$5CCD        ; set pointer to NTRESP - start of area.
        LD      B,$22           ; thirty four bytes to fill.

;; EACH-VAR
L025A:  LD      (HL),$FF        ; insert a default $FF value.
        INC     HL              ; bump the pointer.
        DJNZ    L025A           ; loop back to EACH-VAR.

        RET                     ; return.

; ------------------------------------
; THE 'SHADOW REPORT PRINTING' ROUTINE
; ------------------------------------
;   This routine prints the error reports of the Shadow ROM.
;   These relate to the code that follows a RST 20H restart.  The error code
;   is not printed as it would conflict with Main ROM reports.  The text of
;   the message is printed and then the Main ROM routine is used to print a
;   comma and then the line number and statement.  For example,
;   Program finished, 0:1
;   The code is similar to that at MAIN-4 in the Main ROM.  Some improvements
;   have been made but at least one slight error has been replicated.

;; REP-MSG
L0260:  LD      (IY+$7C),$00    ; clear FLAGS_3 in preparation for leaving 
                                ; this ROM.

        EI                      ; Enable Interrupts.

        HALT                    ; wait for the first interrupt.

        CALL    L17B7           ; routine RCL-T-CH reclaims any temporary
                                ; channels and stops any running drive motor.

        RES     5,(IY+$01)      ; update FLAGS - 'Ready for new key'.
        BIT     1,(IY+$30)      ; test FLAGS2 - is printer buffer empty ?
        JR      Z,L0276         ; forward, if so, to FETCH-ERR

        RST     10H             ; CALBAS - call a Base ROM routine.
        DEFW    $0ECD           ; main routine - COPY-BUFF
                                ; Note. the programmer has neglected to
                                ; set bit 1 of FLAGS first.

;; FETCH-ERR
L0276:  POP     HL              ; drop the return address - after RST.
        LD      A,(HL)          ; fetch the error code.
        LD      (IY+$00),A      ; place in system variable ERR_NR.
        INC     A               ; increment setting zero if was $FF.
        PUSH    AF              ; save actual code and status flags.

        LD      HL,$0000        ; prepare to blank some system variables.
        LD      (IY+$37),H      ; clear all the bits of FLAGX.
        LD      (IY+$26),H      ; blank X_PTR_hi to suppress error marker.
        LD      ($5C0B),HL      ; blank DEFADD to signal that no defined
                                ; function is being evaluated.

        INC     L               ; select offset of 1 (explicit in main ROM ).
        LD      ($5C16),HL      ; update STRMS_00 - inputs from keyboard.

        RST     10H             ; CALBAS
        DEFW    $16B0           ; main SET-MIN clears workspace etc.

        RES     5,(IY+$37)      ; update FLAGX - signal in EDIT mode
                                ; not INPUT mode.
                                ; Note. all the bits were reset earlier.

        RST     10H             ; CALBAS
        DEFW    $0D6E           ; main CLS-LOWER

        SET     5,(IY+$02)      ; update TV_FLAG - signal lower screen
                                ; requires clearing.
        RES     3,(IY+$02)      ; update TV_FLAG - no change in mode.

        POP     AF              ; restore the incremented error code.
        LD      HL,L02BF        ; start search at REP-MSGS table below.
        LD      B,$04           ; roughly ensure that BC does not limit
                                ; search area as code must be found.
        CPIR                    ; search for code $00 - $17 skipping
                                ; all ASCII text.

;   At this point HL addresses first character of message.

;; PR-REP-LP
L02A7:  LD      A,(HL)          ; fetch each character in turn.
        CP      $20             ; compare to space.
        JR      C,L02B4         ; forward if less to END-PR-MS

        PUSH    HL              ; save the character pointer
        RST     10H             ; CALBAS
        DEFW    $0010           ; main PRINT-A

        POP     HL              ; restore pointer
        INC     HL              ; and increment.
        JR      L02A7           ; loop back to PR-REP-LP

; ---

;; END-PR-MS
L02B4:  LD      SP,($5C3D)      ; set machine stack pointer from ERR_SP
        INC     SP              ; prepare to overwrite the MAIN-4
        INC     SP              ; address $1303.
        LD      HL,$1349        ; substitute with the part that prints
                                ; the comma and line statement.
        PUSH    HL              ; push address to base of stack.
        RST     00H             ; return to MAIN-ROM.

;   Note. at this stage we have, say, "Program finished" on the screen and
;   the Main ROM routine at $1349 will complete the ", 0:1" part looping
;   back to MAIN-2 to put $1303 on the stack again.

; ------------------------------------
; THE 'SHADOW REPORT MESSAGES' ROUTINE
; ------------------------------------
;   These are the Shadow Error Reports.  Note. that the never used
;   "Header mismatch error" has been largely reclaimed.  Each error code,
;   which must be less than a space, serves to delimit the preceding text.
;   The final delimiter might just as well be $18.

;; REP-MSGS
L02BF   DEFB    $00
        DEFM    "Program finished"
        DEFB    $01
        DEFM    "Nonsense in BASIC"     ; Duplicate of a Main ROM error
        DEFB    $02
        DEFM    "Invalid stream number"
        DEFB    $03
        DEFM    "Invalid device expression"
        DEFB    $04
        DEFM    "Invalid name"
        DEFB    $05
        DEFM    "Invalid drive number"
        DEFB    $06
        DEFM    "Invalid station number"
        DEFB    $07
        DEFM    "Missing name"
        DEFB    $08
        DEFM    "Missing station number"
        DEFB    $09
        DEFM    "Missing drive number"
        DEFB    $0A
        DEFM    "Missing baud rate"
        DEFB    $0B
        DEFM    "er mismatch e"         ; Note. remnants of unused text.
        DEFB    $0C
        DEFM    "Stream already open"
        DEFB    $0D
        DEFM    "Writing to a 'read' file"
        DEFB    $0E
        DEFM    "Reading a 'write' file"
        DEFB    $0F
        DEFM    "Drive 'write' protected"
        DEFB    $10
        DEFM    "Microdrive full"
        DEFB    $11
        DEFM    "Microdrive not present"
        DEFB    $12
        DEFM    "File not found"
        DEFB    $13
        DEFM    "Hook code error"       ; not listed in manual.
        DEFB    $14
        DEFM    "CODE error"
        DEFB    $15
        DEFM    "MERGE error"
        DEFB    $16
        DEFM    "Verification has failed"
        DEFB    $17
        DEFM    "Wrong file type"
        DEFB    $18                     ; end-marker

; *********************************************
; **  T H E   S Y N T A X   R O U T I N E S  **
; *********************************************

; --------------------------------
; THE 'CAT COMMAND SYNTAX' ROUTINE
; --------------------------------
;   e.g. CAT 3
;   Without the syntax tables of the Main ROM, checking syntax is quite
;   laborious.  Although the Main ROM allowed CAT without a parameter, a
;   single expression in the range 1 - 8 is now required.  By default, CAT
;   outputs to the upper screen but output may be directed to any stream in
;   the range 0 to 15 decimal.  The subroutines used to evaluate the numeric
;   expressions use the SCANNING routine, in Main ROM, which inserts the
;   hidden five-byte numbers after any numeric arguments.

;; CAT-SYN
L0486:  LD      HL,$5CD8        ; address system variable S_STR1.
        LD      (HL),$02        ; default to stream 2 the screen.

        RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR

        CP      $0D             ; carriage return ?
        JR      Z,L0494         ; forward, if so, to MISSING-D

        CP      $3A             ; is character ':' ?

;; MISSING-D
L0494:  JP      Z,L0683         ; jump if no parameter to NREPORT-9

        CP      $23             ; is character '#' ?
        JR      NZ,L04A6        ; forward to CAT-SCRN

;   Output is directed at a specific stream.

        CALL    L064E           ; routine EXPT-STRM checks for number in range.
        CALL    L05B1           ; routine SEPARATOR checks for ',' or ';'.
        JR      NZ,L04B2        ; forward, if not present, to OREPORT-1
                                ; 'Nonsense in BASIC'

        RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR

;; CAT-SCRN
L04A6:  CALL    L061E           ; routine EXPT-NUM
        CALL    L05B7           ; routine ST-END
        CALL    L066D           ; routine CHECK-M-2 checks that drive is in 
                                ; range 1 - 8.

        JP      L1AB5           ; jump forward to CAT-RUN

; ---

;; OREPORT-1
L04B2:  RST     20H             ; Shadow Error Restart
        DEFB    $00             ; Nonsense in BASIC

; -----------------------------------
; THE 'FORMAT COMMAND SYNTAX' ROUTINE
; -----------------------------------
;   e.g.

;; FRMT-SYN
L04B4:  CALL    L05F2           ; routine EXPT-SPEC
        CALL    L05B1           ; routine SEPARATOR
        JR      NZ,L04BF        ; forward to NO-FOR-M

        CALL    L062F           ; routine EXPT-NAME

;; NO-FOR-M
L04BF:  CALL    L05B7           ; routine ST-END
        LD      A,($5CD9)       ; sv L_STR1 device letter.
        CP      $54             ; is character  "T" ?
        JR      Z,L04CD         ; forward to FOR-B-T

        CP      $42             ; is character  "B" ?
        JR      NZ,L04D3        ; forward to NOT-FOR-B


;; FOR-B-T
L04CD:  CALL    L06B0           ; routine TEST-BAUD
        JP      L0ACD           ; jump to SET-BAUD

;; NOT-FOR-B
L04D3:  CP      $4E             ; is character "N" ?
        JR      NZ,L04E7        ; forward to FOR-M

        CALL    L068F           ; routine TEST-STAT
        LD      A,($5CD6)       ; sv D_STR1 drive number
        AND     A
        JP      Z,L069F         ; jump to NREPORT-6
        LD      ($5CC5),A       ; sv NTSTAT
        JP      L05C1           ; jump to END1

;; FOR-M
L04E7:  CALL    L0685           ; routine TEST-MNAM
        JP      L1ABA           ; jump to FOR-RUN

; ---------------------------------
; THE 'OPEN COMMAND SYNTAX' ROUTINE
; ---------------------------------
;

;; OPEN-SYN
L04ED:  CALL    L064E           ; routine EXPT-STRM
        CALL    L05B1           ; routine SEPARATOR
        JR      NZ,L04B2        ; back to OREPORT-1
                                ; 'Nonsense in BASIC'

        CALL    L05F2           ; routine EXPT-SPEC
        CALL    L05B1           ; routine SEPARATOR
        JR      NZ,L0500        ; forward to NOT-OP-M

        CALL    L062F           ; routine EXPT-NAME

;; NOT-OP-M
L0500:  CALL    L05B7           ; routine ST-END
        LD      A,($5CD8)       ; sv D_STR1

        RST     10H             ; CALBAS
        DEFW    $1727           ; main STR-DATA1

        LD      HL,$0011        ;
        AND     A               ;
        SBC     HL,BC           ;
        JR      C,L052F         ; forward to NREPORT-C

        LD      A,($5CD9)       ; sv L_STR1 device letter.
        CP      $54             ; "T" ?
        JR      Z,L051C         ; forward to OPEN-RS

        CP      $42             ; "B" ?
        JR      NZ,L051F        ; forward to NOT-OP-B


;; OPEN-RS
L051C:  JP      L0B4E           ; jump to OP-RSCHAN

; ---

;; NOT-OP-B
L051F:  CP      $4E             ; is character "N" ?
        JR      NZ,L0529        ; forward to OP-M-C

        CALL    L068F           ; routine TEST-STAT
        JP      L0F40           ; jump to OPEN-N-ST

; ---

;; OP-M-C
L0529:  CALL    L0685           ; routine TEST-MNAM
        JP      L1ABF           ; jump to OP-RUN

; ---

;; NREPORT-C
L052F:  RST     20H             ; Shadow Error Restart
        DEFB    $0B             ; Stream already open

; ----------------------------------
; THE 'ERASE COMMAND SYNTAX' ROUTINE
; ----------------------------------
;

;; ERASE-SYN
L0531:  CALL    L06A3           ; routine EXPT-EXPR
        CALL    L05B7           ; routine ST-END
        CALL    L0685           ; routine TEST-MNAM
        JP      L1AAB           ; jump to ERASE-RUN

; ---------------------------------
; THE 'MOVE COMMAND SYNTAX' ROUTINE
; ---------------------------------
;

;; MOVE-SYN
L053D:  CALL    L06B9           ; routine EXPT-EXP1
        CALL    L059F           ; routine EX-D-STR
        RST     10H             ; CALBAS
        DEFW    $0018           ; main GET-CHAR

        CP      $CC             ; 'TO' ?
        JR      NZ,L0584        ; forward to NONSENSE

        CALL    L06B9           ; routine EXPT-EXP1
        CALL    L059F           ; routine EX-D-STR
        RST     10H             ; CALBAS
        DEFW    $0018           ; main GET-CHAR

        CALL    L05B7           ; routine ST-END
        JP      L1AB0           ; jump to MOVE-RUN

; --------------------------
; THE 'CLS# COMMAND' ROUTINE
; --------------------------
;

;; CLS#-SYN
L0559:  RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR

        CP      $23             ; is the character '#' ?
        JR      NZ,L0584        ; forward, if not, to NONSENSE

        RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR

        CALL    L05B7           ; routine ST-END

        LD      HL,L0038        ; prepare a zero and black ink on white paper.
        LD      ($5C8D),HL      ; set system variables ATTR_P and MASK_P.
        LD      ($5C8F),HL      ; set system variables ATTR_T and MASK_T.
                                ; Note. not really necessary as done by CLS.
        LD      (IY+$0E),L      ; set system variable BORDCR to colour scheme.
        LD      (IY+$57),H      ; set system variable P_FLAG to zero.

        LD      A,$07           ; load A with white.
        OUT     ($FE),A         ; directly change border colour.

        RST     10H             ; CALBAS
        DEFW    $0D6B           ; main CLS clears screen and sets colours.

        JP      L05C1           ; jump forward to END1.

; ----------------------------
; THE 'CLEAR# COMMAND' ROUTINE
; ----------------------------
;

;; CLR#-SYN
L057F:  RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR


        CP      $23             ; '#' ?

;; NONSENSE
L0584:  JP      NZ,L04B2        ; jump to OREPORT-1
                                ; 'Nonsense in BASIC'

        RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR


        CALL    L05B7           ; routine ST-END


        XOR     A               ;

;; ALL-STRMS
L058E:  PUSH    AF              ;
        SET     1,(IY+$7C)      ; sv FLAGS_3
        CALL    L1718           ; routine CLOSE
        POP     AF              ;
        INC     A               ;
        CP      $10             ;
        JR      C,L058E         ; back to ALL-STRMS

        JP      L05C1           ; jump to END1


; -----------------------------------------------------
; THE 'EXCHANGE FILE SPECIFIERS DSTRI AND STR2' ROUTINE
; -----------------------------------------------------
;   This routine is used by the MOVE routines to bring one of the two 8-byte
;   file specifiers into context.  There were two similar routines in the
;   first Interface 1 ROM and this, the most efficient, has survived.

;; EX-D-STR
L059F:  LD      HL,$5CD6        ; sv D_STR1. drive number
        LD      DE,$5CDE        ; sv D_STR2.
        LD      B,$08           ; eight bytes to swap.

;; ALL-BYTES
L05A7:  LD      A,(DE)          ; fetch byte 1.
        LD      C,(HL)          ; fetch byte 2.
        LD      (HL),A          ; place byte 1.
        LD      A,C             ; byte 2 to accumulator.
        LD      (DE),A          ; place byte 2.

        INC     HL              ; increment the
        INC     DE              ; two pointers.
        DJNZ    L05A7           ; loop back, for all eight, to ALL-BYTES.

        RET                     ; return.


; -----------------------
; THE 'SEPARATOR' ROUTINE
; -----------------------
;   This routine returns with zero flag set if the current character is
;   either a comma or semi-colon.

;; SEPARATOR
L05B1:  CP      $2C             ; is character ',' ?
        RET     Z               ; return with zero set if so.

        CP      $3B             ; is character ';' ?
        RET                     ; return.

; ------------------------------
; THE 'END OF STATEMENT' ROUTINE
; ------------------------------
;

;; ST-END
L05B7:  CP      $0D             ; is character carriage return ?
        JR      Z,L05BF         ; forward, if so, to TEST-RET

        CP      $3A             ; is character a ':' ?
        JR      NZ,L0584        ; back, if not, to NONSENSE


;; TEST-RET
L05BF:  RST     18H             ; checking syntax ?
        RET     NZ              ; return if not.


; --------------------------------------------
; THE 'RETURN TO THE MAIN INTERPRETER' ROUTINE
; --------------------------------------------
;

;; END1
L05C1:  LD      SP,($5C3D)      ; sv ERR_SP
        LD      (IY+$00),$FF    ; sv ERR_NR

        LD      HL,$1BF4        ; Main ROM address STMT-NEXT

        RST     18H             ; checking syntax ?
        JR      Z,L05E0         ; forward, if so, to RETAD-SYN

        LD      A,$7F           ;
        IN      A,($FE)         ;
        RRA                     ;
        JR      C,L05DD         ; forward to RETAD-RUN

        LD      A,$FE           ;
        IN      A,($FE)         ;
        RRA                     ;
        JR      NC,L05E2        ; forward to BREAK-PGM


;; RETAD-RUN
L05DD:  LD      HL,$1B7D        ; Main ROM address STMT-R-1

;; RETAD-SYN
L05E0:  PUSH    HL              ;
        RST     00H             ; to MAIN-ROM

; ---

;; BREAK-PGM
L05E2:  LD      (IY+$00),$14    ; insert error code in system variable ERR_NR.
        RST     28H             ; Error Main ROM 
                                ; 'BREAK into program'

; ----------------------------------------
; THE 'EVALUATE STRING EXPRESSION' ROUTINE
; ----------------------------------------
;

;; EXPT-STR
L05E7:  RST     10H             ; CALBAS
        DEFW    $1C8C           ; main EXPT-EXP
        RST     18H             ; checking syntax ?
        RET     Z

        PUSH    AF
        RST     10H             ; CALBAS
        DEFW    $2BF1           ; main STK-FETCH
        POP     AF
        RET


; -----------------------------------------
; THE 'EVALUATE CHANNEL EXPRESSION' ROUTINE
; -----------------------------------------
;

;; EXPT-SPEC
L05F2:  RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR


;; EXP-SPEC2
L05F5   CALL    L05E7           ; routine EXPT-STR evaluates a string e.g. "m"
                                ; start in DE, length in BC.

; one of the main tenets of Sinclair BASIC is that a value can be replaced 
; by an expression of the same type at any time, so this routine must allow
; something like "tomato"(3) as well as the more conventional "m" specifier.
; Only in runtime when the expression is evaluated can a single character be
; insisted upon.

        JR      Z,L060C         ; forward, if checking syntax, to TEST-NEXT.

        PUSH    AF              ; save following character.

        LD      A,C             ; in runtime check 
        DEC     A               ; immediately for 
        OR      B               ; a single character.

        JR      NZ,L062D        ; forward, if not, to NREPORT-3
                                ; 'Invalid device expression'

        LD      A,(DE)          ; fetch the addressed character.

        RST     10H             ; CALBAS
        DEFW    $2C8D           ; main ALPHA

        JR      NC,L062D        ; forward, if not alphabetic, to NREPORT-3

        AND     $DF             ; convert to uppercase with 'AND %11011111'

        LD      ($5CD9),A       ; place in system variable L_STR1 device letter.

        POP     AF              ; restore the following character.

;; TEST-NEXT
L060C:  CP      $0D             ; test for carriage return.
        RET     Z               ; return if so.

        CP      $3A             ; is character ':' ?
        RET     Z               ; return if so.

        CP      $A5             ; RND
        RET     NC              ; return with a token??

        CALL    L05B1           ; routine SEPARATOR tests for both ';' and ','.

        JP      NZ,L04B2        ; jump back, if not, to OREPORT-1
                                ; 'Nonsense in BASIC'

        RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR

; -----------------------------------------------
; THE 'EVALUATE NUMERIC DRIVE EXPRESSION' ROUTINE
; -----------------------------------------------
;   This routine is called once only to evaluate the numeric expression
;   following a 'CAT' command token or is used from above to check a numeric 
;   expression following for example "M"; .

;; EXPT-NUM
L061E:  RST     10H             ; CALBAS
        DEFW    $1C82           ; main EXPT-1NUM
        RST     18H             ; checking syntax ?
        RET     Z               ; return if checking syntax.

        PUSH    AF              ; save NZ not syntax flag

        RST     10H             ; CALBAS
        DEFW    $1E99           ; main FIND-INT2

        LD      ($5CD6),BC      ; set system variable D_STR1 drive number

        POP     AF              ; restore NZ not syntax flag

        RET                     ; return.

; ---

;; NREPORT-3
L062D:  RST     20H             ; Shadow Error Restart
        DEFB    $02             ; 'Invalid device expression'

; -------------------------------
; THE 'EVALUATE FILENAME' ROUTINE
; -------------------------------
;

;; EXPT-NAME
L062F:  RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR


        CALL    L05E7           ; routine EXPT-STR
        RET     Z

        PUSH    AF
        LD      A,C
        OR      B
        JR      Z,L064C         ; forward to NREPORT-4

        LD      HL,$000A
        SBC     HL,BC
        JR      C,L064C         ; forward to NREPORT-4

        LD      ($5CDA),BC      ; sv N_STR1
        LD      ($5CDC),DE      ; sv D_STR1
        POP     AF
        RET

; ---

;; NREPORT-4
L064C:  RST     20H             ; Shadow Error Restart
        DEFB    $03             ; Invalid name

; ------------------------------------
; THE 'EVALUATE STREAM NUMBER' ROUTINE
; ------------------------------------
;

;; EXPT-STRM
L064E:  RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR


        RST     10H             ; CALBAS
        DEFW    $1C82           ; main EXPT-1NUM
        RST     18H             ; checking syntax ?
        RET     Z               ;

        PUSH    AF              ;
        RST     10H             ; CALBAS
        DEFW    $1E94           ; main FIND-INT1
        CP      $10             ;
        JR      NC,L0663        ; forward to NREPORT-2

        LD      ($5CD8),A       ; sv D_STR1
        POP     AF              ;
        RET                     ;

; ---

;; NREPORT-2
L0663:  RST     20H             ; Shadow Error Restart
        DEFB    $01             ; Invalid stream number


; ----------------------------------
; THE 'CHECK "M" PARAMETERS' ROUTINE
; ----------------------------------
; called once from TEST-MNAM

;; CHECK-M
L0665:  LD      A,($5CD9)       ; fetch system variable L_STR1 device letter.
        CP      $4D             ; is character "M" ?
        JP      NZ,L062D        ; jump back, if not, to NREPORT-3
                                ; Error: 'Invalid device expression'.

;; CHECK-M-2
L066D:  LD      DE,($5CD6)      ; fetch system variable D_STR1 drive number.
        LD      A,E             ; test for
        OR      D               ; zero.
        JR      Z,L0681         ; forward, if so, to NREPORT-5
                                ; 'Invalid drive number'

        INC     DE              ; also test that
        LD      A,E             ; location does not hold
        OR      D               ; the default $FFFF value.
        JR      Z,L0683         ; forward, if so, to NREPORT-9
                                ; 'Missing drive number'.

        DEC     DE              ; restore to initial value.
        LD      HL,L0008        ; and test that
        SBC     HL,DE           ; drive is in range 1 - 8.
        RET     NC              ; return if so.


;; NREPORT-5
L0681:  RST     20H             ; Shadow Error Restart
        DEFB    $04             ; Invalid drive number
; ---

;; NREPORT-9
L0683:  RST     20H             ; Shadow Error Restart
        DEFB    $08             ; Missing drive number

; -----------------------------------------------
; THE 'CHECK "M" PARAMETERS AND FILENAME' ROUTINE
; -----------------------------------------------
; This routine checks that the device expression is "M", that the drive is in
; the range 1 - 8 and that the filename is not null.

;; TEST-MNAM
L0685:  CALL    L0665           ; routine CHECK-M checks for "M" and valid 
                                ; drive number.

        LD      A,($5CDB)       ; load A with D_STR1 the high byte of length
                                ; of filename.
        AND     A               ; test for zero.
        RET     Z               ; return if so.

; else system default $FF.

        RST     20H             ; Shadow Error Restart
        DEFB    $06             ; Missing name


; ----------------------------------
; THE 'CHECK STATION NUMBER' ROUTINE
; ----------------------------------
;

;; TEST-STAT
L068F:  LD      DE,($5CD6)      ; sv D_STR1 drive number
        INC     DE
        LD      A,E
        OR      D
        JR      Z,L06A1         ; forward to NREPORT-8

        DEC     DE
        LD      HL,L0040
        SBC     HL,DE
        RET     NC


;; NREPORT-6
L069F:  RST     20H             ; Shadow Error Restart
        DEFB    $05             ; Invalid station number

;; NREPORT-8
L06A1:  RST     20H             ; Shadow Error Restart
        DEFB    $07             ; Missing station number

; -----------------------------------
; THE 'EVALUATE "X";N;"NAME"' ROUTINE
; -----------------------------------
;

;; EXPT-EXPR
L06A3:  CALL    L05F2           ; routine EXPT-SPEC
        CALL    L05B1           ; routine SEPARATOR
        JP      NZ,L04B2        ; jump to OREPORT-1
                                ; 'Nonsense in BASIC'

        CALL    L062F           ; routine EXPT-NAME
        RET                     ; return...


; -----------------------------
; THE 'CHECK BAUD RATE' ROUTINE
; -----------------------------
;

;; TEST-BAUD
L06B0:  LD      HL,($5CD6)      ; sv D_STR1 drive number
        INC     HL
        LD      A,L
        OR      H
        RET     NZ

        RST     20H             ; Shadow Error Restart
        DEFB    $09             ; Missing baud rate

; -------------------------------------------
; THE 'EVALUATE STREAM OR EXPRESSION' ROUTINE
; -------------------------------------------
;

;; EXPT-EXP1
L06B9:  RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR


        CP      $23             ; is character '#' ?
        JP      Z,L064E         ; jump to EXPT-STRM

        CALL    L05F5           ; routine EXP-SPEC2
        CALL    L05B1           ; routine SEPARATOR
        JR      NZ,L06CC        ; forward to ENDHERE

        CALL    L062F           ; routine EXPT-NAME

;; ENDHERE
L06CC:  RST     18H             ; checking syntax ?
        RET     Z

        LD      A,($5CD9)       ; sv L_STR1 device letter.
        CP      $54             ; is character "T" ?
        RET     Z               ;

        CP      $42             ; is character "B" ?
        RET     Z               ;

        CP      $4E             ; is character "N" ?
        JP      Z,L068F         ; jump, if so, to TEST-STAT

        JP      L0685           ; jump to TEST-MNAM

; ---

        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF
        DEFB    $FF

; --------------------
; THE 'UNPAGE' ROUTINE
; --------------------
;

;; UNPAGE
L0700:  RET


; ---------------------------------
; THE 'EVALUATE PARAMETERS' ROUTINE
; ---------------------------------
;

;; EXPT-PRMS
L0701:  RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR


        CP      $2A             ; is character '*'
        JR      NZ,L073C        ; forward, if not, to OREP-1-2

        RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR


        CALL    L05F5           ; routine EXP-SPEC2
        CALL    L05B1           ; routine SEPARATOR
        JR      NZ,L0716        ; forward to NO-NAME

        CALL    L062F           ; routine EXPT-NAME

;; NO-NAME
L0716:  PUSH    AF
        LD      A,($5CD9)       ; sv L_STR1 device letter.

        CP      $4E             ; is character "N" ?
        JR      NZ,L0722        ; forward, if not, to NOT-NET

        SET     3,(IY+$7C)      ; update FLAGS_3 signal networking.

;; NOT-NET
L0722:  POP     AF
        CP      $0D             ; is character carriage return ?
        JR      Z,L0750         ; forward to END-EXPT

        CP      $3A             ; is character ':' ?
        JR      Z,L0750         ; forward to END-EXPT

        CP      $AA             ; is character the token 'SCREEN$' ?
        JR      Z,L0771         ; forward to SCREEN$

        CP      $AF             ; is character the token 'CODE' ?
        JR      Z,L0789         ; forward to CODE

        CP      $CA             ; is character the token 'LINE' ?
        JR      Z,L073E         ; forward to LINE

        CP      $E4             ; is character the token 'DATA' ?
        JP      Z,L07D2         ; jump to DATA

;; OREP-1-2
L073C:  RST     20H             ; Shadow Error Restart
        DEFB    $00             ; Nonsense in BASIC

; ---

;; LINE
L073E:  RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR

        RST     10H             ; CALBAS
        DEFW    $1C82           ; main EXPT-1NUM

        CALL    L05B7           ; routine ST-END

        RST     10H             ; CALBAS
        DEFW    $1E99           ; main FIND-INT2

        LD      ($5CED),BC      ; sv HD_11
        JR      L0753           ; forward to PROG

; ---

;; END-EXPT
L0750:  CALL    L05B7           ; routine ST-END

; the 'PROGRAM' SUBROUTINE is used when loading 'run'.

;; PROG
L0753:  XOR     A               ;
        LD      ($5CE6),A       ; sv HD_00
        LD      HL,($5C59)      ; sv E_LINE
        LD      DE,($5C53)      ; sv PROG
        LD      ($5CE9),DE      ; sv HD_0D
        SCF                     ;
        SBC     HL,DE           ;
        LD      ($5CE7),HL      ; sv HD_0B
        LD      HL,($5C4B)      ; sv VARS
        SBC     HL,DE           ;
        LD      ($5CEB),HL      ; sv HD_0F
        RET

; ---

;; SCREEN$
L0771:  RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR

        CALL    L05B7           ; routine ST-END
        LD      HL,$1B00
        LD      ($5CE7),HL      ; sv HD_0B
        LD      HL,$4000
        LD      ($5CE9),HL      ; sv HD_0D
        LD      A,$03
        LD      ($5CE6),A       ; sv HD_00
        RET

; ---

;; CODE
L0789:  RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR

        CP      $0D             ; is character a carriage return ?
        JR      Z,L079A         ; forward to DEFLT-0

        CP      $3A             ; is character a ':' ?
        JR      NZ,L079F        ; forward to PAR-1

        BIT     5,(IY+$7C)      ; sv FLAGS_3
        JR      NZ,L073C        ; back to OREP-1-2


;; DEFLT-0
L079A:  RST     10H             ; CALBAS
        DEFW    $1CE6           ; main USE-ZERO
        JR      L07A7           ; forward to TEST-SAVE

; ---

;; PAR-1
L079F:  RST     10H             ; CALBAS
        DEFW    $1C82           ; main EXPT-1NUM
        CALL    L05B1           ; routine SEPARATOR
        JR      Z,L07B2         ; forward to PAR-2


;; TEST-SAVE
L07A7:  BIT     5,(IY+$7C)      ; sv FLAGS_3
        JR      NZ,L073C        ; back to OREP-1-2

        RST     10H             ; CALBAS
        DEFW    $1CE6           ; main USE-ZERO
        JR      L07B8           ; forward to END-CODE

; ---

;; PAR-2
L07B2:  RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR


        RST     10H             ; CALBAS
        DEFW    $1C82           ; main EXPT-1NUM

;; END-CODE
L07B8:  RST     10H             ; CALBAS
        DEFW    $0018           ; main GET-CHAR

        CALL    L05B7           ; routine ST-END

        RST     10H             ; CALBAS
        DEFW    $1E99           ; main FIND-INT2
        LD      ($5CE7),BC      ; sv HD_0B

        RST     10H             ; CALBAS
        DEFW    $1E99           ; main FIND-INT2
        LD      ($5CE9),BC      ; sv HD_0D

        LD      A,$03
        LD      ($5CE6),A       ; sv HD_00
        RET                     ; return.

; ---
;
; ---


;; DATA
L07D2:  BIT     6,(IY+$7C)      ; sv FLAGS_3
        JR      Z,L07DA         ; forward to NO-M-ARR

        RST     20H             ; Shadow Error Restart
        DEFB    $14             ; MERGE error

;; NO-M-ARR
L07DA:  RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR


        RST     10H             ; CALBAS
        DEFW    $28B2           ; main LOOK-VARS

        SET     7,C
        JR      NC,L07F2        ; forward to EXISTING

        LD      HL,$0000
        BIT     4,(IY+$7C)      ; sv FLAGS_3
        JR      NZ,L080E        ; forward to LD-DATA

        LD      (IY+$00),$01    ; sv ERR_NR to '2 Variable not found'
        RST     28H             ; Error Main ROM

; ---

;; EXISTING
L07F2:  JR      Z,L07F6         ; forward to G-TYPE


;; NONS-BSC
L07F4:  RST     20H             ; Shadow Error Restart
        DEFB    $00             ; Nonsense in BASIC

; ---

;; G-TYPE
L07F6:  RST     18H             ; checking syntax ?
        JR      Z,L081C         ; forward to END-DATA

        BIT     5,(IY+$7C)      ; sv FLAGS_3
        JR      Z,L0803         ; forward to VR-DATA

        BIT     7,(HL)
        JR      Z,L07F4         ; back to NONS-BSC


;; VR-DATA
L0803:  INC     HL
        LD      A,(HL)
        LD      ($5CE7),A       ; sv HD_0B
        INC     HL
        LD      A,(HL)
        LD      ($5CE8),A       ; sv HD_0B_hi
        INC     HL

;; LD-DATA
L080E:  LD      A,C
        LD      ($5CEB),A       ; sv HD_0F
        LD      A,$01
        BIT     6,C
        JR      Z,L0819         ; forward to NUM-ARR

        INC     A

;; NUM-ARR
L0819:  LD      ($5CE6),A       ; sv HD_00

;; END-DATA
L081C:  EX      DE,HL
        RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR


        CP      $29             ; is character ')' ?
        JR      NZ,L07F4        ; back to NONS-BSC

        RST     10H             ; CALBAS
        DEFW    $0020           ; main NEXT-CHAR


        CALL    L05B7           ; routine ST-END
        LD      ($5CE9),DE      ; sv HD_0D
        RET                     ; return.


; ---------------------------------
; THE 'SAVE COMMAND SYNTAX' ROUTINE
; ---------------------------------
;

;; SAVE-SYN
L082F:  SET     5,(IY+$7C)      ; sv FLAGS_3
        CALL    L0701           ; routine EXPT-PRMS

        LD      A,($5CD9)       ; sv L_STR1 device letter.

        CP      $42             ; is character 'B' ?
        JR      Z,L084F         ; forward to SA-HEADER

        CP      $4E             ; is character 'N' ?
        JR      NZ,L0849        ; forward to SAVE-M

        CALL    L068F           ; routine TEST-STAT
        CALL    L0F46           ; routine OP-TEMP-N
        JR      L084F           ; forward to SA-HEADER

; ---

;; SAVE-M
L0849:  CALL    L0685           ; routine TEST-MNAM
        JP      L1AC4           ; jump to SAVE-RUN

; ---

;; SA-HEADER
L084F:  LD      B,$09
        LD      HL,$5CE6        ; sv HD_00

;; HD-LOOP
L0854:  CALL    L0884           ; routine SA-BYTE
        INC     HL
        DJNZ    L0854           ; back to HD-LOOP

        LD      HL,($5CE9)      ; sv HD_0D
        BIT     3,(IY+$7C)      ; sv FLAGS_3
        JR      Z,L086E         ; forward to SA-BLOCK

        LD      A,($5CE6)       ; sv HD_00
        CP      $03             ; compare with three - type CODE
        JR      NC,L086E        ; forward to SA-BLOCK

        LD      DE,$0114        ;
        ADD     HL,DE           ;

;; SA-BLOCK
L086E:  LD      BC,($5CE7)      ; sv HD_0B

;; SA-BLK-LP
L0872:  LD      A,C             ;
        OR      B               ;
        JR      Z,L0881         ; forward to S-BLK-END

        PUSH    IX              ;;;

        CALL    L0884           ; routine SA-BYTE

        POP     IX              ;;;

        DEC     BC              ;
        INC     HL              ;
        JR      L0872           ; back to SA-BLK-LP

; ---

;; S-BLK-END
L0881:  JP      L098C           ; jump to TST-MR-M

; --------------------------------------------------
; THE 'SAVE A BYTE TO NETWORK OR RS232 LINK' ROUTINE
; --------------------------------------------------
;

;; SA-BYTE
L0884:  PUSH    HL              ;
        PUSH    BC              ;
        BIT     3,(IY+$7C)      ; sv FLAGS_3
        LD      A,(HL)          ;
        JR      NZ,L0892        ; forward to SA-NET

        CALL    L0D07           ; routine BCHAN-OUT
        JR      L0895           ; forward to SA-B-END

; ---

;; SA-NET
L0892:  CALL    L0E09           ; routine NCHAN-OUT

;; SA-B-END
L0895:  POP     BC              ;
        POP     HL              ;
        RET                     ;


; ---------------------------------
; THE 'LOAD COMMAND SYNTAX' ROUTINE
; ---------------------------------
;

;; LOAD-SYN
L0898:  SET     4,(IY+$7C)      ; sv FLAGS_3
        CALL    L0701           ; routine EXPT-PRMS
        JP      L08B3           ; jump to LD-VF-MR

; -----------------------------------
; THE 'VERIFY COMMAND SYNTAX' ROUTINE
; -----------------------------------
;

;; VERIF-SYN
L08A2:  SET     7,(IY+$7C)      ; sv FLAGS_3
        CALL    L0701           ; routine EXPT-PRMS
        JP      L08B3           ; jump to LD-VF-MR

; ----------------------------------
; THE 'MERGE COMMAND SYNTAX' ROUTINE
; ----------------------------------
;

;; MRG-SYN
L08AC:  SET     6,(IY+$7C)      ; sv FLAGS_3
        CALL    L0701           ; routine EXPT-PRMS

; ----------------------------------------
; THE 'LOAD-VERIFY-MERGE COMMANDS' ROUTINE
; ----------------------------------------
;

;; LD-VF-MR
L08B3:  LD      HL,$5CE6        ; set source to HD_00
        LD      DE,$5CDE        ; set destination to D_STR2
        LD      BC,$0007        ; seven bytes to copy.
        LDIR                    ; copy type, start, length, length of program.

        LD      A,($5CD9)       ; sv L_STR1 device letter.

        CP      $4E             ; "N" ?

        JR      Z,L08D1         ; forward to TS-L-NET

        CP      $42             ; "B" ?

        JR      Z,L08D7         ; forward to TS-L-RS

; proceed with Microdrive device.

        CALL    L0685           ; routine TEST-MNAM return without error if
                                ; device is "M" and drive and filename are OK.

        CALL    L1971           ; routine F-M-HEAD loads the header type
                                ; record for the above filename and populates
                                ; the locations HD_00 to HD_11.

        JR      L08F6           ; forward to TEST-TYPE which tests that file
                                ; types agree and then loads rest of records.

; ---

;; TS-L-NET
L08D1:  CALL    L068F           ; routine TEST-STAT
        CALL    L0F46           ; routine OP-TEMP-N

;; TS-L-RS
L08D7:  LD      HL,$5CE6        ; sv HD_00
        LD      B,$09           ;

;; LD-HEADER
L08DC:  PUSH    HL
        PUSH    BC
        BIT     3,(IY+$7C)      ; sv FLAGS_3
        JR      Z,L08EB         ; forward to LD-HD-RS


;; LD-HD-NET
L08E4:  CALL    L0DAF           ; routine NCHAN-IN
        JR      NC,L08E4        ; back to LD-HD-NET

        JR      L08F0           ; forward to LD-HDR-2

; ---

;; LD-HD-RS
L08EB:  CALL    L0B88           ; routine BCHAN-IN
        JR      NC,L08EB        ; back to LD-HD-RS


;; LD-HDR-2
L08F0:  POP     BC
        POP     HL
        LD      (HL),A
        INC     HL
        DJNZ    L08DC           ; back to LD-HEADER

; -->

;; TEST-TYPE
L08F6:  LD      A,($5CDE)       ; sv D_STR2
        LD      B,A
        LD      A,($5CE6)       ; sv HD_00
        CP      B
        JR      NZ,L0906        ; forward to NREPORT-N

        CP      $03             ; compare with three - type CODE
        JR      Z,L0915         ; forward to T-M-CODE

        JR      C,L0908         ; forward to TST-MERGE

;; NREPORT-N
L0906:  RST     20H             ; Shadow Error Restart
        DEFB    $16             ; Wrong file type

; ---

;; TST-MERGE
L0908:  BIT     6,(IY+$7C)      ; sv FLAGS_3
        JR      NZ,L096B        ; forward to MERGE-BLK

        BIT     7,(IY+$7C)      ; sv FLAGS_3
        JP      Z,L09A7         ; jump to LD-PR-AR

;; T-M-CODE
L0915:  BIT     6,(IY+$7C)      ; sv FLAGS_3
        JR      Z,L091D         ; forward to LD-BLOCK

        RST     20H             ; Shadow Error Restart
        DEFB    $14             ; MERGE error

; ---

;; LD-BLOCK
L091D:  LD      HL,($5CDF)      ; sv D_STR2 (+1) length of data
        LD      DE,($5CE7)      ; sv HD_0B
        LD      A,H             ;
        OR      L               ;
        JR      Z,L0936         ; forward to LD-BLK-2

        SBC     HL,DE           ;
        JR      NC,L0936        ; forward to LD-BLK-2

        BIT     4,(IY+$7C)      ; sv FLAGS_3
        JR      Z,L0934         ; forward to NREPORT-L

        RST     20H             ; Shadow Error Restart
        DEFB    $13             ; Code Error

; ---

;; NREPORT-L
L0934:  RST     20H             ; Shadow Error Restart
        DEFB    $15             ; Verification has failed

; ---

;; LD-BLK-2
L0936:  LD      HL,($5CE1)      ; sv L_STR2
        LD      A,(IX+$04)      ; channel letter
        CP      $CD             ; 'M' +$80 ?
        JR      NZ,L0945        ; forward to LD-BLK-3

        LD      HL,($5CE4)      ; sv D_STR2             ********
        JR      L0956           ; forward to LD-BLK-4

; ---

;; LD-BLK-3
L0945:  BIT     3,(IY+$7C)      ; sv FLAGS_3
        JR      Z,L0956         ; forward to LD-BLK-4

        LD      A,($5CE6)       ; sv HD_00
        CP      $03             ; compare with three - type CODE
        JR      Z,L0956         ; forward to LD-BLK-4

        LD      BC,$0114        ;
        ADD     HL,BC           ;

;; LD-BLK-4
L0956:  LD      A,H             ;
        OR      L               ;
        JR      NZ,L095D        ; forward to LD-BLK-5

        LD      HL,($5CE9)      ; sv HD_0D

;; LD-BLK-5
L095D:  LD      A,($5CE6)       ; sv HD_00
        AND     A               ;
        JR      NZ,L0966        ; forward to LD-NO-PGM

        LD      HL,($5C53)      ; sv PROG

;; LD-NO-PGM
L0966:  CALL    L0A60           ; routine LV-ANY
        JR      L098C           ; forward to TST-MR-M

; ---


;; MERGE-BLK
L096B:  LD      A,($5CEE)       ; sv HD_11_hi
        AND     $C0             ;
        JR      NZ,L0977        ; forward to NO-AUTOST

        CALL    L17B7           ; routine RCL-T-CH


        RST     20H             ; Shadow Error Restart
        DEFB    $14             ; MERGE error

; ---

;; NO-AUTOST
L0977:  LD      BC,($5CE7)      ; sv HD_0B
        PUSH    BC              ;
        INC     BC              ;

        RST     10H             ; CALBAS
        DEFW    $0030           ; main BC-SPACES

        LD      (HL),$80        ;
        EX      DE,HL           ;
        POP     DE              ;
        PUSH    HL              ;
        CALL    L0A60           ; routine LV-ANY
        POP     HL              ;

        RST     10H             ; CALBAS
        DEFW    $08CE           ; main ME-CTRLX

; ---

;; TST-MR-M
L098C:  LD      A,(IX+$04)      ; channel letter
        CP      $CD             ; 'M' + $80 ?
        JR      NZ,L0998        ; forward to TST-MR-N

        CALL    L138E           ; routine CLOSE-M2
        JR      L09A4           ; forward to MERGE-END

; ---

;; TST-MR-N
L0998:  BIT     3,(IY+$7C)      ; sv FLAGS_3
        JR      Z,L09A4         ; forward to MERGE-END

        CALL    L0FAE           ; routine SEND-NEOF
        CALL    L17B7           ; routine RCL-T-CH

;; MERGE-END
L09A4:  JP      L05C1           ; jump to END1

; ---

;; LD-PR-AR
L09A7:  LD      DE,($5CE7)      ; sv HD_0B
        LD      HL,($5CE1)      ; sv L_STR2
        PUSH    HL              ;
        LD      A,H             ;
        OR      L               ;
        JR      NZ,L09B9        ; forward to LD-PROG

        INC     DE              ;
        INC     DE              ;
        INC     DE              ;
        EX      DE,HL           ;
        JR      L09C2           ; forward to TST-SPACE

; ---


;; LD-PROG
L09B9:  LD      HL,($5CDF)      ; sv D_STR2 (+1) length of data
        EX      DE,HL           ;
        SCF                     ;
        SBC     HL,DE           ;
        JR      C,L09CB         ; forward to TST-TYPE


;; TST-SPACE
L09C2:  LD      DE,$0005        ;
        ADD     HL,DE           ;
        LD      B,H             ;
        LD      C,L             ;

        RST     10H             ; CALBAS
        DEFW    $1F05           ; main TEST-ROOM

;   Note. that before the above call, interrupts are disabled and the motor
;   of the microdrive is running.  If there should be insufficient room,
;   then the processor stops at the HALT instruction at address $1303
;   (MAIN-4), in the main ROM, while trying to output the "Out of Memory"
;   report.  This could be corrected by replacing the above 3 bytes to a
;   call to a 6-byte subroutine which carries out the same instructions
;   between an EI/DI pair.  In the production of the "Out of Memory" report
;   this ROM will be paged again by the instruction fetch at 0008. The
;   motors are stopped at START-4 and then Control will then pass to the
;   other ROM to execute the "LD A,(HL)", then back to this ROM to eliminate
;   the "OK" message before a final switch to the Main ROM for the actual
;   message text.

;; TST-TYPE
L09CB:  POP     HL
        LD      A,($5CE6)       ; sv HD_00
        AND     A
        JR      Z,L0A19         ; forward to SET-PROG

        LD      A,H
        OR      L
        JR      Z,L09F7         ; forward to CRT-NEW

        LD      A,(IX+$04)      ; channel letter
        CP      $CD             ; is character an inverted "M" ?
        JR      NZ,L09E2        ; forward to T-LD-NET

        LD      HL,($5CE4)      ; sv D_STR2
        JR      L09EC           ; forward to RCLM-OLD

; ---

;; T-LD-NET
L09E2:  BIT     3,(IY+$7C)      ; sv FLAGS_3
        JR      Z,L09EC         ; forward to RCLM-OLD

        LD      DE,$0114
        ADD     HL,DE

;; RCLM-OLD
L09EC:  DEC     HL
        LD      B,(HL)
        DEC     HL
        LD      C,(HL)
        DEC     HL
        INC     BC
        INC     BC
        INC     BC
        RST     10H             ; CALBAS
        DEFW    $19E8           ; main RECLAIM-2

;; CRT-NEW
L09F7:  LD      HL,($5C59)      ; sv E_LINE
        DEC     HL
        LD      BC,($5CE7)      ; sv HD_0B
        PUSH    BC
        INC     BC
        INC     BC
        INC     BC
        LD      A,($5CE3)       ; sv D_STR2
        PUSH    AF
        RST     10H             ; CALBAS
        DEFW    $1655           ; main MAKE-ROOM
        INC     HL
        POP     AF
        LD      (HL),A
        POP     DE
        INC     HL
        LD      (HL),E
        INC     HL
        LD      (HL),D
        INC     HL

;; END-LD-PR
L0A13:  CALL    L0A60           ; routine LV-ANY

        JP      L098C           ; jump to TST-MR-M

; ---

;; SET-PROG
L0A19:  RES     1,(IY+$7C)      ; sv FLAGS_3
        LD      DE,($5C53)      ; sv PROG
        LD      HL,($5C59)      ; sv E_LINE
        DEC     HL
        RST     10H             ; CALBAS
        DEFW    $19E5           ; main RECLAIM-1
        LD      BC,($5CE7)      ; sv HD_0B
        LD      HL,($5C53)      ; sv PROG
        RST     10H             ; CALBAS
        DEFW    $1655           ; main MAKE-ROOM
        INC     HL
        LD      BC,($5CEB)      ; sv HD_0F
        ADD     HL,BC
        LD      ($5C4B),HL      ; sv VARS
        LD      A,($5CEE)       ; sv HD_11_hi
        LD      H,A
        AND     $C0
        JR      NZ,L0A52        ; forward to NO-AUTO

        SET     1,(IY+$7C)      ; sv FLAGS_3
        LD      A,($5CED)       ; sv HD_11
        LD      L,A
        LD      ($5C42),HL      ; sv NEWPPC
        LD      (IY+$0A),$00    ; sv NSPPC

;; NO-AUTO
L0A52:  LD      HL,($5C53)      ; sv PROG
        LD      DE,($5CE7)      ; sv HD_0B
        DEC     HL
        LD      ($5C57),HL      ; sv DATADD
        INC     HL
        JR      L0A13           ; back to END-LD-PR


; ----------------------------
; THE 'LOAD OR VERIFY' ROUTINE
; ----------------------------
;   This routine is able to either LOAD or VERIFY a block of bytes, from any 
;   of the three possible binary sources, A Microdrive cartridge, the Binary
;   "B" RS232 channel or the Network "N" channel.
;   The block could be a program, code bytes or an array and the first 
;   receiving location is in HL and the length in DE.

;; LV-ANY
L0A60:  LD      A,D             ; test the length
        OR      E               ; for zero.
        RET     Z               ; return if so.

        LD      A,(IX+$04)      ; fetch channel letter
        CP      $CD             ; is letter "M" + $80 ?

        JR      NZ,L0A6E        ; forward, if not, to LV-BN to load from 
                                ; the B channel or network.

; else is a temporary "M" channel so load or verify and then return.

        CALL    L199A           ; routine LV-MCH loads or verifies a block
                                ; of code from microdrive.

        RET                     ; return after called routine.

; ---

; Load or Verify from B channel or Network.

;; LV-BN
L0A6E:  PUSH    HL              ; save address.
        PUSH    DE              ; save byte count.
        BIT     3,(IY+$7C)      ; test FLAGS_3 - using network ?
        JR      Z,L0A7D         ; forward, if not, to LV-B

; Load or Verify from "N" channel.

;; LV-N
L0A76:  CALL    L0DAF           ; routine NCHAN-IN
        JR      NC,L0A76        ; back to LV-N

        JR      L0A82           ; forward to LV-BN-E

; ---

; Load or Verify from "B" channel.

;; LV-B
L0A7D:  CALL    L0B88           ; routine BCHAN-IN
        JR      NC,L0A7D        ; back to LV-B

; Load or Verify "B","N" end test.

;; LV-BN-E
L0A82:  POP     DE              ; restore code length.
        DEC     DE              ; and decrement.
        POP     HL              ; restore load address.

        BIT     7,(IY+$7C)      ; test FLAGS_3 - verify operation.
        JR      NZ,L0A8E        ; forward, if so missing load, to VR-BN

        LD      (HL),A          ; load the byte into memory.
        JR      L0A93           ; forward to LVBN-END

; ---

; Verify "B" or "N" bytes.

;; VR-BN
L0A8E:  CP      (HL)            ; compare the received byte with the byte in
                                ; memory.
        JR      Z,L0A93         ; forward, with match, to LVBN-END.

        RST     20H             ; Shadow Error Restart
        DEFB    $15             ; 'Verification has failed'

; ---

; Load or Verify "B","N" end.

;; LVBN-END
L0A93:  INC     HL              ; increment the address.
        LD      A,E             ; test the byte 
        OR      D               ; counter for zero.
        JR      NZ,L0A6E        ; back, if not, to LV-BN

        RET                     ; return.


; --------------------------------
; THE 'LOAD "RUN" PROGRAM' ROUTINE
; --------------------------------
;

;; LOAD-RUN
L0A99:  LD      BC,$0001        ; set drive to one.
        LD      ($5CD6),BC      ; update D_STR1 drive number.

        LD      BC,$0003        ; length of "run" is three.
        LD      ($5CDA),BC      ; update N_STR1 length of filename.

        LD      BC,L0ACA        ; addr: NAME-RUN (below)
        LD      ($5CDC),BC      ; update A_STR1 - address of filename.

        SET     4,(IY+$7C)      ; update FLAGS_3 signal a LOAD operation.

        CALL    L0753           ; routine PROG sets up the first seven header 
                                ; bytes for a program.

        LD      HL,$5CE6        ; set start to HD_00
        LD      DE,$5CDE        ; set destination to D_STR2
        LD      BC,$0009        ; nine bytes are copied.
                                ; Note. should be seven but is mostly harmless.

        LDIR                    ; block copy.

        SET     7,(IY+$0A)      ; update Main NSPPC - signal no jump to be made.

        CALL    L1971           ; routine F-M-HEAD loads the header type 
                                ; record for the 'run' file and populates
                                ; the nine locations HD_00 to HD_11.

        JP      L08F6           ; jump back to TEST-TYPE to test that type is
                                ; 'program' and load the rest.

; ---

;; NAME-RUN
L0ACA:  DEFM    "run"           ; the filename "run"

; *******************************************
; **  T H E   R S 2 3 2   R O U T I N E S  **
; *******************************************

; ----------------------------------------
; THE 'SET "BAUD" SYSTEM VARIABLE' ROUTINE
; ----------------------------------------
;

;; SET-BAUD
L0ACD:  LD      BC,($5CD6)      ; sv D_STR1 drive number
        LD      HL,L0AF3        ; RS-CONSTS

;; NXT-ENTRY
L0AD4:  LD      E,(HL)
        INC     HL
        LD      D,(HL)
        INC     HL
        EX      DE,HL
        LD      A,H
        CP      $4B             ;
        JR      NC,L0AE8        ; forward to END-SET

        AND     A
        SBC     HL,BC
        JR      NC,L0AE8        ; forward to END-SET

        EX      DE,HL
        INC     HL
        INC     HL
        JR      L0AD4           ; loop back to NXT-ENTRY

; ---

;; END-SET
L0AE8:  EX      DE,HL
        LD      E,(HL)
        INC     HL
        LD      D,(HL)
        LD      ($5CC3),DE      ; sv BAUD
        JP      L05C1           ; jump to END1

; ------------------------------------
; THE 'RS232 TIMING CONSTANTS' ROUTINE
; ------------------------------------
;

;; RS-CONSTS
L0AF3:  DEFW    $0032           ;
        DEFW    $0A82           ;
        DEFW    $006E           ;
        DEFW    $04C5           ;
        DEFW    $012C           ;
        DEFW    $01BE           ;
        DEFW    $0258           ;
        DEFW    $00DE           ;
        DEFW    $04B0           ;
        DEFW    $006E           ;
        DEFW    $0960           ;
        DEFW    $0036           ;
        DEFW    $12C0           ;
        DEFW    $001A           ;
        DEFW    $2580           ;
        DEFW    $000C           ;
        DEFW    $4B00           ;
        DEFW    $0005           ;


; ----------------------------------------------
; THE 'OPEN RS232 CHANNEL IN CHANS AREA' ROUTINE
; ----------------------------------------------
;

;; OP-RS-CH
L0B17:  LD      HL,($5C53)      ; use system variable PROG to address the
                                ; location following the Channels area.
        DEC     HL              ; step back to the end-marker.
        LD      BC,$000B        ; eleven bytes of room required.
        PUSH    BC              ; save bytes

        RST     10H             ; CALBAS
        DEFW    $1655           ; main routine MAKE-ROOM opens up the space.
                                ; register HL points to location before room.

        POP     BC              ; bring back the eleven bytes.

        PUSH    DE              ; save DE briefly
        CALL    L1A82           ; routine REST-N-AD adjusts the dynamic memory
                                ; pointers to filenames in D_STR1 and D_STR2.
        POP     DE              ; restore DE.

        LD      HL,L0B76 - 1    ; last byte of T-Channel info.
        LD      BC,$000B        ; eleven bytes to copy.
        LDDR                    ; block copy downwards.

        INC     DE              ;
        LD      A,($5CD9)       ; sv L_STR1 device letter.
        CP      $42             ; is it "B" ?
        RET     NZ              ; return as must be "T".

; but if this is to be a binary channel then overwrite the letter and the output
; and input routines.

        PUSH    DE              ;

        LD      HL,$0004        ;
        ADD     HL,DE           ;

        LD      (HL),$42        ; 'B'
        INC     HL              ;

        LD      DE,L0D07        ; address B-CHAN-OUT
        LD      (HL),E          ;
        INC     HL              ;
        LD      (HL),D          ;
        INC     HL              ;

        LD      DE,L0B7C        ; address B-INPUT
        LD      (HL),E          ;
        INC     HL              ;
        LD      (HL),D          ;

        POP     DE              ;
        RET                     ; return.


; ----------------------------------------
; THE 'ATTACH CHANNEL TO A STREAM' ROUTINE
; ----------------------------------------
;

;; OP-RSCHAN
L0B4E:  CALL    L0B17           ; routine OP-RS-CH

;; OP-STREAM
L0B51:  LD      HL,($5C4F)      ; sv CHANS
        DEC     HL
        EX      DE,HL
        AND     A
        SBC     HL,DE
        EX      DE,HL
        LD      HL,$5C16        ; sv STRMS_00
        LD      A,($5CD8)       ; sv D_STR1
        RLCA
        LD      C,A
        LD      B,$00
        ADD     HL,BC
        LD      (HL),E
        INC     HL
        LD      (HL),D
        JP      L05C1           ; jump to END1

; ----------------------
; THE '"T" CHANNEL DATA'
; ----------------------
; the eleven-byte "T" CHANNEL descriptor.

;; TCHAN-DAT
L0B6B:  DEFW    $0008           ; main ERROR-1
        DEFW    $0008           ; main ERROR-1
        DEFB    $54             ; character "T"
        DEFW    L0C3A           ; TCHAN-OUT
        DEFW    L0B76           ; T-INPUT
        DEFW    $000B           ; channel length - 11 bytes.

; -------------------------------
; THE '"T" CHANNEL INPUT' ROUTINE
; -------------------------------
;

;; T-INPUT
L0B76:  LD      HL,L0B82        ; address of routine TCHAN-IN
        JP      L0D5A           ; jump to CALL-INP

; -------------------------------
; THE '"B" CHANNEL INPUT' ROUTINE
; -------------------------------
;

;; B-INPUT
L0B7C:  LD      HL,L0B88        ; address of routine BCHAN-IN
        JP      L0D5A           ; jump to CALL-INP

; ---------------------------------------
; THE '"T" CHANNEL INPUT SERVICE' ROUTINE
; ---------------------------------------
;

;; TCHAN-IN
L0B82:  CALL    L0B88           ; routine BCHAN-IN
        RES     7,A
        RET


; ---------------------------------------
; THE '"B" CHANNEL INPUT SERVICE' ROUTINE
; ---------------------------------------
; (Hook Code: $1D)

;; BCHAN-IN
L0B88:  LD      HL,$5CC7        ; sv SER_FL
        LD      A,(HL)          ;
        AND     A               ;
        JR      Z,L0B95         ; forward to REC-BYTE

        LD      (HL),$00        ;
        INC     HL              ;
        LD      A,(HL)          ;
        SCF                     ;

        RET                     ; Return.

; ---

;; REC-BYTE
L0B95:  CALL    L163E           ; routine TEST-BRK

        DI                      ; Disable Interrupts

        LD      A,($5CC6)       ; sv IOBORD
        OUT     ($FE),A

        LD      DE,($5CC3)      ; sv BAUD
        LD      HL,$0320        ; 800d.
        LD      B,D             ;
        LD      C,E             ;
        SRL     B               ;
        RR      C               ;
        LD      A,$FE           ;
        OUT     ($EF),A         ;

;; READ-RS
L0BAF:  IN      A,($F7)         ; bit 7 is input serial data (txdata)
        RLCA                    ;
        JR      NC,L0BC3        ; forward to TST-AGAIN

        IN      A,($F7)         ;
        RLCA                    ;
        JR      NC,L0BC3        ; forward to TST-AGAIN

        IN      A,($F7)         ;
        RLCA                    ;
        JR      NC,L0BC3        ; forward to TST-AGAIN

        IN      A,($F7)         ;
        RLCA                    ;
        JR      C,L0BCF         ; forward to START-BIT


;; TST-AGAIN
L0BC3:  DEC     HL              ;
        LD      A,H             ;
        OR      L               ;
        JR      NZ,L0BAF        ; back to READ-RS

        PUSH    AF              ;
        LD      A,$EE           ;
        OUT     ($EF),A         ;
        JR      L0BEE           ; forward to WAIT-1

; ---

;; START-BIT
L0BCF:  LD      H,B             ; Load HL with halved BAUD value.
        LD      L,C             ;

        LD      B,$80           ; Load B with the start bit.

        DEC     HL              ; Reduce the counter by the time for the four
        DEC     HL              ; tests.
        DEC     HL              ;

;; SERIAL-IN
L0BD6:  ADD     HL,DE           ; Add the BAUD value.
        NOP                     ; (4) a timing value.

;; BD-DELAY
L0BD8:  DEC     HL              ; (6) Delay for 26 * BAUD
        LD      A,H             ; (4)
        OR      L               ; (4)
        JR      NZ,L0BD8        ; (12) back to BD-DELAY

        ADD     A,$00           ; (7) wait
        IN      A,($F7)         ; Read a bit.
        RLCA                    ; Rotate bit 7 to carry.
        RR      B               ; pick up carry in B
        JR      NC,L0BD6        ; back , if no start bit, to SERIAL-IN

        LD      A,$EE           ; Send CTS line low  (comms data 0 also)
        OUT     ($EF),A         ; send to serial port

        LD      A,B             ; Transfer the received byte to A.
        CPL                     ; Complement.
        SCF                     ; Set Carry to signal success.
        PUSH    AF              ; (*) push the success flag.

;   The success and failure (time out) paths converge here with the HL register
;   holding zero.

;; WAIT-1
L0BEE:  ADD     HL,DE           ; (11) transfer DE (BAUD) to HL.

;; WAIT-2
L0BEF:  DEC     HL              ; ( 6) delay for stop bit.
        LD      A,L             ; ( 4)
        OR      H               ; ( 4)
        JR      NZ,L0BEF        ; (12/7) back to WAIT-2

;   Register HL is now zero again.

        ADD     HL,DE           ; HL = 0 + BAUD
        ADD     HL,DE           ; HL = 2 * BAUD
        ADD     HL,DE           ; HL = 3 * BAUD

;   The device at the other end of the cable (not a Spectrum) may send a 
;   second byte even though CTS (Clear To Send) is low.

;; T-FURTHER
L0BF7:  DEC     HL              ; Decrement counter.
        LD      A,L             ; Test for
        OR      H               ; zero.
        JR      Z,L0C34         ; forward, if no second byte, to END-RS-IN

        IN      A,($F7)         ; Read TXdata.
        RLCA                    ; test the bit read.
        JR      NC,L0BF7        ; back, if none,  to T-FURTHER

;   As with first byte, TXdata must be high four four tests.

        IN      A,($F7)         ;
        RLCA                    ;
        JR      NC,L0BF7        ; back to T-FURTHER

        IN      A,($F7)         ;
        RLCA                    ;
        JR      NC,L0BF7        ; back to T-FURTHER

        IN      A,($F7)         ;
        RLCA                    ;
        JR      NC,L0BF7        ; back to T-FURTHER


;   A second byte is on its way and is received exactly as before.

        LD      H,D             ;
        LD      L,E             ;
        SRL     H               ;
        RR      L               ;
        LD      B,$80           ;
        DEC     HL              ;
        DEC     HL              ;
        DEC     HL              ;

;; SER-IN-2
L0C1B:  ADD     HL,DE           ;
        NOP                     ; timing.

;; BD-DELAY2
L0C1D:  DEC     HL              ;
        LD      A,H             ;
        OR      L               ;
        JR      NZ,L0C1D        ; back to BD-DELAY2

        ADD     A,$00           ;
        IN      A,($F7)         ;
        RLCA                    ;
        RR      B               ;
        JR      NC,L0C1B        ; back to SER-IN-2

;  The start bit has been pushed out and B contains the second received byte.

        LD      HL,$5CC7        ; Address the SER_FL System Variable.

        LD      (HL),$01        ; Signal there is a byte in the next location.
        INC     HL              ; Address that location.
        LD      A,B             ; Transfer the byte to A.
        CPL                     ; Complement
        LD      (HL),A          ; and insert in the second byte of serial flag.

;; END-RS-IN
L0C34:  CALL    L0D4D           ; routine BORD-REST

        POP     AF              ; ( either 0 and NC or the first received byte
                                ;   and the carry flag set ) 

        EI                      ; Enable Interrupts

        RET                     ; Return.

; --------------------------------
; THE '"T" CHANNEL OUTPUT' ROUTINE
; --------------------------------
;   The text channel output routine is able to list programs and, when 
;   printing, takes correct action with TAB values etc.

;; TCHAN-OUT
L0C3A:  CP      $A5             ; 'RND' - first token
        JR      C,L0C44         ; forward, if less, to NOT-TOKEN

        SUB     $A5             ; reduce to range $00-5A
        RST     10H             ; CALBAS
        DEFW    $0C10           ; main PO-TOKENS
        RET                     ; return.

; ---

;; NOT-TOKEN
L0C44:  LD      HL,$5C3B        ; Address the FLAGS System Variable.
        RES     0,(HL)          ; update FLAGS - allow for leading space.
        CP      $20             ; compare to space
        JR      NZ,L0C4F        ; forward, if not, to NOT-LEAD

        SET     0,(HL)          ; update FLAGS - signal suppress leading space.

;; NOT-LEAD
L0C4F:  CP      $7F             ; compare to copyright symbol. (DEL in ASCII)
        JR      C,L0C55         ; forward, if less, to NOT-GRAPH

        LD      A,$3F           ; output CHR$(127) and graphics as '?'

;; NOT-GRAPH
L0C55:  CP      $20             ; compare against space.
        JR      C,L0C70         ; forward to CTRL-CD

        PUSH    AF              ; Preserve character.

        INC     (IY+$76)        ; Increment width         NMI_ADD_lo
        LD      A,($5CB1)       ; Load A with limit from  NMI_ADD_hi
        CP      (IY+$76)        ; Compare to width        NMI_ADD_lo

        JR      NC,L0C6C        ; forward, if less or equal, to EMIT-CH

        CALL    L0C74           ; routine TAB-SETZ emits CR/LF.

        LD      (IY+$76),$01    ; Set width to one        NMI_ADD_lo

;; EMIT-CH
L0C6C:  POP     AF              ; Restore the unprinted character.

        JP      L0D07           ; jump to BCHAN-OUT

; ---

;; CTRL-CD
L0C70:  CP      $0D             ; carriage return ?
        JR      NZ,L0C82        ; forward to NOT-CR


;; TAB-SETZ
L0C74:  LD      (IY+$76),$00    ; sv NMI_ADD_lo
        LD      A,$0D           ; output a CR carriage return.
        CALL    L0D07           ; routine BCHAN-OUT
        LD      A,$0A           ; output a LF line feed.
        JP      L0D07           ; jump to BCHAN-OUT

; ---

;; NOT-CR
L0C82:  CP      $06             ;
        JR      NZ,L0CA5        ; forward to NOT-CMM

        LD      BC,($5CB0)      ; sv NMI_ADD
        LD      E,$00           ;

;; SPC-COUNT
L0C8C:  INC     E
        INC     C
        LD      A,C
        CP      B
        JR      Z,L0C9A         ; forward to CMM-LP2


;; CMM-LOOP
L0C92:  SUB     $08
        JR      Z,L0C9A         ; forward to CMM-LP2

        JR      NC,L0C92        ; back to CMM-LOOP

        JR      L0C8C           ; back to SPC-COUNT


;; CMM-LP2
L0C9A:  PUSH    DE
        LD      A,$20
        CALL    L0C3A           ; routine TCHAN-OUT
        POP     DE
        DEC     E
        RET     Z

        JR      L0C9A           ; back to CMM-LP2

; ---

;; NOT-CMM
L0CA5:  CP      $16
        JR      Z,L0CB5         ; forward to TAB-PROC

        CP      $17
        JR      Z,L0CB5         ; forward to TAB-PROC

        CP      $10
        RET     C

        LD      DE,$0CD0
        JR      L0CB8           ; forward to STORE-COD

; ---

;; TAB-PROC
L0CB5:  LD      DE,L0CC8        ; addr: TAB-SERV

;; STORE-COD
L0CB8:  LD      ($5C0E),A       ; sv TVDATA

;; ALTER-OUT
L0CBB:  LD      HL,($5C51)      ; sv CURCHL
        PUSH    DE
        LD      DE,$0005
        ADD     HL,DE
        POP     DE
        LD      (HL),E
        INC     HL
        LD      (HL),D
        RET

; ---

;; TAB-SERV
L0CC8:  LD      DE,L0CD0        ; addr: TAB-SERV2
        LD      ($5C0F),A       ; sv TVDATA
        JR      L0CBB           ; back to ALTER-OUT

; ---

;; TAB-SERV2
L0CD0:  LD      DE,L0C3A        ; addr: TCHAN-OUT
        CALL    L0CBB           ; routine ALTER-OUT
        LD      D,A
        LD      A,($5C0E)       ; sv TVDATA
        CP      $16             ; AT control code ?
        JR      Z,L0CE6         ; forward to TST-WIDTH

        CP      $17             ; TAB control code ?
        CCF
        RET     NZ

        LD      A,($5C0F)       ; sv TVDATA
        LD      D,A

;; TST-WIDTH
L0CE6:  LD      A,($5CB1)       ; sv NMI_ADD
        CP      D
        JR      Z,L0CEE         ; forward to TAB-MOD

        JR      NC,L0CF4        ; forward to TABZERO


;; TAB-MOD
L0CEE:  LD      B,A
        LD      A,D
        SUB     B
        LD      D,A
        JR      L0CE6           ; back to TST-WIDTH

; ---

;; TABZERO
L0CF4:  LD      A,D
        OR      A
        JP      Z,L0C74         ; jump to TAB-SETZ

;; TABLOOP
L0CF9:  LD      A,($5CB0)       ; sv NMI_ADD_lo
        CP      D               ;
        RET     Z               ;

        PUSH    DE              ;
        LD      A,$20           ;
        CALL    L0C3A           ; routine TCHAN-OUT
        POP     DE              ;
        JR      L0CF9           ; back to TABLOOP


; --------------------------------
; THE '"B" CHANNEL OUTPUT' ROUTINE
; --------------------------------
; (Hook Code: $1E)
;   The bits of a byte are sent inverted. They are fixed in length and heralded
;   by a start bit and followed by two stop bits.

;; BCHAN-OUT
L0D07:  LD      B,$0B           ; Set bit count to eleven - 1 + 8 + 2.

        CPL                     ; Invert the bits of the character.
        LD      C,A             ; Copy the character to C.

        LD      A,($5CC6)       ; Load A from System Variable IOBORD
        OUT     ($FE),A         ; Change the border colour.

        LD      A,$EF           ; Set to %11101111
        OUT     ($EF),A         ; Make CTS (Clear to Send) low.

        CPL                     ; reset bit 0 (other bits of no importance)
        OUT     ($F7),A         ; Make RXdata low. %00010000

        LD      HL,($5CC3)      ; Fetch value from BAUD System Variable.
        LD      D,H             ; Copy BAUD value to DE for count.
        LD      E,L             ;

;; BD-DEL-1
L0D1C:  DEC     DE              ; ( 6) Wait 26 * BAUD cycles
        LD      A,D             ; ( 4) 
        OR      E               ; ( 4)
        JR      NZ,L0D1C        ; (12) back to BD-DEL-1

;; TEST-DTR
L0D21:  CALL    L163E           ; routine TEST-BRK allows user to stop.
        IN      A,($EF)         ; Read the communication port.
        AND     $08             ; isolate DTR (Data Terminal Ready) bit.
        JR      Z,L0D21         ; back, until DTR found high, to TEST-DTR

        SCF                     ; Set carry flag as the start bit.
        DI                      ; Disable Interrupts.

;; SER-OUT-L
L0D2C:  ADC     A,$00           ; Set bit 0            76543210 <- C  
        OUT     ($F7),A         ; Send RXdata the start bit.

        LD      D,H             ; Transfer the BAUD value to DE for count.
        LD      E,L             ;

;; BD-DEL-2
L0D32:  DEC     DE              ; ( 6) Wait for 26 * BAUD
        LD      A,D             ; ( 4)
        OR      E               ; ( 4)
        JR      NZ,L0D32        ; (12) back to BD-DEL-2

        DEC     DE              ; ( 6) 
        XOR     A               ; ( 4) clear rxdata bit
        SRL     C               ;      shift a bit of output byte to carry.
        DJNZ    L0D2C           ; back for 11 bits to SER-OUT-L

;   Note the last two bits will have been sent reset as C is exhausted.

        EI                      ; Enable Interrupts.

        LD      A,$01           ; Set RXdata

        LD      C,$EF           ; prepare port address.
        LD      B,$EE           ; prepare value %11101110
        OUT     ($F7),A         ; Send RXdata high.
        OUT     (C),B           ; Send CTS and comms data low - switch off RS232

;; BD-DEL-3
L0D48:  DEC     HL              ; ( 6) The final 26 * BAUD delay
        LD      A,L             ; ( 4) 
        OR      H               ; ( 4) 
        JR      NZ,L0D48        ; (12) back to BD-DEL-3


; -----------------------------------
; THE 'BORDER COLOUR RESTORE' ROUTINE
; -----------------------------------
;

;; BORD-REST
L0D4D:  PUSH    AF              ; Preserve the accumulator value throughout.

        LD      A,($5C48)       ; Fetch System Variable BORDCR
        AND     $38             ; Mask off the paper bits.
        RRCA                    ; Rotate to the range 0 - 7
        RRCA                    ;
        RRCA                    ;
        OUT     ($FE),A         ; Change the border colour.

        POP     AF              ; Restore accumulator and flags.

        RET                     ; Return.


; ----------------------
; THE 'CALL-INP' ROUTINE
; ----------------------
;   If the extended streams e.g. #7 are being used for input then this ROM
;   will be paged in as a result of the $0008 address in the normal INPUT
;   channel position. Since 'INPUT #7' or 'INKEYS #7' could have been used 
;   it is the purpose of this routine to determine which has been used.
;   Note also that 'MOVE #7 TO #2' could also invoke this routine and that MOVE
;   operations are further differentiated in the INKEY$ branch.

;; CALL-INP
L0D5A:  RES     3,(IY+$02)      ; update TV_FLAG - The mode is to be considered 
                                ; unchanged.
                                ; Note. this should have been done by the Main
                                ; ROM before entering the EDITOR.

        PUSH    HL              ; (*) Preserve HL the address of the actual 
                                ; service routine - either NCHAN_IN, MCHAN_IN,
                                ; BCHAN_IN ot T_CHAN_IN.

        LD      HL,($5C3D)      ; Fetch address of Error Stack Pointer ERR_SP

        LD      E,(HL)          ; Extract the address of the error handler
        INC     HL              ; If INPUT is being used this will be
        LD      D,(HL)          ; address $107F in the Main ROM.

        AND     A               ; Prepare to subtract.

        LD      HL,$107F        ; address of ED-ERROR in the Main ROM

        SBC     HL,DE           ; subtract from test value.

        JR      NZ,L0D98        ; forward if not in EDITOR to INKEY$

;   continue to handle INPUT from a stream.

        POP     HL              ; (*) POP service routine to HL e.g. NCHAN_IN

        LD      SP,($5C3D)      ; set Stack Pointer from System Variable ERR_SP
        POP     DE              ; discard the known ED-ERROR address $107F.
        POP     DE              ; POP the next value in hierarchy - MAIN-4
                                ; (usually).
        LD      ($5C3D),DE      ; and set the system variable ERR_SP

;; IN-AGAIN.
L0D78:  PUSH    HL              ; Push the address of the service routine
                                ; e.g. NCHAN_IN on the machine stack.

        LD      DE,L0D7E        ; addr: IN-AG-RET (below)
        PUSH    DE              ; push this address 

        JP      (HL)            ; jump to the service routine either MCHAN_IN,
                                ; NCHAN_IN, BCHAN_IN or TCHAN_IN and then return
                                ; to the next address IN-AG-RET.

; ---

;; IN-AG-RET
L0D7E   JR      C,L0D8A         ; forward with acceptable codes to ACC-CODE

        JR      Z,L0D87         ; forward with time-out to NO-READ

;   Otherwise Iris has closed her channel or the microdrive file was exhausted.

;; OREPORT-8
L0D82:  LD      (IY+$00),$07    ; set ERR_NR to  '8 End of file'
        RST     28H             ; Error Main ROM.

; ---

;; NO-READ
L0D87:  POP     HL              ; Retrieve the address of teh service routine
                                ; and try again as always for INPUT.
        JR      L0D78           ; back to IN-AGAIN.

; ---

;; ACC-CODE
L0D8A:  CP      $0D             ; Is the acceptable code ENTER?
        JR      Z,L0D94         ; forward, if so, to END-INPUT

        RST     10H             ; CALBAS - Call the Base ROM.
        DEFW    $0F85           ; main ADD-CHRX 
                                ; A special entry point within ADD-CHAR to add
                                ; the character to WORKSPACE.

        POP     HL              ; Retrieve the address of the saved service 
                                ; routine.
        JR      L0D78           ; back for another character to IN-AGAIN.

; ---

;; END-INPUT
L0D94:  POP     HL              ; Discard the service routine.
        JP      L0700           ; jump to UNPAGE

; -------------------
; THE 'INKEY$' BRANCH
; -------------------

;; INKEY$
L0D98: