The ROM control routine
This is the entry point for all 'new' BASIC commands and the channels supported by the
'pupil' system. This routine is executed in RAM (the first KEY_SCAN after a reset jumps
to the appropriate routine, which copies the first 2335 ROM bytes to RAM).
2086 ROM_START2 LD (#1DD6),HL DISCiPLE's CH_ADD (D_CH_ADD).
2089 LD (#1DEA),A
208C LD A,(#1DE5) Get CALBAS indicator.
208F CP #47
2091 JR NZ,#20A0,ROM_START3 Jump if not executing a CALBAS.
The error occurred during CALBAS, so go to Spectrum error routine.
2093 XOR A
2094 LD (#1DE5),A Clear the CALBAS flag.
2097 LD (#1ACF),A Clear FLAGS3.
209A LD HL,#0054 Address in the Spectrum error routine.
209D EX (SP),HL Put new return address on the stack.
209E JR #2050,UNPAGE_1 Page out DISCiPLE and then return.
20A0 ROM_START3 POP HL Get RETurn address (usually points to
20A1 PUSH HL the error code).
20A2 PUSH DE
Now see if a DISCiPLE's channel has been requested.
20A3 AND A
20A4 LD DE,#15FE If a channel has been requested this is
the RETurn address stored by the CALL
#162C in the 'CALL_SUB' subroutine in
the 'main' ROM.
20A7 SBC HL,DE Compare the addresses.
20A9 POP DE
20AA JR NZ,#20CA,ROM_START4 No channels requested, so jump.
Now see if the channel requested is the "P" channel. The DISCiPLE's "P" channel has to
be handled seperately from "D" channels because it doesn't hold information about the
DISCiPLE systems in/out addresses.
20AC LD HL,#0050 This makes UNPAGE_1 the return address.
20AF PUSH HL
20B0 PUSH BC
20B1 LD HL,(23631) Fetch CHANS.
20B4 LD BC,16 Point to the "P" channel.
20B7 ADD HL,BC
20B8 SBC HL,DE Compare "P" address with used address.
20BA POP BC
20BB LD A,(#1DEA) Restore A.
20BE JP Z,#089F,PCHAN_OUT Jump if DISCiPLE "P" channel was used.
20C1 LD HL,4 DE holds address of routine pointer-4.
20C4 ADD HL,DE HL now points to the routine pointer.
20C5 LD E,(HL) Fetch routine address.
20C6 INC HL
20C7 LD D,(HL)
20C8 EX DE,HL HL now points to the routine.
20C9 JP (HL) Jump to the appropriate 'input' or
'output' routine.
At this point the DISCiPLE has been paged-in by an error in the 'main' ROM (not during
a CALBAS).
20CA ROM_START4 POP HL Fetch address of error code.
20CB RST #10,CALBAS CALBAS in CH_ADD+1, this gets the byte
20CC DEFW #007B pointed by HL, i.e. the errorcode.
20CE LD (IY+0),A Store it in ERR_NR.
20D1 CP #FF Is the error 'OK'?
20D3 JR Z,#20EB,TEST_INPUT Jump if so.
20D5 SUB 27 Adjust the range, error codes now below 0.
20D7 JP NC,#0899,REPORT_17 Give 'Invalid CODE' error. Hook- and
command codes are not supported.
Now the reduced error code is tested for the values wich might indicate DISCiPLE BASIC
commands.
20DA CP 240 Jump if the error is
20DC JR Z,#20EB,TEST_INPUT 'Nonsense in BASIC'.
20DE CP 243
20E0 JR Z,#20EB,TEST_INPUT Also if it is 'Invalid file name'.
20E2 CP 252
20E4 JR Z,#20EB,TEST_INPUT Or 'Invalid stream'.
20E6 CP 230
20E8 JP NZ,#0146,SPEC_ERR Exit if not 'Variable not found'.
Now follows the infamous 'Backstepping' routine, from the address where the BASIC
interpreter failed a backward search is made for a character code larger or equal to
206, i.e. a keyword. There are many ways this algorithm can fail, e.g.:
-A number in a BASIC line is followed by a CHR$ 14 and the binary representation
of the number, this could contain a byte >= 206.
-If there is no keyword on the line, searching continous within the line length,
line number and then on to previous line(s).
20EB TEST_INPUT BIT 5,(IY+55) Test FLAG_X.
20EF JP NZ,#0146,SPEC_ERR Exit if in input mode.
20F2 LD HL,(23645) Get address reached by interpreter
20F5 FIND_COM DEC HL (CH_ADD).
20F6 LD A,(HL)
20F7 CP 206 See if character is a keyword (>=206,
i.e. DEF FN, the first BASIC command).
20F9 JR C,#20F5,FIND_COM If not, repeat 'Backstepping.'
20FB LD (23645),HL Update CH_ADD.
20FE RST #30,SYNTAX_Z
20FF JR NZ,#212E,RUNTIME Jump during runtime.
2101 DEC HL Compensate for increase at #2104.
2102 LD C,0 ???? C isn't used.
Now the routine removes numbers from the current BASIC line.
2104 RECLM_NUM INC HL
2105 LD A,(HL) Next character.
2106 CP 14
2108 JR NZ,#2129,NO_NUM Jump if it's not a 'number' marker.
210A PUSH BC
210B PUSH HL
210C LD BC,6 Reclaim the six bytes forming a number
210F RST #10,CALBAS with it's marker.
2110 DEFW #19E8,RECLAIM_2
2112 POP HL Retrieve address in line.
2113 PUSH HL But keep it on the stack also.
2114 LD DE,(#1DD6) Address reached by interpreter.
2118 AND A Jump if the reclaimed bytes were after
2119 SBC HL,DE the character pointed to by D_CH_ADD.
211B JR NC,#2127,NEXT_1
211D EX DE,HL Otherwise D_CH_ADD has to be updated.
211E LD BC,6
2121 AND A The character pointed by D_CH_ADD has
2122 SBC HL,BC been moved '6' bytes down.
2124 LD (#1DD6),HL Update D_CH_ADD.
2127 NEXT_1 POP HL
2128 POP BC
2129 NO_NUM LD A,(HL)
212A CP 13
212C JR NZ,#2104,RECLM_NUM Repeat until 'end of line' is found.
Now clear the BASIC workspace and test if the Spectrum is a pupil in a network.
212E RUNTIME RST #10,CALBAS CALL the Spectrum ROM routine SET_WORK
212F DEFW #16BF,SET_WORK to clear the workspace.
2131 LD A,(#1DE4)
2134 CP #78
2136 JP Z,#0315,PUPIL Jump if this is a PUPIL station.
If not a pupil and because the DISCiPLE isn't booted the only valid commands are FORMAT
(for network) and RUN (to boot).
2139 CALL #002C,GET_C_ROM Get next character from line.
213C CP 208
213E JP Z,#080C,NET_FORMAT Jump with 'FORMAT' command.
2141 CP 247
2143 JP Z,#01BC,RUN Also jump with 'RUN'.
THE 'SPECTRUM ERROR' ROUTINE
This routine must be entered with the error code in (ERR_NR), and does the same as the
'main' ROM 'ERROR' restart.
2146 SPEC_ERR LD HL,(#1DD6) Get D_CH_ADD.
2149 LD (23645),HL Store it in CH_ADD and X_PTR.
214C LD (23647),HL
214F LD HL,#0058 Address in Spectrum error routine.
2152 JP #004F,UNPAGE_HL Jump to Spectrum error routine.