![]() |
Routines |
| Prev: 05E3 | Up: Map |
|
Used by the routine at CLASS_0B.
This entry point is used for all four commands. The value held in T-ADDR, however, distinguishes between the four commands. The first part of the following routine is concerned with the construction of the 'header information' in the work space.
|
||||||||
| SAVE_ETC | 0605 | POP AF | Drop the address - SCAN_LOOP. | |||||
| 0606 | LD A,($5C74) | Reduce T-ADDR-lo by +E0, giving +00 for SAVE, +01 for LOAD, +02 for VERIFY and +03 for MERGE. | ||||||
| 0609 | SUB $E0 | |||||||
| 060B | LD ($5C74),A | |||||||
| 060E | CALL CLASS_0A | Pass the parameters of the 'name' to the calculator stack. | ||||||
| 0611 | CALL SYNTAX_Z | Jump forward if checking syntax. | ||||||
| 0614 | JR Z,SA_DATA | |||||||
| 0616 | LD BC,$0011 | Allow seventeen locations for the header of a SAVE (T-ADDR-lo=+00) but thirty four for the other commands. | ||||||
| 0619 | LD A,($5C74) | |||||||
| 061C | AND A | |||||||
| 061D | JR Z,SA_SPACE | |||||||
| 061F | LD C,$22 | |||||||
| SA_SPACE | 0621 | RST $30 | The required amount of space is made in the work space. | |||||
| 0622 | PUSH DE | Copy the start address to the IX register pair. | ||||||
| 0623 | POP IX | |||||||
| 0625 | LD B,$0B | A program name can have up to ten characters but first enter eleven space characters into the prepared area. | ||||||
| 0627 | LD A," " | |||||||
| SA_BLANK | 0629 | LD (DE),A | ||||||
| 062A | INC DE | |||||||
| 062B | DJNZ SA_BLANK | |||||||
| 062D | LD (IX+$01),$FF | A null name is +FF only. | ||||||
| 0631 | CALL STK_FETCH | The parameters of the name are fetched and its length is tested. | ||||||
| 0634 | LD HL,$FFF6 | This is '-10'. | ||||||
| 0637 | DEC BC | In effect jump forward if the length of the name is not too long (i.e. no more than ten characters). | ||||||
| 0638 | ADD HL,BC | |||||||
| 0639 | INC BC | |||||||
| 063A | JR NC,SA_NAME | |||||||
| 063C | LD A,($5C74) | But allow for the LOADing, VERIFYing and MERGEing of programs (T-ADDR-lo>+00) with 'null' names or extra long names. | ||||||
| 063F | AND A | |||||||
| 0640 | JR NZ,SA_NULL | |||||||
|
Report F - Invalid file name.
|
||||||||
| 0642 | RST $08 | Call the error handling routine. | ||||||
| 0643 | DEFB $0E | |||||||
|
Continue to handle the name of the program.
|
||||||||
| SA_NULL | 0644 | LD A,B | Jump forward if the name has a 'null' length. | |||||
| 0645 | OR C | |||||||
| 0646 | JR Z,SA_DATA | |||||||
| 0648 | LD BC,$000A | But truncate longer names. | ||||||
|
The name is now transferred to the work space (second location onwards).
|
||||||||
| SA_NAME | 064B | PUSH IX | Copy the start address to the HL register pair. | |||||
| 064D | POP HL | |||||||
| 064E | INC HL | Step to the second location. | ||||||
| 064F | EX DE,HL | Switch the pointers over and copy the name. | ||||||
| 0650 | LDIR | |||||||
|
The many different parameters, if any, that follow the command are now considered. Start by handling 'xxx "name" DATA'.
|
||||||||
| SA_DATA | 0652 | RST $18 | Is the present code the token 'DATA'? | |||||
| 0653 | CP $E4 | |||||||
| 0655 | JR NZ,SA_SCR | Jump if not. | ||||||
| 0657 | LD A,($5C74) | However it is not possible to have 'MERGE name DATA' (T-ADDR-lo=+03). | ||||||
| 065A | CP $03 | |||||||
| 065C | JP Z,REPORT_C | |||||||
| 065F | RST $20 | Advance CH-ADD. | ||||||
| 0660 | CALL LOOK_VARS | Look in the variables area for the array. | ||||||
| 0663 | SET 7,C | Set bit 7 of the array's name. | ||||||
| 0665 | JR NC,SA_V_OLD | Jump if handling an existing array. | ||||||
| 0667 | LD HL,$0000 | Signal 'using a new array'. | ||||||
| 066A | LD A,($5C74) | Consider the value in T-ADDR-lo and give an error if trying to SAVE or VERIFY a new array. | ||||||
| 066D | DEC A | |||||||
| 066E | JR Z,SA_V_NEW | |||||||
|
Report 2 - Variable not found.
|
||||||||
| 0670 | RST $08 | Call the error handling routine. | ||||||
| 0671 | DEFB $01 | |||||||
|
Continue with the handling of an existing array.
|
||||||||
| SA_V_OLD | 0672 | JP NZ,REPORT_C | Note: this fails to exclude simple strings. | |||||
| 0675 | CALL SYNTAX_Z | Jump forward if checking syntax. | ||||||
| 0678 | JR Z,SA_DATA_1 | |||||||
| 067A | INC HL | Point to the 'low length' of the variable. | ||||||
| 067B | LD A,(HL) | The low length byte goes into the work space, followed by the high length byte. | ||||||
| 067C | LD (IX+$0B),A | |||||||
| 067F | INC HL | |||||||
| 0680 | LD A,(HL) | |||||||
| 0681 | LD (IX+$0C),A | |||||||
| 0684 | 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 | 0685 | LD (IX+$0E),C | Copy the array's name. | |||||
| 0688 | LD A,$01 | Assume an array of numbers. | ||||||
| 068A | BIT 6,C | Jump if it is so. | ||||||
| 068C | JR Z,SA_V_TYPE | |||||||
| 068E | INC A | It is an array of characters. | ||||||
| SA_V_TYPE | 068F | LD (IX+$00),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 | 0692 | EX DE,HL | Save the pointer in DE. | |||||
| 0693 | RST $20 | Is the next character a ')'? | ||||||
| 0694 | CP ")" | |||||||
| 0696 | JR NZ,SA_V_OLD | Give report C if it is not. | ||||||
| 0698 | RST $20 | Advance CH-ADD. | ||||||
| 0699 | CALL CHECK_END | Move on to the next statement if checking syntax. | ||||||
| 069C | 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.) | ||||||
| 069D | JP SA_ALL | |||||||
|
Now consider 'SCREEN$'.
|
||||||||
| SA_SCR | 06A0 | CP $AA | Is the present code the token SCREEN$? | |||||
| 06A2 | JR NZ,SA_CODE | Jump if not. | ||||||
| 06A4 | LD A,($5C74) | However it is not possible to have 'MERGE name SCREEN$' (T-ADDR-lo=+03). | ||||||
| 06A7 | CP $03 | |||||||
| 06A9 | JP Z,REPORT_C | |||||||
| 06AC | RST $20 | Advance CH-ADD. | ||||||
| 06AD | CALL CHECK_END | Move on to the next statement if checking syntax. | ||||||
| 06B0 | LD (IX+$0B),$00 | The display area and the attribute area occupy +1B00 locations and these locations start at +4000; these details are passed to the header area in the work space. | ||||||
| 06B4 | LD (IX+$0C),$1B | |||||||
| 06B8 | LD HL,$4000 | |||||||
| 06BB | LD (IX+$0D),L | |||||||
| 06BE | LD (IX+$0E),H | |||||||
| 06C1 | JR SA_TYPE_3 | Jump forward. | ||||||
|
Now consider 'CODE'.
|
||||||||
| SA_CODE | 06C3 | CP $AF | Is the present code the token 'CODE'? | |||||
| 06C5 | JR NZ,SA_LINE | Jump if not. | ||||||
| 06C7 | LD A,($5C74) | However it is not possible to have 'MERGE name CODE' (T-ADDR-lo=+03). | ||||||
| 06CA | CP $03 | |||||||
| 06CC | JP Z,REPORT_C | |||||||
| 06CF | RST $20 | Advance CH-ADD. | ||||||
| 06D0 | CALL PR_ST_END | Jump forward if the statement has not finished. | ||||||
| 06D3 | JR NZ,SA_CODE_1 | |||||||
| 06D5 | LD A,($5C74) | However it is not possible to have 'SAVE name CODE' (T-ADDR-lo=+00) by itself. | ||||||
| 06D8 | AND A | |||||||
| 06D9 | JP Z,REPORT_C | |||||||
| 06DC | CALL USE_ZERO | Put a zero on the calculator stack - for the 'start'. | ||||||
| 06DF | JR SA_CODE_2 | Jump forward. | ||||||
|
Look for a 'starting address'.
|
||||||||
| SA_CODE_1 | 06E1 | CALL CLASS_06 | Fetch the first number. | |||||
| 06E4 | RST $18 | Is the present character a comma? | ||||||
| 06E5 | CP "," | |||||||
| 06E7 | JR Z,SA_CODE_3 | Jump if it is - the number was a 'starting address'. | ||||||
| 06E9 | LD A,($5C74) | However refuse 'SAVE name CODE' that does not have a 'start' and a 'length' (T-ADDR-lo=+00). | ||||||
| 06EC | AND A | |||||||
| 06ED | JP Z,REPORT_C | |||||||
| SA_CODE_2 | 06F0 | CALL USE_ZERO | Put a zero on the calculator stack - for the 'length'. | |||||
| 06F3 | JR SA_CODE_4 | Jump forward. | ||||||
|
Fetch the 'length' as it was specified.
|
||||||||
| SA_CODE_3 | 06F5 | RST $20 | Advance CH-ADD. | |||||
| 06F6 | CALL CLASS_06 | Fetch the 'length'. | ||||||
|
The parameters are now stored in the header area of the work space.
|
||||||||
| SA_CODE_4 | 06F9 | CALL CHECK_END | But move on to the next statement now if checking syntax. | |||||
| 06FC | CALL FIND_INT2 | Compress the 'length' into the BC register pair and store it. | ||||||
| 06FF | LD (IX+$0B),C | |||||||
| 0702 | LD (IX+$0C),B | |||||||
| 0705 | CALL FIND_INT2 | Compress the 'starting address' into the BC register pair and store it. | ||||||
| 0708 | LD (IX+$0D),C | |||||||
| 070B | LD (IX+$0E),B | |||||||
| 070E | LD H,B | Transfer the 'pointer' to the HL register pair as usual. | ||||||
| 070F | LD L,C | |||||||
|
'SCREEN$' and 'CODE' are both of type 3.
|
||||||||
| SA_TYPE_3 | 0710 | LD (IX+$00),$03 | Enter the 'type' number. | |||||
| 0714 | JR SA_ALL | Rejoin the other pathways. | ||||||
|
Now consider 'LINE' and 'no further parameters'.
|
||||||||
| SA_LINE | 0716 | CP $CA | Is the present code the token 'LINE'? | |||||
| 0718 | JR Z,SA_LINE_1 | Jump if it is. | ||||||
| 071A | CALL CHECK_END | Move on to the next statement if checking syntax. | ||||||
| 071D | LD (IX+$0E),$80 | When there are no further parameters, +80 is entered. | ||||||
| 0721 | JR SA_TYPE_0 | Jump forward. | ||||||
|
Fetch the 'line number' that must follow 'LINE'.
|
||||||||
| SA_LINE_1 | 0723 | LD A,($5C74) | However only allow 'SAVE name LINE number' (T-ADDR-lo=+00). | |||||
| 0726 | AND A | |||||||
| 0727 | JP NZ,REPORT_C | |||||||
| 072A | RST $20 | Advance CH-ADD. | ||||||
| 072B | CALL CLASS_06 | Pass the number to the calculator stack. | ||||||
| 072E | CALL CHECK_END | Move on to the next statement if checking syntax. | ||||||
| 0731 | CALL FIND_INT2 | Compress the 'line number' into the BC register pair and store it. | ||||||
| 0734 | LD (IX+$0D),C | |||||||
| 0737 | LD (IX+$0E),B | |||||||
|
'LINE' and 'no further parameters' are both of type 0.
|
||||||||
| SA_TYPE_0 | 073A | LD (IX+$00),$00 | 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.
|
||||||||
| 073E | LD HL,($5C59) | The pointer to the end of the variables area (E-LINE). | ||||||
| 0741 | LD DE,($5C53) | The pointer to the start of the BASIC program (PROG). | ||||||
| 0745 | SCF | Now perform the subtraction to find the length of the 'program + variables'; store the result. | ||||||
| 0746 | SBC HL,DE | |||||||
| 0748 | LD (IX+$0B),L | |||||||
| 074B | LD (IX+$0C),H | |||||||
| 074E | LD HL,($5C4B) | Repeat the operation but this time storing the length of the 'program' only (VARS-PROG). | ||||||
| 0751 | SBC HL,DE | |||||||
| 0753 | LD (IX+$0F),L | |||||||
| 0756 | LD (IX+$10),H | |||||||
| 0759 | 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 | 075A | LD A,($5C74) | Jump forward when handling a SAVE command (T-ADDR-lo=+00). | |||||
| 075D | AND A | |||||||
| 075E | 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.
|
||||||||
| 0761 | PUSH HL | Save the 'destination' pointer. | ||||||
| 0762 | LD BC,$0011 | Form in the IX register pair the base address of the 'second header area'. | ||||||
| 0765 | ADD IX,BC | |||||||
|
Now enter a loop, leaving it only when a 'header' has been LOADed.
|
||||||||
| LD_LOOK_H | 0767 | PUSH IX | Make a copy of the base address. | |||||
| 0769 | LD DE,$0011 | LOAD seventeen bytes. | ||||||
| 076C | XOR A | Signal 'header'. | ||||||
| 076D | SCF | Signal 'LOAD'. | ||||||
| 076E | CALL LD_BYTES | Now look for a header. | ||||||
| 0771 | POP IX | Retrieve the base address. | ||||||
| 0773 | 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.
|
||||||||
| 0775 | LD A,$FE | Ensure that channel 'S' is open. | ||||||
| 0777 | CALL CHAN_OPEN | |||||||
| 077A | LD (IY+$52),$03 | Set the scroll counter (SCR-CT). | ||||||
| 077E | LD C,$80 | Signal 'names do not match'. | ||||||
| 0780 | LD A,(IX+$00) | Compare the 'new' type against the 'old' type. | ||||||
| 0783 | CP (IX-$11) | |||||||
| 0786 | JR NZ,LD_TYPE | Jump if the 'types' do not match. | ||||||
| 0788 | LD C,$F6 | But if they do, signal 'ten characters are to match'. | ||||||
| LD_TYPE | 078A | CP $04 | Clearly the 'header' is nonsense if 'type 4 or more'. | |||||
| 078C | JR NC,LD_LOOK_H | |||||||
|
The appropriate message - 'Program: ', 'Number array: ', 'Character array: ' or 'Bytes: ' is printed.
|
||||||||
| 078E | LD DE,$09C0 | The base address of the message block. | ||||||
| 0791 | PUSH BC | Save the C register whilst the appropriate message is printed. | ||||||
| 0792 | CALL PO_MSG | |||||||
| 0795 | POP BC | |||||||
|
The 'new name' is printed and as this is done the 'old' and the 'new' names are compared.
|
||||||||
| 0796 | PUSH IX | Make the DE register pair point to the 'new name' and the HL register pair to the 'old name'. | ||||||
| 0798 | POP DE | |||||||
| 0799 | LD HL,$FFF0 | |||||||
| 079C | ADD HL,DE | |||||||
| 079D | LD B,$0A | Ten characters are to be considered. | ||||||
| 079F | LD A,(HL) | Jump forward if the match is to be against an actual name. | ||||||
| 07A0 | INC A | |||||||
| 07A1 | JR NZ,LD_NAME | |||||||
| 07A3 | LD A,C | But if the 'old name' is 'null' then signal 'ten characters already match'. | ||||||
| 07A4 | ADD A,B | |||||||
| 07A5 | 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 | 07A6 | INC DE | Consider each character of the 'new name' in turn. | |||||
| 07A7 | LD A,(DE) | |||||||
| 07A8 | CP (HL) | Match it against the appropriate character of the 'old name'. | ||||||
| 07A9 | INC HL | |||||||
| 07AA | JR NZ,LD_CH_PR | Do not count it if it does not does not match. | ||||||
| 07AC | INC C | |||||||
| LD_CH_PR | 07AD | RST $10 | Print the 'new' character. | |||||
| 07AE | DJNZ LD_NAME | Loop for ten characters. | ||||||
| 07B0 | BIT 7,C | Accept the name only if the counter has reached zero. | ||||||
| 07B2 | JR NZ,LD_LOOK_H | |||||||
| 07B4 | LD A,$0D | Follow the 'new name' with a 'carriage return'. | ||||||
| 07B6 | RST $10 | |||||||
|
The correct header has been found and the time has come to consider the three commands LOAD, VERIFY, and MERGE separately.
|
||||||||
| 07B7 | POP HL | Fetch the pointer. | ||||||
| 07B8 | LD A,(IX+$00) | 'SCREEN$' and 'CODE' are handled with VERIFY. | ||||||
| 07BB | CP $03 | |||||||
| 07BD | JR Z,VR_CONTRL | |||||||
| 07BF | LD A,($5C74) | Jump forward if using a LOAD command (T-ADDR-lo=+01). | ||||||
| 07C2 | DEC A | |||||||
| 07C3 | JP Z,LD_CONTRL | |||||||
| 07C6 | CP $02 | Jump forward if using a MERGE command; continue into VR_CONTRL with a VERIFY command. | ||||||
| 07C8 | JP Z,ME_CONTRL | |||||||
| Prev: 05E3 | Up: Map |