The BASIC command execution routines II
THE 'GET TRACK AND SECTOR' SUBROUTINE
This routine loads DE with track and sector number from the file header, where they were
stored by the 'EXPT_PARMS' subroutine. Used with LOAD/SAVE @.
2870 GET_TR&SE LD A,(#3E11) Get track from LSB of LENGTH1_1.
2873 LD D,A
2874 LD A,(#3E13) Get sector from LSB of FILE_ADDR1.
2877 LD E,A
THE 'SAVE HEADER 1' SUBROUTINE
This subroutine SAVEs the 9 bytes header from UFIA 1 to the file and to the catalogue
entry which is build up in the DFCA.
2879 SAVE_HEAD1 LD HL,#3E10 Start of header 1.
287C LD DE,#3BA9 Address of header area of a catalogue
287F LD B,9 The headers length.
2881 SAVE_H11 LD A,(HL)
2882 LD (DE),A
2883 CALL #0761,SBYT Save the byte to the file.
2886 INC HL
2887 INC DE
2888 DJNZ #2881,SAVE_H11 Repeat for all nine bytes.
288A RET Finished.
THE 'SAVE' COMMAND SYNTAX ROUTINE
This routine checks that the SAVE command has the appropriate syntax.
288B SAVE LD IX,#3AC3 Pointer to the DFCA.
288F CALL #160D,SIGN_5 Signal 'SAVEing'.
2892 CALL #2665,EXPT_PARMS Evaluate & store all parameters.
2895 CALL #0702,TEST_DRV See if the drive is defined.
2898 LD A,(#3E04)
289B CP 64,"@"
289D JR NZ,#28AF,SAVE_RUN Jump if the command wasn't 'SAVE @'.
289F LD IX,(#3E15) Get address where sector is to be saved
28A3 CALL #2870,GET_TR&SE from. Get track and sector number.
28A6 LD A,(#3E01) Get drive number.
28A9 CALL #2FF2,HWSAD Write the sector.
28AC JP #047C,END Finished.
THE 'SAVE A FILE' ROUTINE
This routine SAVEs the specified file on the specified drive.
28AF SAVE_RUN CALL #0AD9,OFSM_2 Open the file for 'SAVE'.
28B2 JP NZ,#254E,ERASE_EXIT Exit if the file isn't to be
28B5 LD A,(#3E05)
28B8 CP 11 Pass the header to the file unless it's
28BA CALL NZ,#2879,SAVE_HEAD1 an 'execute' file.
28BD LD HL,(#3E13) Fetch the start address.
28C0 LD DE,(#3E11) Fetch the length.
28C4 CALL #0850,HSVBK_2 Save the block.
28C7 CALL #0B89,CFSM Close the file.
28CA JP #254E,ERASE_EXIT Exit via 'ERASE_EXIT'.
THE 'LOAD HEADER INTO UFIA 2' SUBROUTINE
This subroutine LOADs a 9 bytes header into UFIA 2.
28CD LOAD_HEAD2 LD HL,#3E29 Start of HEADER 2.
28D0 LD B,9 Length of a header.
28D2 LOAD_H21 CALL #077F,LBYT Load a byte.
28D5 LD (HL),A Store it into UFIA 2.
28D6 INC HL
28D7 DJNZ #28D2,LOAD_H21 Repeat for all header bytes.
THE 'LOAD' COMMAND SYNTAX ROUTINE
The 'LOAD' flag is set and the routine continues into the 'LOAD_VERIFY_MERGE' routine
28DA LOAD CALL #1608,SIGN_4 Signal 'LOADing'.
28DD JR #28E7,LD_VF_MR
THE 'VERIFY' COMMAND SYNTAX ROUTINE
The 'VERIFY' flag is set and again the 'LOAD_VERIFY_MERGE' routine handles the rest.
28DF VERIFY CALL #1617,SIGN_7 Signal 'VERIFYing'.
28E2 JR #28E7,LD_VF_MR
THE 'MERGE' COMMAND SYNTAX ROUTINE
The 'MERGE' flag is set and 'LOAD_VERIFY_MERGE' continues the syntax checking.
28E4 MERGE CALL #1612,SIGN_6 Signal 'MERGEing'.
THE 'LOAD_VERIFY_MERGE' COMMAND ROUTINE
This routine checks the syntax of the LOAD, VERIFY and MERGE commands and executes it.
28E7 LD_VF_MR LD IX,#3AC3 Pointer to DFCA.
28EB CALL #2665,EXPT_PARMS Evaluate & store all parameters.
28EE LD_VF_MR1 CALL #0702,TEST_DRV See if the drive is defined.
28F1 LD A,(#3E04)
28F4 CP 64,"@"
28F6 JR NZ,#2908,LD_ETC_RUN Jump if it wasn't a '@' command.
28F8 LD IX,(#3E15) Get address where sector is to be
28FC CALL #2870,GET_TR&SE loaded. Get track and sector number.
28FF LD A,(#3E01) Get drive number.
2902 CALL #2FD4,HRSAD Load the sector.
2905 JP #047C,END Finished.
The routine continues here when a file is to be LOADed from disk.
2908 LD_ETC_RUN CALL #0BCF,HGFLE_2 Open the file for loading.
290B LD A,(#3E05)
290E CP 5
2910 JR NZ,#2921,LD_ETC_R1 Jump if it isn't a 'Snapshot 48K'.
2912 LD SP,#3FEA Use internal stack.
2915 LD HL,16384 Start address and length of a 48K Snap.
2918 LD DE,49152
291B CALL #079E,LOAD_FILE Load the file.
291E JP #00B1,SNAP_EXIT Exit via 'SNAP_EXIT'.
2921 LD_ETC_R1 CP 9
2923 JR NZ,#294A,LD_ETC_R3 Jump if it isn't a 'Snapshot 128K'.
2925 LD SP,#3FEA Use internal stack.
2928 CALL #077F,LBYT Get the page configuration byte.
292B PUSH AF
292C AND #F8 Keep the RAM page bits only.
292E LD B,#08 LOAD the eight RAM-pages.
2930 LD_ETC_R2 PUSH AF
2931 PUSH BC
2932 CALL #223F,RAMPAGE_A Page in RAM bank.
2935 LD HL,49152 Start address and length of each RAM
2938 LD DE,16384 bank.
293B CALL #079E,LOAD_FILE 'LOAD DE bytes to HL'.
293E POP BC
293F POP AF
2940 INC A Next RAM bank.
2941 DJNZ #2930,LD_ETC_R2 Repeat for each RAM bank.
2943 POP AF Retrieve page configuration.
2944 CALL #223F,RAMPAGE_A Page in the right RAM, ROM and SCR$
2947 JP #00B1,SNAP_EXIT bank, exit via 'SNAP_EXIT'.
294A LD_ETC_R3 CP 11
294C JR NZ,#2954,LD_ETC_R4 Jump if it isn't a 'Execute' file.
294E CALL #3BD6 Execute (this is the address of the
2951 JP #047C,END disk buffer). Finished.
2954 LD_ETC_R4 CALL #28CD,LOAD_HEAD2 Load the header into UFIA2.
2957 LD A,(#3E10) Fetch type of program to be LOADed.
295A LD B,A
295B LD A,(#3E29) Fetch type of program found.
295E CP B
295F JP NZ,#1654,REP_8 Give an error if they aren't equal.
NOTE: The error 'Invalid FILE NAME' is given, maybe MGT have made a typing error. 'Wrong
FILE type' is the right message.
2962 CP 3
2964 JR Z,#2974,LD_ETC_R5 Jump if it's a 'CODE' file.
2966 JP NC,#1654,REP_8 Give error if file type >= 4.
2969 CALL #163A,TEST_6
296C JR NZ,#29DF,MERGE_CTRL Jump if 'MERGEing'.
296E CALL #163F,TEST_7 Jump if not 'VERIFYing' (i.e. doing a
2971 JP Z,#29FB,LOAD_CTRL LOAD).
Now deal with loading of all files with type 3, like 'CODE' and 'SCREEN$', or verifying
of all file types.
2974 LD_ETC_R5 CALL #163A,TEST_6
2977 JP NZ,#1660,REP_14 Give error if 'MERGE .. CODE' was used.
297A LD HL,(#3E11) Fetch length of requested file.
297D LD DE,(#3E2A) Fetch length of file found.
2981 LD A,H
2982 OR L
2983 JR Z,#2992,LD_ETC_R6 Jump if length unspecified.
2985 SBC HL,DE Jump if file to be LOADed is shorter
2987 JR NC,#2992,LD_ETC_R6 than or of equal length as the
2989 CALL #1630,TEST_4
298C JP Z,#165C,REP_12 'VERIFY failed' if not LOADing.
298F JP #1662,REP_15 'CODE error' otherwise.
2992 LD_ETC_R6 LD HL,(#3E13) Fetch start address from FILE_ADDR1
2995 LD A,H
2996 OR L
2997 JR NZ,#299C,LD_ETC_R7 Jump if a start address was specified.
2999 LD HL,(#3E2C) Otherwise use the start address of the
299C LD_ETC_R7 LD A,(#3E29) But if the file is a BASIC program the
299F AND A start address is held in (PROG).
29A0 JR NZ,#29A5,LD_ETC_R8
29A2 LD HL,(23635) Fetch 'start' from (PROG).
29A5 LD_ETC_R8 CALL #2A9A,LV_ANY Load the file.
29A8 CALL #163F,TEST_7
29AB JP NZ,#047C,END Exit when 'VERIFYing'.
29AE LD HL,(#3E17) Fetch execute address.
29B1 CALL #29BD,EXEC_CODE Use it if it was specified.
29B4 LD HL,(#3E30) Otherwise use the files execute
29B7 CALL #29BD,EXEC_CODE address.
29BA JP #047C,END But if it hasn't one either, exit here.
THE 'EXECUTE CODE FILE' SUBROUTINE
This routine jumps to the address in the HL register pair (if it is valid) after pushing
the addresses of 'STMT_R_1' and 'STACK_BC'.
29BD EXEC_CODE LD A,H
29BE OR L
29BF RET Z Return if the execute address is zero.
29C0 LD A,H
29C1 CP #FF
29C3 JR NZ,#29C9,EXEC_C1
29C5 LD A,L Also return when the execute address is
29C6 CP #FF #FFFF.
29C8 RET Z
29C9 EXEC_C1 LD SP,(23613) Clear the stack. (ERR_SP)
29CD LD (IY+0),#FF Clear the error.
29D1 CALL #168E,BORD_REST Restore the border colour.
29D4 LD BC,#1B7D,STMT_R_1 Return to 'STMT_R_1' in the 'main' ROM
29D7 PUSH BC when finished.
29D8 LD BC,#2D2B,STACK_BC Return to 'STMT_R_1' via 'STACK_BC'
29DB PUSH BC also in the 'main' ROM.
29DC JP #004F,UNPAGE_HL Jump to the execute address while
unpaging the +D.
THE 'MERGE CONTROL' ROUTINE This routine handles the MERGEing of a (BASIC) file. No test is made if the file is an array when using the MERGE 'p'n syntax (see NOTE at 'LOAD CONTROL').
29DF MERGE_CTRL LD BC,(#3E2A) Fetch the length of the program to be
29E3 PUSH BC MERGEd.
29E4 INC BC Extra location for the 'end marker'.
29E5 RST #10,CALBAS Call 'BC_SPACES' in the 'main' ROM to
29E6 DEFW #0030,BC_SPACES make the required room in workspace.
29E8 LD (HL),128 Mark the end.
29EA EX DE,HL Move start pointer to HL.
29EB POP DE Length to DE.
29EC PUSH HL
29ED CALL #2A9A,LV_ANY Load the file.
29F0 POP HL Fetch 'start' of new program.
29F1 LD DE,(23635) Fetch 'start' of old program (PROG).
29F5 RST #10,CALBAS Do the MERGEing by calling the 'main'
29F6 DEFW #08D2,ME_NEW_LP ROM 'MERGE' routine.
29F8 JP #047C,END Finished.
THE 'LOAD CONTROL' ROUTINE
This routine handles the LOADing of a BASIC program or an array.
NOTE: The Spectrum will crash when trying to LOAD or MERGE 'p' an array. The problem
starts in the 'HGFLE_2' ('OPEN A FILE FOR LOAD') subroutine in ROM (#0BCF) which is called from
the 'LD_ETC_RUN' routine at #2908. Normally UFIA1 holds the parameters of the existing array (if
present), and UFIA2 holds the parameters of the array to be loaded. But when the 'p' syntax is
used, the 'HGFLE_2' routine makes the contents of UFIA1 equal to UFIA2. The reclaiming at
address #2A32 then fails, trying to reclaim something which isn't there.
29FB LOAD_CTRL LD DE,(#3E2A) Fetch 'new' length.
29FF LD HL,(#3E13) Fetch 'old' start (=0 when loading a
2A02 PUSH HL 'new' array').
2A03 LD A,H
2A04 OR L
2A05 JR NZ,#2A0D,LOAD_C1 Jump if not a 'new' array.
2A07 INC DE Increment 'length' by 3, i.e. allows
2A08 INC DE for the insertion of array name and
2A09 INC DE two-byte length.
2A0A EX DE,HL Move 'length' to HL.
2A0B JR #2A16,LOAD_C2 Jump forward.
The array to be loaded replaces an existing array.
2A0D LOAD_C1 LD HL,(#3E11) Fetch 'old' length (i.e. length of
existing program or array) from UFIA1.
2A10 EX DE,HL Move 'new' length to HL.
2A11 SCF Jump if the program or array to be
2A12 SBC HL,DE loaded isn't longer than the existing
2A14 JR C,#2A1F,LOAD_C3 one.
2A16 LOAD_C2 LD DE,5 Otherwise a check must be made to
2A19 ADD HL,DE ensure that there is sufficient space
2A1A LD B,H in memory for the program (or array) to
2A1B LD C,L be loaded.
2A1C RST #10,CALBAS Make the check by calling the 'main'
2A1D DEFW #1F05,TEST_ROOM ROM 'TEST_ROOM' subroutine.
2A1F LOAD_C3 POP HL Restore 'old' start (=0 when handling
2A20 LD A,(#3E29) a 'new' array).
2A23 AND A
2A24 JR Z,#2A57,LD_PROG Jump if it's a BASIC program.
2A26 LD A,H
2A27 OR L Jump unless an 'old' array is to be
2A28 JR Z,#2A35,LOAD_C4 erased before loading the 'new' one.
2A2A DEC HL Points to high byte of 'array length'.
2A2B LD B,(HL) Fetch the 'length'.
2A2C DEC HL
2A2D LD C,(HL)
2A2E DEC HL Now points to the 'array name'.
2A2F INC BC Include 'length' and 'name' in the
2A30 INC BC array length.
2A31 INC BC
2A32 RST #10,CALBAS Call 'RECLAIM_2' in the 'main' ROM to
2A33 DEFW #19E8,RECLAIM_2 delete the array.
2A35 LOAD_C4 LD HL,(23641) (E_LINE) points to the end of variables
2A38 DEC HL area+1.
2A39 LD BC,(#3E2A) Fetch length of array to be loaded.
2A3D PUSH BC
2A3E INC BC Include in the length one byte for the
2A3F INC BC 'array name' and two bytes for the
2A40 INC BC 'array length'.
2A41 LD A,(#3E15) Fetch the array name from 'LENGTH1_2'.
2A44 PUSH AF
2A45 RST #10,CALBAS Call 'MAKE_ROOM' to create the space
2A46 DEFW #1655,MAKE_ROOM for the array.
2A48 INC HL Point to first 'new' location inserted.
2A49 POP AF
2A4A LD (HL),A Store array name into first location.
2A4B POP DE
2A4C INC HL Store array length into the following
2A4D LD (HL),E two locations.
2A4E INC HL
2A4F LD (HL),D
2A50 INC HL
2A51 CALL #2A9A,LV_ANY Load the file.
2A54 JP #047C,END Finished.
Now deal with the LOADing of a BASIC program and its variables.
2A57 LD_PROG LD DE,(23635) Fetch start of existing program. (PROG)
2A5B LD HL,(23641) Fetch end of existing program. I.e.
2A5E DEC HL (E_LINE)-1.
2A5F RST #10,CALBAS Delete the program by calling
2A60 DEFW #19E5,RECLAIM_1 'RECLAIM_1' in the 'main' ROM.
2A62 LD BC,(#3E2A) Fetch length of program and variables.
2A66 LD HL,(23635) Fetch (PROG), start of a BASIC program.
2A69 RST #10,CALBAS Create the required space by calling
2A6A DEFW #1655,MAKE_ROOM 'MAKE_ROOM'.
2A6C INC HL Point to the first location.
2A6D LD BC,(#3E2E) Fetch length without variables.
2A71 ADD HL,BC Calculate and store the start of the
2A72 LD (23627),HL variables area.
2A75 LD A,(#3E31) When no autostart is known this
2A78 LD H,A ('AUTOSTART2-hi') holds #FF.
2A79 AND #C0
2A7B JR NZ,#2A88,LD_PROG1 Jump with no autostart.
2A7D LD A,(#3E30) Otherwise store the autostart line
2A80 LD L,A number into 'NEWPPC' and clear 'NSPPC'.
2A81 LD (23618),HL These hold the line and the statement
2A84 LD (IY+10),#00 to be executed respectively.
2A88 LD_PROG1 LD HL,(23635) Fetch the start of the BASIC program.
2A8B LD DE,(#3E2A) Fetch the length + variables.
2A8F DEC HL Reset the DATA pointer 'DATADD' to the
2A90 LD (23639),HL beginning of the program.
2A93 INC HL Balance the 'DEC HL'.
2A94 CALL #2A9A,LV_ANY Load the file.
2A97 JP #047C,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'.
2A9A LV_ANY LD A,D
2A9B OR E
2A9C RET Z Return if 'length' is zero.
2A9D CALL #163F,TEST_7
2AA0 JR NZ,#2AAE,LV_ANY3 Jump if 'VERIFYing'.
2AA2 JP #079E,LOAD_FILE Otherwise load the file.
2AA5 LV_ANY1 CP (HL) The actual VERIFY, i.e. compare the
fetched byte with that held in memory.
2AA6 JP NZ,#165C,REP_12 Give an error if they don't match.
2AA9 LV_ANY2 INC HL Next memory address.
2AAA DEC DE One byte less to go.
2AAB LD A,D
2AAC OR E
2AAD RET Z Exit if no more bytes left.
2AAE LV_ANY3 CALL #077F,LBYT Load one byte.
2AB1 CALL #163F,TEST_7
2AB4 JR NZ,#2AA5,LV_ANY1 Jump if VERIFYing.
2AB6 LD (HL),A Otherwise store the byte.
2AB7 JR #2AA9,LV_ANY2 Repeat for all bytes.
THE 'FORMAT' COMMAND SYNTAX ROUTINE
This routine tests if the command has the appropriate syntax.
2AB9 FORMAT RST #28,NEXT_C Advance CH_ADD to next character.
2ABA AND #DF Only capitals.
2ABC CP 68,"D"
2ABE JP NZ,#1644,REP_0 Give an error if not a "D".
2AC1 RST #28,NEXT_C Next character.
2AC2 CALL #25FA,EXPT_DEVN2 Evaluate the drive number.
2AC5 CP 204,"TO" Jump if the current character isn't
2AC7 JR NZ,#2AD3,FORMAT_1 'TO'.
2AC9 CALL #2626,SWAP_UFIAS Exchange UFIA1 and UFIA2.
2ACC RST #28,NEXT_C Update CH_ADD.
2ACD CALL #25FA,EXPT_DEVN2 Evaluate 2nd drive number.
2AD0 CALL #2626,SWAP_UFIAS Exchange UFIA's again.
2AD3 FORMAT_1 CALL #3148,ST_END_RAM Confirm end of statement and exit when
2AD6 CALL #0702,TEST_DRV Check if the drive is defined.
2AD9 RST #10,CALBAS
2ADA DEFW #0D6E,CLS_LOWER Clear lower screen area.
2ADC SET 5,(IY+2) Signal 'lower screen has to be
2AE0 CALL #180C,MESG_2 Print 'Are you SURE ? (y/n)' message.
2AE3 CALL #0B60,TEST_Y Wait for a key, Zero set means 'Y'
2AE6 JP NZ,#047C,END pressed. Finished when not sure.
2AE9 CALL #0C2B,FORMAT_RUN Otherwise FORMAT the disk.
2AEC JP #047C,END Finished.