![]() |
Routines |
| Prev: 01507 | Up: Map | Next: 01995 |
| SAVE_ETC | 01541 | POP AF | Drop the address - SCAN_LOOP. | |
| 01542 | LD A,(23668) | Reduce T-ADDR-lo by 224, giving 0 for SAVE, 1 for LOAD, 2 for VERIFY and 3 for MERGE. | ||
| 01545 | SUB 224 | |||
| 01547 | LD (23668),A | |||
| 01550 | CALL CLASS_0A | Pass the parameters of the 'name' to the calculator stack. | ||
| 01553 | CALL SYNTAX_Z | Jump forward if checking syntax. | ||
| 01556 | JR Z,SA_DATA | |||
| 01558 | LD BC,17 | Allow seventeen locations for the header of a SAVE (T-ADDR-lo=0) but thirty four for the other commands. | ||
| 01561 | LD A,(23668) | |||
| 01564 | AND A | |||
| 01565 | JR Z,SA_SPACE | |||
| 01567 | LD C,34 | |||
| SA_SPACE | 01569 | RST 48 | The required amount of space is made in the work space. | |
| 01570 | PUSH DE | Copy the start address to the IX register pair. | ||
| 01571 | POP IX | |||
| 01573 | LD B,11 | A program name can have up to ten characters but first enter eleven space characters into the prepared area. | ||
| 01575 | LD A," " | |||
| SA_BLANK | 01577 | LD (DE),A | ||
| 01578 | INC DE | |||
| 01579 | DJNZ SA_BLANK | |||
| 01581 | LD (IX+1),255 | A null name is 255 only. | ||
| 01585 | CALL STK_FETCH | The parameters of the name are fetched and its length is tested. | ||
| 01588 | LD HL,65526 | This is '-10'. | ||
| 01591 | DEC BC | In effect jump forward if the length of the name is not too long (i.e. no more than ten characters). | ||
| 01592 | ADD HL,BC | |||
| 01593 | INC BC | |||
| 01594 | JR NC,SA_NAME | |||
| 01596 | LD A,(23668) | But allow for the LOADing, VERIFYing and MERGEing of programs (T-ADDR-lo>0) with 'null' names or extra long names. | ||
| 01599 | AND A | |||
| 01600 | JR NZ,SA_NULL | |||
|
Report F - Invalid file name.
|
||||
| 01602 | RST 8 | Call the error handling routine. | ||
| 01603 | DEFB 14 | |||
|
Continue to handle the name of the program.
|
||||
| SA_NULL | 01604 | LD A,B | Jump forward if the name has a 'null' length. | |
| 01605 | OR C | |||
| 01606 | JR Z,SA_DATA | |||
| 01608 | LD BC,10 | But truncate longer names. | ||
|
The name is now transferred to the work space (second location onwards).
|
||||
| SA_NAME | 01611 | PUSH IX | Copy the start address to the HL register pair. | |
| 01613 | POP HL | |||
| 01614 | INC HL | Step to the second location. | ||
| 01615 | EX DE,HL | Switch the pointers over and copy the name. | ||
| 01616 | LDIR | |||
|
The many different parameters, if any, that follow the command are now considered. Start by handling 'xxx "name" DATA'.
|
||||
| SA_DATA | 01618 | RST 24 | Is the present code the token 'DATA'? | |
| 01619 | CP 228 | |||
| 01621 | JR NZ,SA_SCR | Jump if not. | ||
| 01623 | LD A,(23668) | However it is not possible to have 'MERGE name DATA' (T-ADDR-lo=3). | ||
| 01626 | CP 3 | |||
| 01628 | JP Z,REPORT_C | |||
| 01631 | RST 32 | Advance CH-ADD. | ||
| 01632 | CALL LOOK_VARS | Look in the variables area for the array. | ||
| 01635 | SET 7,C | Set bit 7 of the array's name. | ||
| 01637 | JR NC,SA_V_OLD | Jump if handling an existing array. | ||
| 01639 | LD HL,0 | Signal 'using a new array'. | ||
| 01642 | LD A,(23668) | Consider the value in T-ADDR-lo and give an error if trying to SAVE or VERIFY a new array. | ||
| 01645 | DEC A | |||
| 01646 | JR Z,SA_V_NEW | |||
|
Report 2 - Variable not found.
|
||||
| 01648 | RST 8 | Call the error handling routine. | ||
| 01649 | DEFB 1 | |||
|
Continue with the handling of an existing array.
|
||||
| SA_V_OLD | 01650 | JP NZ,REPORT_C | Note: this fails to exclude simple strings. | |
| 01653 | CALL SYNTAX_Z | Jump forward if checking syntax. | ||
| 01656 | JR Z,SA_DATA_1 | |||
| 01658 | INC HL | Point to the 'low length' of the variable. | ||
| 01659 | LD A,(HL) | The low length byte goes into the work space, followed by the high length byte. | ||
| 01660 | LD (IX+11),A | |||
| 01663 | INC HL | |||
| 01664 | LD A,(HL) | |||
| 01665 | LD (IX+12),A | |||
| 01668 | INC HL | Step past the length bytes. | ||
|
The next part is common to both 'old' and 'new' arrays. Note: syntax path error.
|
||||
| SA_V_NEW | 01669 | LD (IX+14),C | Copy the array's name. | |
| 01672 | LD A,1 | Assume an array of numbers. | ||
| 01674 | BIT 6,C | Jump if it is so. | ||
| 01676 | JR Z,SA_V_TYPE | |||
| 01678 | INC A | It is an array of characters. | ||
| SA_V_TYPE | 01679 | LD (IX+0),A | Save the 'type' in the first location of the header area. | |
|
The last part of the statement is examined before joining the other pathways.
|
||||
| SA_DATA_1 | 01682 | EX DE,HL | Save the pointer in DE. | |
| 01683 | RST 32 | Is the next character a ')'? | ||
| 01684 | CP ")" | |||
| 01686 | JR NZ,SA_V_OLD | Give report C if it is not. | ||
| 01688 | RST 32 | Advance CH-ADD. | ||
| 01689 | CALL CHECK_END | Move on to the next statement if checking syntax. | ||
| 01692 | EX DE,HL | Return the pointer to the HL register pair before jumping forward. (The pointer indicates the start of an existing array's contents.) | ||
| 01693 | JP SA_ALL | |||
|
Now consider 'SCREEN$'.
|
||||
| SA_SCR | 01696 | CP 170 | Is the present code the token SCREEN$? | |
| 01698 | JR NZ,SA_CODE | Jump if not. | ||
| 01700 | LD A,(23668) | However it is not possible to have 'MERGE name SCREEN$' (T-ADDR-lo=3). | ||
| 01703 | CP 3 | |||
| 01705 | JP Z,REPORT_C | |||
| 01708 | RST 32 | Advance CH-ADD. | ||
| 01709 | CALL CHECK_END | Move on to the next statement if checking syntax. | ||
| 01712 | LD (IX+11),0 | The display area and the attribute area occupy 6912 locations and these locations start at 16384; these details are passed to the header area in the work space. | ||
| 01716 | LD (IX+12),27 | |||
| 01720 | LD HL,16384 | |||
| 01723 | LD (IX+13),L | |||
| 01726 | LD (IX+14),H | |||
| 01729 | JR SA_TYPE_3 | Jump forward. | ||
|
Now consider 'CODE'.
|
||||
| SA_CODE | 01731 | CP 175 | Is the present code the token 'CODE'? | |
| 01733 | JR NZ,SA_LINE | Jump if not. | ||
| 01735 | LD A,(23668) | However it is not possible to have 'MERGE name CODE' (T-ADDR-lo=3). | ||
| 01738 | CP 3 | |||
| 01740 | JP Z,REPORT_C | |||
| 01743 | RST 32 | Advance CH-ADD. | ||
| 01744 | CALL PR_ST_END | Jump forward if the statement has not finished. | ||
| 01747 | JR NZ,SA_CODE_1 | |||
| 01749 | LD A,(23668) | However it is not possible to have 'SAVE name CODE' (T-ADDR-lo=0) by itself. | ||
| 01752 | AND A | |||
| 01753 | JP Z,REPORT_C | |||
| 01756 | CALL USE_ZERO | Put a zero on the calculator stack - for the 'start'. | ||
| 01759 | JR SA_CODE_2 | Jump forward. | ||
|
Look for a 'starting address'.
|
||||
| SA_CODE_1 | 01761 | CALL CLASS_06 | Fetch the first number. | |
| 01764 | RST 24 | Is the present character a comma? | ||
| 01765 | CP "," | |||
| 01767 | JR Z,SA_CODE_3 | Jump if it is - the number was a 'starting address'. | ||
| 01769 | LD A,(23668) | However refuse 'SAVE name CODE' that does not have a 'start' and a 'length' (T-ADDR-lo=0). | ||
| 01772 | AND A | |||
| 01773 | JP Z,REPORT_C | |||
| SA_CODE_2 | 01776 | CALL USE_ZERO | Put a zero on the calculator stack - for the 'length'. | |
| 01779 | JR SA_CODE_4 | Jump forward. | ||
|
Fetch the 'length' as it was specified.
|
||||
| SA_CODE_3 | 01781 | RST 32 | Advance CH-ADD. | |
| 01782 | CALL CLASS_06 | Fetch the 'length'. | ||
|
The parameters are now stored in the header area of the work space.
|
||||
| SA_CODE_4 | 01785 | CALL CHECK_END | But move on to the next statement now if checking syntax. | |
| 01788 | CALL FIND_INT2 | Compress the 'length' into the BC register pair and store it. | ||
| 01791 | LD (IX+11),C | |||
| 01794 | LD (IX+12),B | |||
| 01797 | CALL FIND_INT2 | Compress the 'starting address' into the BC register pair and store it. | ||
| 01800 | LD (IX+13),C | |||
| 01803 | LD (IX+14),B | |||
| 01806 | LD H,B | Transfer the 'pointer' to the HL register pair as usual. | ||
| 01807 | LD L,C | |||
|
'SCREEN$' and 'CODE' are both of type 3.
|
||||
| SA_TYPE_3 | 01808 | LD (IX+0),3 | Enter the 'type' number. | |
| 01812 | JR SA_ALL | Rejoin the other pathways. | ||
|
Now consider 'LINE' and 'no further parameters'.
|
||||
| SA_LINE | 01814 | CP 202 | Is the present code the token 'LINE'? | |
| 01816 | JR Z,SA_LINE_1 | Jump if it is. | ||
| 01818 | CALL CHECK_END | Move on to the next statement if checking syntax. | ||
| 01821 | LD (IX+14),128 | When there are no further parameters, 128 is entered. | ||
| 01825 | JR SA_TYPE_0 | Jump forward. | ||
|
Fetch the 'line number' that must follow 'LINE'.
|
||||
| SA_LINE_1 | 01827 | LD A,(23668) | However only allow 'SAVE name LINE number' (T-ADDR-lo=0). | |
| 01830 | AND A | |||
| 01831 | JP NZ,REPORT_C | |||
| 01834 | RST 32 | Advance CH-ADD. | ||
| 01835 | CALL CLASS_06 | Pass the number to the calculator stack. | ||
| 01838 | CALL CHECK_END | Move on to the next statement if checking syntax. | ||
| 01841 | CALL FIND_INT2 | Compress the 'line number' into the BC register pair and store it. | ||
| 01844 | LD (IX+13),C | |||
| 01847 | LD (IX+14),B | |||
|
'LINE' and 'no further parameters' are both of type 0.
|
||||
| SA_TYPE_0 | 01850 | LD (IX+0),0 | Enter the 'type' number. | |
|
The parameters that describe the program, and its variables, are found and stored in the header area of the work space.
|
||||
| 01854 | LD HL,(23641) | The pointer to the end of the variables area (E-LINE). | ||
| 01857 | LD DE,(23635) | The pointer to the start of the BASIC program (PROG). | ||
| 01861 | SCF | Now perform the subtraction to find the length of the 'program + variables'; store the result. | ||
| 01862 | SBC HL,DE | |||
| 01864 | LD (IX+11),L | |||
| 01867 | LD (IX+12),H | |||
| 01870 | LD HL,(23627) | Repeat the operation but this time storing the length of the 'program' only (VARS-PROG). | ||
| 01873 | SBC HL,DE | |||
| 01875 | LD (IX+15),L | |||
| 01878 | LD (IX+16),H | |||
| 01881 | EX DE,HL | Transfer the 'pointer' to the HL register pair as usual. | ||
|
In all cases the header information has now been prepared.
The routine continues with the first task being to separate SAVE from LOAD, VERIFY and MERGE.
|
||||
| SA_ALL | 01882 | LD A,(23668) | Jump forward when handling a SAVE command (T-ADDR-lo=0). | |
| 01885 | AND A | |||
| 01886 | JP Z,SA_CONTRL | |||
|
In the case of a LOAD, VERIFY or MERGE command the first seventeen bytes of the 'header area' in the work space hold the prepared information, as detailed above; and it is now time to fetch a 'header' from the tape.
|
||||
| 01889 | PUSH HL | Save the 'destination' pointer. | ||
| 01890 | LD BC,17 | Form in the IX register pair the base address of the 'second header area'. | ||
| 01893 | ADD IX,BC | |||
|
Now enter a loop, leaving it only when a 'header' has been LOADed.
|
||||
| LD_LOOK_H | 01895 | PUSH IX | Make a copy of the base address. | |
| 01897 | LD DE,17 | LOAD seventeen bytes. | ||
| 01900 | XOR A | Signal 'header'. | ||
| 01901 | SCF | Signal 'LOAD'. | ||
| 01902 | CALL LD_BYTES | Now look for a header. | ||
| 01905 | POP IX | Retrieve the base address. | ||
| 01907 | JR NC,LD_LOOK_H | Go round the loop until successful. | ||
|
The new 'header' is now displayed on the screen but the routine will only proceed if the 'new' header matches the 'old' header.
|
||||
| 01909 | LD A,254 | Ensure that channel 'S' is open. | ||
| 01911 | CALL CHAN_OPEN | |||
| 01914 | LD (IY+82),3 | Set the scroll counter (SCR-CT). | ||
| 01918 | LD C,128 | Signal 'names do not match'. | ||
| 01920 | LD A,(IX+0) | Compare the 'new' type against the 'old' type. | ||
| 01923 | CP (IX-17) | |||
| 01926 | JR NZ,LD_TYPE | Jump if the 'types' do not match. | ||
| 01928 | LD C,246 | But if they do, signal 'ten characters are to match'. | ||
| LD_TYPE | 01930 | CP 4 | Clearly the 'header' is nonsense if 'type 4 or more'. | |
| 01932 | JR NC,LD_LOOK_H | |||
|
The appropriate message - 'Program: ', 'Number array: ', 'Character array: ' or 'Bytes: ' is printed.
|
||||
| 01934 | LD DE,2496 | The base address of the message block. | ||
| 01937 | PUSH BC | Save the C register whilst the appropriate message is printed. | ||
| 01938 | CALL PO_MSG | |||
| 01941 | POP BC | |||
|
The 'new name' is printed and as this is done the 'old' and the 'new' names are compared.
|
||||
| 01942 | PUSH IX | Make the DE register pair point to the 'new name' and the HL register pair to the 'old name'. | ||
| 01944 | POP DE | |||
| 01945 | LD HL,65520 | |||
| 01948 | ADD HL,DE | |||
| 01949 | LD B,10 | Ten characters are to be considered. | ||
| 01951 | LD A,(HL) | Jump forward if the match is to be against an actual name. | ||
| 01952 | INC A | |||
| 01953 | JR NZ,LD_NAME | |||
| 01955 | LD A,C | But if the 'old name' is 'null' then signal 'ten characters already match'. | ||
| 01956 | ADD A,B | |||
| 01957 | LD C,A | |||
|
A loop is entered to print the characters of the 'new name'. The name will be accepted if the 'counter' reaches zero, at least.
|
||||
| LD_NAME | 01958 | INC DE | Consider each character of the 'new name' in turn. | |
| 01959 | LD A,(DE) | |||
| 01960 | CP (HL) | Match it against the appropriate character of the 'old name'. | ||
| 01961 | INC HL | |||
| 01962 | JR NZ,LD_CH_PR | Do not count it if it does not does not match. | ||
| 01964 | INC C | |||
| LD_CH_PR | 01965 | RST 16 | Print the 'new' character. | |
| 01966 | DJNZ LD_NAME | Loop for ten characters. | ||
| 01968 | BIT 7,C | Accept the name only if the counter has reached zero. | ||
| 01970 | JR NZ,LD_LOOK_H | |||
| 01972 | LD A,13 | Follow the 'new name' with a 'carriage return'. | ||
| 01974 | RST 16 | |||
|
The correct header has been found and the time has come to consider the three commands LOAD, VERIFY, and MERGE separately.
|
||||
| 01975 | POP HL | Fetch the pointer. | ||
| 01976 | LD A,(IX+0) | 'SCREEN$' and 'CODE' are handled with VERIFY. | ||
| 01979 | CP 3 | |||
| 01981 | JR Z,VR_CONTRL | |||
| 01983 | LD A,(23668) | Jump forward if using a LOAD command (T-ADDR-lo=1). | ||
| 01986 | DEC A | |||
| 01987 | JP Z,LD_CONTRL | |||
| 01990 | CP 2 | Jump forward if using a MERGE command; continue into VR_CONTRL with a VERIFY command. | ||
| 01992 | JP Z,ME_CONTRL | |||
| Prev: 01507 | Up: Map | Next: 01995 |