The BASIC command execution routines I
THE 'COPY FILE(S)' ROUTINE
This routine handles the copying of files. It is executed as soon as the 'EXPT_PARMS'
routine at #AEF finds a 'TO' keyword. The return address to the routine which called
'EXPT_PARMS' is dropped at #0708.
0702 TO CALL #0A0F,TEST_SAVE
0705 JP Z,#2920,REP_0 Give error if not SAVEing.
0708 POP HL Drop return address to SAVE routine.
0709 CALL #0AA2,SWAP_UFIAS Swap the UFIAS.
070C RST #28,NEXT_C_RAM
070D AND #DF Drop lower case bit.
070F CP "D"
0711 JP NZ,#2920,REP_0 Jump if 2nd device isn't "D".
0714 LD (#1E04),A Store it in DEV_TYPE1.
0717 CALL #0A5E,EXPT_DEVN Evaluate drive number, store it in UFIA1.
071A CALL #0A1E,SEPARATOR Test for a separator, jump if one
071D JR Z,#0722,TO_1 found, i.e. a 2nd name is given.
071F CALL #09E2,SIGN_LOAD Used here to signal 'use source filename
for destination file'.
0722 TO_1 CALL Z,#0ABC,EXP_F_NAME Evaluate filename if there was a
separator.
0725 CALL #0AA2,SWAP_UFIAS Swap the UFIAS again.
0728 CALL #0409,ST_END_RAM Confirm end of statement and exit
during syntax checking.
072B LD HL,#1E1E Copy the second filename and directory
072E LD DE,#1E32 description.
0731 LD BC,11
0734 LDIR
0736 LD HL,#0001 Track 0 sector 1.
0739 LD (#1DED),HL
073C LD HL,#0000 Disk buffer offset #0000.
073F LD (#1DEB),HL
0742 TO_2 CALL #2984,JTEST_DRV Is the drive defined?
0745 CALL #07E6,TO_SEARCH Search for a file to be copied.
0748 JP NZ,#07B9,TO_EXIT Jump if there are no files left.
074B CALL #299F,JLOAD_1ST Copy file description (directory
description and filename) to UFIA2 and
load the first sector of the file into
the disk buffer.
074E LD A,(#1E1E) Get directory description.
0751 CP 5
0753 JR Z,#0742,TO_2 Jump with 'Snapshot 48K'.
0755 CP 6
0757 JR Z,#0742,TO_2 Jump with 'Microdrive file'.
0759 CP 9
075B JR Z,#0742,TO_2 Jump with 'Snapshot 128K'.
075D CP 10
075F JR Z,#0742,TO_2 Jump with 'Opentype file'.
0761 CP 11
0763 JR Z,#0742,TO_2 Jump with 'Execute file'.
These five file types can't be copied
with the 'SAVE .. TO ..' command.
Now the file is going to be copied.
NOTE: The file to be copied will destroy everything above 'start of BASIC'+256 and
no checks are made if the file fits in memory and if the stack isn't overwritten.
0765 CALL #0DE1,LOAD_HEAD2 Copy the file header (the 9 bytes
consisting of filetype, length, etc.)
to UFIA2.
0768 LD HL,(23635) Fetch start of BASIC program (PROG).
076B INC H Add 256 to it.
076C LD DE,(#1E2A) Fetch length of file (LENGTH2_1).
0770 CALL #29A5,JLOAD_FILE Load DE bytes, starting at address HL.
0773 CALL #07C5,TO_MSG Print the message "CHANGE disc ...." if
source drive is destination drive.
0776 CALL #0AA2,SWAP_UFIAS Swap the UFIA's again. The header of
the loaded file is now held in UFIA1.
0779 CALL #0A0A,TEST_LOAD Used here to test whether a 2nd
077C JR NZ,#0794,TO_5 filename was given. Jump if not.
077E LD HL,#1E33 Here the 2nd filename was stored.
0781 LD DE,#1E06 Start of filename of loaded file.
0784 LD B,10 Filename length.
Now the characters from the filename of the loaded file are replaced by the characters
of the 2nd filename. Except when the wildcard characters '*' and '?' were used in the
2nd name. With '*' all next characters are left unchanged, with '?' the current
character isn't changed.
0786 TO_3 LD A,(HL)
0787 CP "*" With a '*' don't replace the remaining
0789 JR Z,#0794,TO_5 characters.
078B CP "?" With a '?' in name 2 don't replace this
078D JR Z,#0790,TO_4 character.
078F LD (DE),A Store this character.
0790 TO_4 INC HL
0791 INC DE
0792 DJNZ #0786,TO_3 Repeat for all 'normal' characters.
0794 TO_5 CALL #2984,JTEST_DRV
0797 CALL #29A8,JOFSM_2 Open the file for SAVEing.
079A JR NZ,#07AD,TO_6 Jump if file existed already and the
user didn't want to overwrite it.
079C CALL #0D2F,SAVE_HEAD1 SAVE the 9 header bytes to the file.
079F LD HL,(23635) Fetch start of BASIC (PROG), and add
07A2 INC H 256 to it. (here the file was loaded)
07A3 LD DE,(#1E11) Length of file.
07A7 CALL #29C9,JHSVBK_2 Save the file.
07AA CALL #2981,JCFSM Close the file.
07AD TO_6 CALL #0AA2,SWAP_UFIAS Swap the UFIA's again.
07B0 CALL #09CE,SIGN_1HAND Signal 'at least one file has been
copied'
07B3 CALL #07C5,TO_MSG Print message "CHANGE ..." if necessary.
07B6 JP #0742,TO_2 Repeat until no more files have to be
copied.
07B9 TO_EXIT CALL #09F6,TEST_1HAND Give error if there isn't one file
07BC JP Z,#2954,REP_26 copied.
07BF LD HL,#11B7 Otherwise jump to the appropriate 'NEW'
07C2 JP #160D,TO_NEW routine (128K or 48K).
THE 'PRINT "CHANGE DISC"' SUBROUTINE
This subroutine tests whether source and destination drives are equal. If they are
the message "CHANGE disc ..press SPACE" is printed.
07C5 TO_MSG LD A,(#1E01) Fetch source drive.
07C8 LD B,A
07C9 LD A,(#1E1A) Fetch destination drive.
07CC CP B
07CD RET NZ Return if they aren't equal.
07CE RST #10,CALBAS Otherwise clear lower screen area.
07CF DEFW #0D6E,CLS_LOWER
07D1 SET 5,(IY+2) Signal 'lower screen has to be cleared'.
07D5 CALL #19E3,MSG_4 Print "CHANGE disc ..." message.
07D8 CALL #297E,JDISC_BEEP Give a beep.
07DB TO_SPC_KEY LD A,#7F Keyboard row B-SPACE address.
07DD IN A,(254)
07DF RRA
07E0 JR C,#07DB,TO_SPC_KEY Jump unless the SPACE key is pressed.
07E2 RST #10,CALBAS Clear lower screen.
07E3 DEFW #0D6E,CLS_LOWER
07E5 RET Finished.
THE 'SEARCH FILES' SUBROUTINE
This subroutine searches for files which have to be copied. It returns with the Zero
flag set if the current file is to be copied, if the complete directory is searched
the routine returns with Zero reset.
07E6 TO_SEARCH LD DE,(#1DED) Track & sector to DE.
07EA LD A,D
07EB CP 4 Jump if not reached track 4, i.e.
07ED JR NZ,#07F2,TO_SEARCH1 directory hasn't been read completely.
07EF CP 0 Reset Zero flag.
07F1 RET
The directory isn't finished yet, so read sector and test the file(s).
07F2 TO_SEARCH1 CALL #29BD,JRSAD Read sector E from track D.
07F5 TO_SEARCH2 CALL #082D,TO_COPY Check if this file is to be copied.
07F8 PUSH AF Store result (Zero flag).
07F9 LD HL,(#1DEB) Disk buffer offset to HL.
07FC LD A,H
07FD CP 1
07FF JR Z,#0812,TO_NXT_SEC Jump if second entry.
0801 LD A,(#1DDA) Fetch current control port status.
0804 AND #04
0806 JR NZ,#0812,TO_NXT_SEC Jump with single density.
0808 LD HL,256 Otherwise offset is for second entry.
080B LD (#1DEB),HL
080E POP AF Restore Zero flag.
080F RET Z Return if this file is to be copied.
0810 JR #07F5,TO_SEARCH2 Otherwise next file.
The file entries of the current sector have been tested so point to the next sector.
0812 TO_NXT_SEC LD HL,0 Offset is for first entry.
0815 LD DE,(#1DED) Fetch track and sector.
0819 INC E Next sector.
081A LD A,E
081B CP 11
081D JR NZ,#0822,TO_NXT1 Jump if not last sector on this track.
081F LD E,1 Start with sector 1.
0821 INC D Next track.
0822 TO_NXT1 LD (#1DED),DE Store track & sector.
0826 LD (#1DEB),HL Store disk buffer offset.
0829 POP AF Restore Zero flag.
082A RET Z Return if previous file is to be
082B JR #07E6,TO_SEARCH copied. Otherwise jump.
THE 'COPY THIS FILE ?' SUBROUTINE
This subroutine checks if the 'current' filename is to be copied. The routine returns
with the Zero flag set to signal yes and RPT pointing to the directory description of
the file to be copied.
082D TO_COPY LD HL,#1BD6 Point to start of sector.
0830 LD DE,(#1DEB) Offset to DE.
0834 LD (IX+14),D Update RPT (RAM PoinTer (?)).
0837 ADD HL,DE Update HL.
0838 LD A,(HL) Fetch directory description.
0839 AND A
083A JR NZ,#083E,TO_FILE Jump if the file isn't ERASEd.
083C INC A Reset Zero flag to signal 'do not copy
083D RET this file' and exit.
083E TO_FILE INC HL Step past directory descriptor.
083F LD DE,#1E06 DE now points to FILE_NAME1.
0842 LD B,10 A filename is 10 characters long.
0844 TO_COPY_L LD A,(DE) Fetch character.
0845 CP "*" If it was a '*' all other characters
0847 RET Z don't matter. Signal 'copy this one'.
0848 CP "?" If it was a '?' this character doesn't
084A JR Z,#0850,TO_COPY1 matter.
084C XOR (HL)
084D AND #DF Upper and lower case? don't bother.
084F RET NZ Exit if characters are unequal.
0850 TO_COPY1 INC DE Check next character.
0851 INC HL
0852 DJNZ #0844,TO_COPY_L
0854 RET Finished.
THE 'CAT' COMMAND SYNTAX ROUTINE
This routine checks that the command is in the form CAT <#s;>d<<;>n$><!>.
0855 CAT LD IX,#1AC3 Point to the DISCiPLE workspace.
0859 CALL #09FB,TEST_SERV Check if a 'pupil' requested a CAT.
085C JP NZ,#089F,DO_CAT Jump if serving a 'pupil'.
085F LD HL,#1E06 "*" is the default name of the files
0862 LD (HL),#2A being CATted.
0864 LD HL,#1E03 Just like #2 is the default output
0867 LD (HL),#02 stream.
0869 RST #28,NEXT_C_RAM Get next character.
086A CP 13 Give an error if an 'end of line' (CR)
086C JP Z,#2924,REP_2 is found right after "CAT".
086F CP ":"
0871 JP Z,#2924,REP_2 Same error for ":".
0874 CP "#" Jump if no stream specified, use
0876 JR NZ,#0881,CAT_DRV default stream #2.
0878 CALL #109D,EXPT_#_NR Evaluate stream number.
087B CALL #0A1E,SEPARATOR Check if there is a separator.
087E JP NZ,#2920,REP_0 Give an error if no separator found.
0881 CAT_DRV CALL #0A76,EXPT_DEVN2 Evaluate drive number.
0884 CALL #0A1E,SEPARATOR Evaluate filename if there is a
0887 CALL Z,#0ABC,EXP_F_NAME separator.
088A CP "!" If there is no "!" then an extended
088C JR NZ,#0899,EXT_CAT catalogue is given.
088E RST #28,NEXT_C_RAM Next character.
088F CALL #0409,ST_END_RAM Confirm end of statement and exit when
syntax checking.
0892 CALL #2984,JTEST_DRV See if drive is defined.
0895 LD A,#02 Signal 'small' CAT.
0897 JR #08A4,DO_CAT1
0899 EXT_CAT CALL #0409,ST_END_RAM Confirm end of statement and exit
during syntax time.
089C RST #10,CALBAS Clear the screen by calling 'main' ROM
089D DEFW #0DAF,CL_ALL routine.
089F DO_CAT CALL #2984,JTEST_DRV See if drive is defined.
08A2 LD A,#04 Signal extended CAT.
08A4 DO_CAT1 CALL #08B5,CAT_RUN Give the CAT.
08A7 JP #0419,END Finished.
THE 'CAT' COMMAND ROUTINE
This routine makes a catalogue of the disk inserted in the specified drive, by
calling the DISCiPLE ROM routine 'SCAN_CAT'. It has two entry points: #08AA for the
command code 67, and #08B5 for the BASIC 'CAT' command. The first entry point was
somewhat changed in 'Sys 3d' to make the command code work.
08AA PCAT CALL #2984,JTEST_DRV Drive defined?
08AD LD A,(#1E10) Get 'CAT' type.
08B0 NOP
08B1 NOP
08B2 NOP
08B3 NOP
08B4 NOP
08B5 CAT_RUN PUSH AF
08B6 CALL #09FB,TEST_SERV Serving the network?
08B9 CALL NZ,#0924,OPEN_N_CH Open the "N" channel if so.
08BC LD A,(#1E03)
08BF RST #10,CALBAS Open the desired stream by calling
08C0 DEFW #1601,CHAN_OPEN 'CHAN_OPEN' in the 'main' ROM.
08C2 LD A,13
08C4 CALL #29AE,JPRT_A Printing starts on the next line.
08C7 CALL #1979,MSG_0 Print the 1st part of "DIR"-message.
08CA LD A,(#1ACE) Fetch current drive, 0=2, 1=1.
08CD AND #01 Only bit0.
08CF XOR 49 Make ASCII "1" or "2".
08D1 INC A
08D2 CALL #29AE,JPRT_A Print drive number.
08D5 CALL #198F,MSG_1 Print the 2nd part of "DIR"-message.
08D8 LD HL,#0000 Reset 'total number of sectors'
08DB LD (#1DD8),HL occupied.
08DE POP AF Restore 'CAT' type.
08DF CALL #2993,JSCAN_CAT Print the CAT entries.
08E2 CALL #19A0,MSG_2 Print "Free ..." message.
08E5 CALL #29CC,JDRV_CAP Get drive capacity in A register.
The 'Sys 3b' system couldn't cope with non 40, 80 tracks drives (both single and double
sided), the amount of free space was calculated as if it was an 80 tracks double sided
drive. In 'Sys 3c' this was cured.
08E8 PUSH BC
08E9 BIT 7,A
08EB JR Z,#08EE,CAT_RUN1 Jump if drive is single sided.
08ED ADD A,A Otherwise double the number of tracks and
get rid of the side bit.
08EE CAT_RUN1 SUB 4 Subtract number of catalogue tracks.
08F0 LD HL,0
08F3 LD B,10 Each track has 10 sectors.
08F5 LD D,0 Number of tracks to DE.
08F7 LD E,A
08F8 NO_SECTORS ADD HL,DE Calculate total number of sectors.
08F9 DJNZ #08F8,NO_SECTORS
08FB POP BC
08FC NOP New code is two bytes shorter.
08FD NOP
08FE LD DE,(#1DD8) Get number of used sectors.
0902 XOR A Clear carry.
0903 SBC HL,DE Calculate number of free sectors.
0905 SRL H Divide it by two to get number of free
0907 RR L K-bytes.
0909 LD A,(#1DDA) Fetch current control port status.
090C AND #04
090E JR Z,#0914,CAT_RUN2 Jump with double density drive.
0910 SRL H Otherwise divide by two, SD sectors
contain 256 bytes.
0912 RR L
0914 CAT_RUN2 XOR A
0915 CALL #29B1,JPRT_NUM Print the number.
0918 LD A,13
091A CALL #29AE,JPRT_A Print a newline.
091D CALL #09FB,TEST_SERV
0920 RET Z Return if not serving.
0921 JP #2975,JSEND_NEOF Otherwise send the EOF block over the
network.
THE 'OPEN A NETWORK CHANNEL' ROUTINE
This subroutine is used to send the data, requested by a pupil, over the network.
0924 OPEN_N_CH PUSH IX
0926 LD A,(#1DFE) Fetch pupil's station number.
0929 LD (#1E01),A
092C CALL #2960,JOPEN_N Open the "n" channel.
092F POP IX
0931 RET
THE 'ERASE' COMMAND SYNTAX ROUTINE
This routine checks that the command is in the form ERASE *n$ to erase a file or
ERASE *n1$ TO n2$ to rename a file. The '*' stands for DISCiPLE syntax ('d'd<;>) or
Microdrive syntax ('"m"';d;).
NOTE: The routine starts with testing if it was a pupil requested ERASE command, the
'NET_SERVER' routine (at #0369) however doesn't allow pupils ERASEing files.
0932 ERASE CALL #09FB,TEST_SERV
0935 JP NZ,#0954,ERASE1 Jump if serving.
0938 RST #28,NEXT_C_RAM Get next character.
0939 LD (#1E04),A Store the device descriptor.
093C CP """ Test for Microdrive syntax if it was a
093E CALL Z,#0A3E,MD_SYNTAX1 quote.
0941 CALL #0A5E,EXPT_DEVN Evaluate the drive number.
0944 CALL #0A1E,SEPARATOR Test for a separator.
0947 JP NZ,#2920,REP_0 Give error if none found.
094A CALL #0ABC,EXPT_F_NAME Evaluate filename.
094D CP 204 Is the filename followed by "TO"?
094F JR Z,#098D,RENAME Jump if so, rename is wanted.
0951 CALL #0409,ST_END_RAM Confirm end of statement and exit
during syntax checking.
0954 ERASE1 LD A,(#1E04) Fetch device descriptor.
0957 AND #DF Drop lower case bit.
0959 CP "D"
095B JR Z,#0962,ERASE_RUN Jump if it was "D".
095D CP "M"
095F JP NZ,#2934,REP_10 Give error if it wasn't "M".
THE 'ERASE A FILE' ROUTINE
This routine deletes the specified file(s) on the specified drive. First it calls the
routine 'FIND_FILE' to find a matching name, then it marks the file ERASEd by setting
the directory description to 0, the dir. entry is then SAVEd back to disc.
0962 ERASE_RUN CALL #2984,JTEST_DRV See if drive is defined.
0965 ERASE_LOOP CALL #0985,FIND_FILE Find the file.
0968 JR NZ,#0974,NOT_FOUND Jump if not found.
096A LD (HL),0 Directory description 0 means ERASEd.
096C CALL #29CF,JWSAD Write sector DE.
096F CALL #09CE,SIGN_1HAND Signal 'at least one file ERASEd'.
0972 JR #0965,ERASE_LOOP ERASE all files with this filename.
The file wasn't found, an error is given if no file was ERASEd at all.
0974 NOT_FOUND CALL #09F6,TEST_1HAND Give an error if there wasn't at least
0977 JP Z,#2954,REP_26 one file ERASEd.
097A EXIT_ERASE LD A,(#1E04)
097D CP "D" If the device descriptor was a (capital)
097F CALL Z,#08AA,PCAT "D", then give a CATalogue.
Note: This doesn't work anymore because 'CAT'-type, filename and stream don't make
sense. This option was lost when the routine for command code 67 was repaired.
The following happens:
'STRM_NUM1' holds stream number -1 (=#FF, see #065A), which is attached to the
Spectrum "R"-channel (the "R"-channel is used to print characters into Spectrum
workspaces). When the CAT routine is called, the output is stored at the address
held in the Spectrum system variable 'K_CUR', which points to the edit line. Because
the filename is that of the just ERASEd file, the CAT consists only of the
'DISC .. DIRECTORY' message and the 'Free K-bytes' message.
0982 JP #0419,END Finished.
THE 'FIND A FILE' SUBROUTINE
This routine searches the directory for a matching filename by calling the DISCiPLE
ROM routine 'SCAN_CAT', it returns with HL pointing to the directory description of
the matching file. This routine is also called by command code 65 routine.
0985 FIND_FILE LD A,#10 Scan the CATalogue for a matching
0987 CALL #2993,JSCAN_CAT filename.
098A JP #29B4,JRPT_HL Make HL point to the start of the dir.
entry buffer and exit.
THE 'RENAME A FILE' ROUTINE
This routine renames a file by replacing its filename, given first, by the filename
given second. It first tests whether the 'new' name isn't used already. If not, a check
is made whether the file to be renamed exists.
098D RENAME RST #28,NEXT_C_RAM Get next character.
098E CALL #0A1E,SEPARATOR Check if there is a separator.
0991 JP NZ,#2920,REP_0 Give an error if none found.
0994 CALL #0A9C,EXP_F_NAM2 Evaluate 2nd filename.
0997 CALL #0409,ST_END_RAM Confirm end of statement and exit when
synatx checking.
099A LD A,(#1E04) Fetch device descriptor.
099D AND #DF Drop lower case bit.
099F CP "D"
09A1 JR Z,#09A8,RENAME_RUN Jump if it was a "D".
09A3 CP "M"
09A5 JP NZ,#2934,REP_10 Give error if it wasn't a "M".
09A8 RENAME_RUN CALL #2984,JTEST_DRV See if the drive is defined.
09AB CALL #0AA2,SWAP_UFIAS Swap UFIA 1 & 2 in the DFCA.
09AE CALL #0985,FIND_FILE Give an error if the 2nd filename
09B1 JP Z,#2958,REP_28 already exists.
09B4 CALL #0AA2,SWAP_UFIAS Swap UFIA 1 & 2 in the DFCA.
09B7 CALL #0985,FIND_FILE Give an error if the 1st filename
09BA JP NZ,#2954,REP_26 doesn't exist.
09BD INC HL
09BE PUSH DE
09BF LD DE,#1E1F Rename the file by copying the 2nd to
09C2 EX DE,HL the 1st name.
09C3 LD BC,10
09C6 LDIR
09C8 POP DE
09C9 CALL #29CF,JWSAD Write the CATalogue sector.
09CC JR #097A,EXIT_ERASE Exit via 'EXIT_ERASE'.