The BASIC command execution routines
THE 'SAVE' COMMAND SYNTAX ROUTINE
This routine deals with the SAVEing of a file. As with all PUPIL "disk" commands, a
command block is send over the network to the master or an assistant station. The
master or assistant than takes care of the SAVEing to disk.
2672 SAVE CALL #03EF,SIGN_SAVE Signal 'SAVEing'.
2675 CALL #04F3,EXPT_PARMS Evaluate and store the parameters.
2678 CALL #08B1,REQ_SERV Request service by a master or
assistant station (if needed).
267B CALL #04E6,TEST_STAT Check if the destination station number
is in range.
267E CALL #39A9,OPEN_N Open the "N" channel.
2681 CALL #068A,SAVE_NET SAVE file and header over the network.
2684 CALL #39DF,SEND_NEOF Send the EOF block.
2687 JP #0165,END Finished.
THE 'SEND HEADER AND FILE' SUBROUTINE
This subroutine sends the file header and the file itself over the network. The End
Of File block isn't send.
268A SAVE_NET LD DE,9 Length of the header.
268D LD HL,#1E10 Address of the header.
2690 CALL #069A,SAVE_NET1 Send the header over the network.
2693 LD DE,(#1E11) Fetch length of file.
2697 LD HL,(#1E13) Fetch address.
269A SAVE_NET1 LD A,D
269B OR E
269C RET Z Return if no more bytes left.
269D LD A,(HL) Fetch a byte.
269E CALL #386D,N_OUTPUT Send it over the network.
26A1 INC HL Point to next byte.
26A2 DEC DE One less.
26A3 JR #269A,SAVE_NET1 Repeat for all bytes.
THE 'LOAD' COMMAND SYNTAX ROUTINE
The 'LOAD' flag is set and the routine continues into the 'LOAD_VERIFY_MERGE'
26A5 LOAD CALL #03EA,SIGN_LOAD Signal 'LOADing'.
26A8 JR #26B2,LD_VF_MR
THE 'VERIFY' COMMAND SYNTAX ROUTINE
The 'VERIFY' flag is set and again the 'LOAD_VERIFY_MERGE' routine handles the rest.
26AA VERIFY CALL #03F9,SIGN_VERIF Signal 'VERIFYing'.
26AD JR #26B2,LD_VF_MR
THE 'MERGE' COMMAND SYNTAX ROUTINE
The 'MERGE' flag is set and 'LOAD_VERIFY_MERGE' continues the syntax checking.
26AF MERGE CALL #03F4,SIGN_MERGE Signal 'MERGEing'.
THE 'LOAD_VERIFY_MERGE' COMMAND ROUTINE
This subroutine checks the syntax of the LOAD, VERIFY and MERGE commands and executes
26B2 LD_VF_MR CALL #04F3,EXPT_PARMS Evaluate and store the parameters.
26B5 CALL #08B1,REQ_SERV Request service by a master or an
assistant station (if needed).
26B8 CALL #04E6,TEST_STAT Check if the destination station number
is in range.
26BB CALL #39A9,OPEN_N Open the "N" channel.
26BE LD B,9 Length of a header.
26C0 LD HL,#1E29 Start of HEADER 2.
26C3 LD_ETC1 CALL #3808,N_INPUT LOAD a byte from the network.
26C6 LD (HL),A Store it into UFIA2.
26C7 INC HL
26C8 DJNZ #26C3,LD_ETC1 Repeat for all header bytes.
26CA LD A,(#1E10) Fetch type of program to be LOADed.
26CD LD B,A
26CE LD A,(#1E29)
26D1 CP B Fetch type of program found.
26D2 JP NZ,#293A,REP_13 Give 'Wrong FILE type' if types are
26D5 CP 3
26D7 JR Z,#26E7,LD_ETC2 Jump if it's a 'CODE' file.
26D9 JP NC,#293A,REP_13 Give 'Wrong FILE type'
if file type >= 4.
26DC CALL #041C,TEST_MERGE
26DF JR NZ,#273D,MERGE_CTRL Jump if 'MERGEing'.
26E1 CALL #0421,TEST_VERIF
26E4 JP Z,#0759,LOAD_CTRL Jump if not 'VERIFYing' (i.e. doing a
26E7 LD_ETC2 CALL #041C,TEST_MERGE LOAD).
Now deal with LOADing of all files with type 3, like 'CODE' and 'SCREEN$', or VERIFYing
of all file types.
26EA JP NZ,#293C,REP_14 Give 'MERGE error' if trying to MERGE a
26ED LD HL,(#1E11) Fetch length of requested file.
26F0 LD DE,(#1E2A) Fetch length of file found.
26F4 LD A,H
26F5 OR L
26F6 JR Z,#2705,LD_ETC3 Jump if length unspecified.
26F8 SBC HL,DE Jump if file to be LOADed is shorter
26FA JR NC,#2705,LD_ETC3 than or of equal length as the
26FC CALL #0412,TEST_LOAD
26FF JP Z,#2938,REP_12 'VERIFY failed' if not LOADing.
2702 JP #293E,REP_15 Otherwise 'CODE error'.
2705 LD_ETC3 LD HL,(#1E13) Fetch startaddress from FILE_ADDR1.
2708 LD A,H
2709 OR L
270A JR NZ,#270F,LD_ETC4 Jump if a startaddress was specified.
270C LD HL,(#1E2C) Otherwise use the startaddress of the
270F LD_ETC4 LD A,(#1E29) But if the file is a BASIC program the
2712 AND A startaddress is held in (PROG).
2713 JR NZ,#2718,LD_ETC5 Jump if not a BASIC file.
2715 LD HL,(23635) Fetch 'start' from (PROG).
2718 LD_ETC5 CALL #07FE,LV_ANY Load or verify the file.
271B LD HL,(#1E17) Fetch execute address.
271E CALL #072A,EXEC_CODE Use it if it was specified.
2721 LD HL,(#1E30) Otherwise use the files execute
2724 CALL #072A,EXEC_CODE address.
2727 JP #0165,END Finished.
THE 'EXECUTE CODE FILE' SUBROUTINE
This routine is supposed to jump to the address in the HL register pair (if it is valid)
but because of a mistake strange things can happen after the CODE file has been
'executed'. The mistake is made at #2737-#273A, now a return is made to 'STACK_BC' in
the 'main' ROM first and than the code file is executed. It had to be the other way
around. (See RAM disassembly from #0F23 onwards.)
272A EXEC_CODE LD A,H
272B OR L
272C RET Z Return if the execute address is zero.
272D LD A,H
272E CP #FF
2730 JR NZ,#2736,EXEC_CODE1
2732 LD A,L Also return when the execute address is
2733 CP #FF #FFFF.
2735 RET Z
2736 EXEC_CODE1 EX (SP),HL Place execute address onto the stack.
2737 LD HL,#2D2B,STACK_BC
273A JP #004F,UNPAGE_HL
Now consider the MERGEing of a program.
273D MERGE_CTRL LD BC,(#1E2A) Fetch the length of the program to be
2741 PUSH BC MERGEd.
2742 INC BC Extra location for the 'end marker'.
2743 RST #10,CALBAS Make the required room in workspace by
2744 DEFW #0030,BC_SPACES calling 'BC_SPACES'.
2746 LD (HL),128 Place the 'end marker'.
2748 EX DE,HL Move start pointer to HL.
2749 POP DE Length to DE.
274A PUSH HL
274B CALL #07FE,LV_ANY Load the file into workspace.
274E POP HL Fetch 'start' of new program.
274F LD DE,(23635) Fetch 'start' of old program (PROG).
2753 RST #10,CALBAS Do the mergeing by calling the 'main'
2754 DEFW #08D2,ME_NEW_LP ROM 'MERGE' routine.
2756 JP #0165,END Finished.
The final part of the routine deals with the LOADing of a program or an array.
2759 LOAD_CTRL LD DE,(#1E2A) Fetch 'new' length.
275D LD HL,(#1E13) Fetch 'old' start (=0 when loading a
2760 PUSH HL
2761 LD A,H
2762 OR L
2763 JR NZ,#276B,LD_CTRL1 Jump if not a 'new' array.
2765 INC DE Increment length by 3, i.e. allows for
2766 INC DE the insertion of the array name and the
2767 INC DE two-byte length.
2768 EX DE,HL Move 'length' to HL.
2769 JR #2774,LD_CTRL2 Jump forward.
The array to be loaded will replace an existing one.
276B LD_CTRL1 LD HL,(#1E11) Fetch 'old' length (i.e. length of
existing program or array) from UFIA1.
276E EX DE,HL Move 'new' length to HL.
276F SCF Jump if the program or array to be
2770 SBC HL,DE loaded isn't longer than the existing
2772 JR C,#277D,LD_CTRL3 one.
2774 LD_CTRL2 LD DE,5 Otherwise a check must be made to
2777 ADD HL,DE ensure that there is sufficient space
2778 LD B,H in memory for the program (or array) to
2779 LD C,L be loaded.
277A RST #10,CALBAS Make the check by calling the 'main'
277B DEFW #1F05,TEST_ROOM ROM 'TEST_ROOM' subroutine.
277D LD_CTRL3 POP HL Restore 'old' start (#0000 when
handling a 'new' array).
277E LD A,(#1E29)
2781 AND A
2782 JR Z,#27B5,LD_PROG Jump if it's a BASIC program.
2784 LD A,H
2785 OR L Jump unless an 'old' array is to be
2786 JR Z,#2793,LD_CTRL4 erased before loading the 'new' one.
2788 DEC HL Points to high byte of 'array length'.
2789 LD B,(HL) Fetch the 'length'.
278A DEC HL
278B LD C,(HL)
278C DEC HL Now point to the 'array name'.
278D INC BC Include 'length' and 'name' in the
278E INC BC array length.
278F INC BC
2790 RST #10,CALBAS Call 'RECLAIM_2' to delete the array.
2791 DEFW #19E8,RECLAIM_2
2793 LD_CTRL4 LD HL,(23641) (E_LINE) points to the end of the
2796 DEC HL variables area+1.
2797 LD BC,(#1E2A) Fetch length of array to be loaded.
279B PUSH BC
279C INC BC Include in the length one byte for the
279D INC BC 'array name' and two bytes for the
279E INC BC 'array length'.
279F LD A,(#1E15) Fetch the array name from 'LENGTH1_2'.
27A2 PUSH AF
27A3 RST #10,CALBAS Call 'MAKE_ROOM' to create the space
27A4 DEFW #1655,MAKE_ROOM for the array.
27A6 INC HL Point to first 'new' location inserted.
27A7 POP AF
27A8 LD (HL),A Store array name into first location.
27A9 POP DE
27AA INC HL Store array length into the following
27AB LD (HL),E two locations.
27AC INC HL
27AD LD (HL),D
27AE INC HL
27AF CALL #07FE,LV_ANY Load the file.
27B2 JP #0165,END Finished.
Now deal with the LOADing of a BASIC program and its variables.
27B5 LD_PROG LD DE,(23635) Fetch start of existing program (PROG).
27B9 LD HL,(23641) Fetch end of existing program, i.e.
27BC DEC HL (E_LINE)-1.
27BD RST #10,CALBAS Delete the program by calling
27BE DEFW #19E5,RECLAIM_1 'RECLAIM_1' in the 'main' ROM.
27C0 LD BC,(#1E2A) Fetch length of program and variables.
27C4 LD HL,(23635) Fetch (PROG), start of BASIC program.
27C7 RST #10,CALBAS Create the required space by calling
27C8 DEFW #1655,MAKE_ROOM 'MAKE_ROOM'.
27CA INC HL Point to the first location.
27CB LD BC,(#1E2E) Fetch length without variables.
27CF ADD HL,BC Calculate and store the start of the
27D0 LD (23627),HL variables area (VARS).
27D3 LD A,(#1E31) When no autostart line is given, this
27D6 LD H,A ('AUTOSTART2-hi') holds #FF.
27D7 AND #C0
27D9 JR NZ,#27E6,LD_PROG1 Jump with no autostart line.
27DB LD A,(#1E30) Otherwise store it into 'NEWPPC' and
27DE LD L,A clear 'NSPPC'.
27DF LD (23618),HL These hold the line and the statement
27E2 LD (IY+10),0 to be executed respectively.
27E6 LD_PROG1 LD HL,(23635) Fetch the start of the BASIC program.
27E9 LD DE,(#1E2A) Fetch the length.
27ED DEC HL Reset the DATA pointer 'DATADD' to the
27EE LD (23639),HL beginning of the program.
27F1 INC HL Balance the 'DEC HL'.
27F2 CALL #07FE,LV_ANY Load the file.
27F5 JP #0165,END Finished.
THE 'LOAD OR VERIFY' SUBROUTINE
This subroutine is used to LOAD or VERIFY (signalled by FLAGS3) a block of bytes. It
must be entered with HL and DE holding 'start' and 'length'.
27F8 LV_VERIFY CP (HL) The actual VERIFY, i.e. compare the
fetched byte with that held in memory.
27F9 JP NZ,#2938,REP_12 Give 'VERIFY failed' if they don't
27FC LV_NEXT INC HL Next memory address.
27FD DEC DE One byte less to go.
27FE LV_ANY LD A,D
27FF OR E
2800 RET Z Exit if no more bytes left.
2801 CALL #3808,N_INPUT Load one byte from the network.
2804 CALL #0421,TEST_VERIF
2807 JR NZ,#27F8,LV_VERIFY Jump if VERIFYing.
2809 LD (HL),A Otherwise store the byte.
280A JR #27FC,LV_NEXT Repeat for all bytes in the file.
THE 'FORMAT' COMMAND SYNTAX ROUTINE
This routine tests if the command has the appropriate syntax and executes it during
280C FORMAT RST #28,NEXT_C_ROM Advance CH_ADD to next character.
280D AND #DF Only capitals.
280F CP "N" Give 'Nonsense in GNOS' if device isn't
2811 JP NZ,#2922,REP_1 equal to "N".
2814 CALL #0465,EXPT_DEVN Evaluate the station number.
2817 CALL #0155,ST_END_ROM Confirm end of statement and exit
during syntax checking.
281A CALL #04E6,TEST_STAT Check the station number.
281D LD A,(#1E01)
2820 AND A Give 'Invalid STATION' error if station
2821 JP Z,#2932,REP_9 number is 0.
2824 CP 10 Give the error also if station number
2826 JP C,#2932,REP_9 in the range 1..9.
2829 LD (#029C),A Store the station number.
282C LD A,(#1DE4)
282F CP #4E Finished if DISCiPLE was a PUPIL
2831 JP Z,#0165,END already.
2834 LD A,#4E
2836 LD (#1DE4),A Otherwise signal 'PUPIL mode'.
2839 JP #2940,REP_16 And report 'PUPIL set'.
THE 'CAT' COMMAND SYNTAX ROUTINE
This routine handles the syntax checking and the execution of the 'CAT' command.
283C CAT LD HL,#1E06 "*" is the default name of the files
283F LD (HL),"*" being CATted.
2841 CALL #0465,EXPT_DEVN Evaluate drive number.
2844 CALL #0426,SEPARATOR Evaluate the filename if there is a
2847 CALL Z,#04C1,EXP_F_NAME separator.
284A CP "!" If an "!" is present it is thrown away.
284C JR NZ,#284F,CAT1
284E RST #28,NEXT_C_ROM Ignore "!".
284F CAT1 CALL #0155,ST_END_ROM Confirm end of statement and exit if
2852 CALL #08B1,REQ_SERV Request service by a master or an
2855 RST #10,CALBAS Clear the screen.
2856 DEFW #0DAF,CL_ALL
2858 CALL #39A9,OPEN_N Open the "N" channel.
285B CAT2 CALL #3819,NCHAN_IN Read a byte from the network.
285E JR C,#2868,CAT3 Jump if acceptable byte.
2860 JR Z,#285B,CAT2 Try again if no byte has been read.
2862 CALL #39DF,SEND_NEOF ? Why send EOF block, it's a read
2865 JP #0165,END Finished.
2868 CAT3 RST #10,CALBAS Print the received character on the
2869 DEFW #0010,PRINT_A_1 current stream.
286B JR #285B,CAT2
THE 'ERASE' COMMAND SYNTAX ROUTINE
The ERASE command can be given by a PUPIL but the 'NET_SERVER' routine in the system
file ignores it completely.
286D ERASE RST #28,NEXT_C_ROM Advance CH_ADD.
286E LD (#1E04),A Store the device descriptor.
2871 CP """ Test for Microdrive syntax if it was a
2873 CALL Z,#0445,MD_SYNTAX1 quote.
2876 CALL #0465,EXPT_DEVN Evaluate the drive number.
2879 CALL #0426,SEPARATOR A filename must be specified, give
287C JP NZ,#2922,REP_1 'Nonsense in GNOS' if no separator
287F CALL #04C1,EXP_F_NAME Evaluate filename.
2882 CALL #0155,ST_END_ROM Confirm end of statement and exit
during syntax checking.
2885 LD A,(#1E04) Fetch device descriptor.
2888 AND #DF Drop lower case bit.
288A CP "D"
288C JR Z,#2893,ERASE1 Jump if it's "D".
288E CP "M" Give 'Invalid DEVICE' error if it isn't
2890 JP NZ,#2934,REP_10 "M".
2893 ERASE1 CALL #08B1,REQ_SERV Request service by a master or
2896 JP #0165,END assistant. Finished.
THE 'HOOKCODES NOT IMPLEMENTED' ROUTINE
A PUPIL system doesn't support hook and command codes so give an error.
2899 REPORT_17 JP #2942,REP_17 Give 'Invalid CODE'.
THE 'COPY NOT IMPLEMENTED' ROUTINE
Making screendumps on the network printer isn't allowed.
289C COPY JP #2942,REP_17 Give 'Invalid CODE'.
THE '"P" CHANNEL OUTPUT' ROUTINE
This routine handles the PUPIL's "P" channel, the only thing it has to do is sending
a PRINT command block to the master.
289F PCHAN_OUT PUSH AF
28A0 LD A,1 Destination station is the master
28A2 LD (#1DFD),A station.
28A5 LD A,245 This is the 'PRINT' code.
28A7 LD (#1DFF),A
28AA POP AF
28AB LD (#1E00),A Store byte to be printed in command block.
28AE JP #08D2,REQ_SERV3 Send the command block and exit.
THE 'REQUEST SERVICE' SUBROUTINE
This routine handles the sending of a command block to the master or one of its
assistant stations. The station to which it is sended is determined by the drive
number. E.g. the 'CAT' command; when CAT n is given with n between 0 and 9 the command
block is send to the master station. Lies n within the range 20..29 then the command
block is send to station 2. So to select a certain destination station (within the
range 1..9), add it's station number times 10 to the drive number. (The master station
is selected when the range 0..19 is used.)
28B1 REQ_SERV CALL #0403,TEST_SERV Exit when serving the network (master
28B4 RET NZ has given a F command).
28B5 CALL #040D,TEST_NET Exit when using the network in the
28B8 RET NZ 'normal' way (with a N command).
28B9 LD A,(#1E01) Otherwise fetch drive number.
28BC LD B,1 B holds destination station number.
28BE SUB 10 Use master station if drive number is
28B0 JR C,#28C9,REQ_SERV2 in the range 0..9.
28C2 REQ_SERV1 SUB 10 Now calculate destination station.
28C4 JR C,#28C9,REQ_SERV2 1=0..19, 2=20..29, . . , 9=90..99.
28C6 INC B
28C7 JR #28C2,REQ_SERV1
28C9 REQ_SERV2 ADD A,10 Balance last 'SUB 10'.
28CB LD (#1E01),A Store real drive number.
28CE LD A,B Store destination station number.
28CF LD (#1DFD),A
28D2 REQ_SERV3 LD A,(#029C) Fetch own station number from NSTAT.
28D5 LD (#1DFE),A Store it also.
28D8 LD A,3 Default stream.
28DA LD (#1E03),A
Now the command block checksum is calculated. Then the block and its checksum are send
over the network. #28DD is also the entry point for the send command block routine of
28DD REQ_SERV4 LD HL,#1DFD Point to the data buffer.
28E0 LD B,28 Calculate checksum for 28 bytes.
28E2 XOR A Clear checksum.
28E3 REQ_SERV5 ADD A,(HL) Add this byte.
28E4 INC HL
28E5 DJNZ #28E3,REQ_SERV5 Repeat for all bytes.
28E7 LD (HL),A Store the checksum in command block.
28E8 REQ_SERV6 CALL #39ED,NET_STATE Wait until the network is resting.
28EB LD HL,1000 Make the network active for about 57000
28EE LD A,(#1DDA) T cycles.
28F1 OR #80
28F3 OUT (31),A
28F5 REQ_SERV7 DEC HL
28F6 LD A,H
28F7 OR L
28F8 JR NZ,#28F5,REQ_SERV7
28FA LD A,(#1DDA) Make the network inactive.
28FD OUT (31),A
28FF LD B,10 Wait for 125 T cycles.
2901 REQ_SERV8 DJNZ #2901,REQ_SERV8
2903 LD HL,#1DFD Start of command block.
2906 LD E,29 Length.
2908 CALL #3ABC,OUTPAK Send command block.
290B LD HL,#1DF4 Address to store network response code.
290E LD (HL),0
2910 LD E,1 A single byte is to be received.
2912 CALL #3A87,INPAK Get response byte.
2915 JR NZ,#28E8,REQ_SERV6 Send the command block until a response
2917 LD A,(#1DF4)
291A CP 1 The response byte must be '1'.
291C JR NZ,#28E8,REQ_SERV6 Resend the command block until a valid
response byte is received.
291E RET Finished.
291F DEFB #00 An unused location.