; 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: