Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- CONTENTS
- INTRODUCTION
- USE OF HOOK CODES
- EXTENSIONS TO BASIC
- Basic loader program
- Assembler Listings
- Main program
- A simple ‘double POKE’ routine: POKE * x,y
- Pokeing strings into memory: POKE n,”s”
- Memory dump: *L n
- Modified EDIT function: *E n
- An improved sound command: BEEP *a,b,c,d
- A faster and more complete catalogue: * CAT n
- Pseudo—random file handling: READ #S,N
- Adding data to a file: RESTORE #S
- Extending the RS—232 channel
- Extending Spectrum BASIC
- THE SHADOW ROM DISASSEMBLY
- The restart routines
- The control routine
- The syntax checking routines
- The RS—232 link routines
- The Network routines
- The Microdrive routines
- The ‘Hook code’ routines
- The Microdrive command routines
- The ‘not used’ routines
- APPENDIX
- Labels sorted by address value
- Labels sorted alphabetically
- ‘Shadow’ system variables
- Channels
- Bibliography
- Index to routines
- Shadow ROM issue 2
- How to tell which edition Interface 1 you have
- Basic loader program for edition 2 Shadow ROM
- Extended BASIC commands from assembler
- for edition 2 Shadow ROM
- What to do if you have an unknown ROM
- INTRODUCTION
- The Sinclair ZX Interface I adds enormously to the power of the ZX Spectrum, allowing it to send and receive data over \
- an RS—232 link, to use the Local Area Network, and to store information on the Microdrives. Equally impressive is its \
- ability to expand the BASIC provided with the computer, adding new and powerful commands. Much of this power is due to \
- the 8K monitor program which is housed in an 8K Read Only Memory in the Interface 1.
- This ROM, which is kept between memory adresses 0000H and 1FFFH is "paged" back and forth with the main ROM so that \
- both ROMs appear to occupy the same section of memory.
- This book provides a complete listing of this program, fully commented and explained, permitting you to use these \
- routines in your programs. In addition, many examples are given of how to expand the Spectrum's BASIC by using the \
- Interface 1 to define new commands.
- I feel that this book should be of interest to all users of the Interface 1. Those without experience in machine code \
- programming can use the new BASIC commands provided, whether or not they own an assembler. More ambitious programmers \
- will find numerous hints for the creation of the their own routines, and the algorithms controlling the Microdrive, \
- the RS—232 link, and the Local Area Network will be of interest to even the most expert programmer.
- I should like, finally, to thank Massimiliano, Carlo, Giovanna, Sylvia, and Mr. Alfred Milgrom (of Melbourne House \
- Ltd.). A special thanks must go to the entire staff of Sinclair Research Ltd.
- Gianluca Carri
- Florence, Italy,
- January 1985.
- USE OF HOOK CODES
- While the disassembly of the ROM given here will be a valuable aid to machine code programmers wishing to use the \
- Interface I, there is one problem: Sinclair Research have not used the same ROM in every Interface 1. There are two \
- different editions of the ROM. Each, of course, does the same job of running the Microdrives, the RS—232 interface, \
- and the Local Area Network, but there are a number of minor differences in the actual code contained in the ROMs. The \
- differences between the two editions are described in appendix 7.
- Does this mean that we can never rely on being able to write programs that can run on all machines? Far from it. \
- Sinclair Research have provided a way to access a number of the ROM routines in a way which can be guaranteed to work \
- on all machines. To do this, we use what are called hook codes. These consist of a RST 8 instruction followed by a \
- byte whose value depends on which hook code you are using. Their effect is to page the ROM in, call a routine in the \
- Interface 1's 'shadow ROM', then page the main ROM back in and return control to the users program. This provides \
- 'transparant' access to the Interface 1 — the user doesn't need to know anything about the ROM, only about the various \
- hook codes.
- The following example shows the use of hook code 20H (which tests to see if a key has been pressed) from machine code:
- ORG 7D00H ;32000 dec
- EXAMPLE RST 0008H ;hook code restart
- DEFB 20H ;check keypress
- RET
- END
- To do the same thing from BASIC:
- POKE 32000,207: POKE 32001,32: POKE 32002,201: RANDONISE USR 32000
- The hook codes available for your use are numbered from 1BH to 32H (27 to 50 decimal). The hook codes are all fully \
- described in the disassembly, from 1981H to 1B6DH. If you use the hook codes within your programs, instead of calling
- the shadow ROM subroutines, there will be no need to change your program if Sinclair make further changes to the ROM. \
- Otherwise you will need to update all the absolute references to the shadow ROM.
- In using hook codes, only the contents of the A register may be passed to the subroutines being called. The \
- subroutines do not preserve any registers, so be sure to save all of the main set of registers before you use any hook \
- codes. Some of the more complex routines corrupt HL', the return address to BASIC, so you may wish to preserve this.
- Although the individual hook codes are dealt with in detail in the disassembly, here is a brief summary of their \
- actions:
- 1BH - Accepts a character from the keyboard.
- 1CH - A character is output to stream 2, which is normally the upper part of the screen.
- 1DH - Accepts a byte of data from the RS—232 link.
- 1EH - Sends a byte of data to the RS—232 link.
- 1FH - A character is output to stream 3, which is normally the ZX printer.
- 20H - Tests for keypress.
- The next twelve hook codes refer to the Microdrives.
- 21H - Select drive. Can be used to turn any drive on, or all drives off.
- 22H - Open channel. Allows the user to create a microdrive channel.
- 23H - Close channel. The Microdrive channel is reclaimed.
- 24H - Delete file. Used to erase a named file from a Microdrive channel.
- 25H - Read sequential. Allows the user to fetch the 'next' record of a named file.
- 26H - Write record. Writes a new record onto the next free sector of a microdrive cartridge.
- 27H - Read random. Similar to 'read sequential', except that the record read need not be the next one in the file.
- 28H - Reads a record from a specified sector of tape.
- 29H - Reads the record from the next sector of tape that passes under the read head of the Microdrive.
- 2AH - Writes a record to a specified sector of tape.
- 2BH - Due to a programming error, this has the same effect as 'create channel' in the first issue ROM. This should be \
- corrected in later issues.
- 2CH - Reclaims the memory used by a Microdrive channel.
- The following four hook codes refer to the local area network.
- 2DH - Opens a network channel.
- 2EH - Closes a network channel.
- 2FH - Fetches a 'packet' of information from a network channel.
- 30H - Sends a packet over a network channel.
- 31H - Creates the new system variables used by the Interface 1. This happens when the system is powered up, and when \
- NEW is typed, but it also can be done manually.
- 32H - This routine is different from the other hook codes in that it can be used to call any routine in the shadow \
- ROM. The shadow ROM is paged in, the routine whose address is held in the system variable HD-11 (held at address \
- 5CEDH) is called, and the main ROM is paged back in.
- Another use for hook code 32H is paging in the Shadow ROM. If you want the Shadow ROM to sit in main memory, where the \
- main ROM normally is, and to be directly accessible to your program, use the following program fragment to page
- the Shadow ROM in:
- LD HL,LABEL
- LD (23789),HL
- RST 8
- DEFB 32H
- LABEL POP HL
- POP HL
- To page the main ROM back in, simply do CALL 0700H
- For more information about the hook codes and the ZX Interface 1, see the 'Spectrum Microdrive Book' by Dr. Ian Logan. \
- also published by Melbourne House.
- EXTENSIONS TO BASIC
- This section of the book shows how to add a number of new commands to the Spectrums BASIC. Those with no knowledge of \
- machine code, or simply no interest in it can simply type the routines that follow into their Spectrums, save them
- onto tape or Microdrive, and instantly have a more powerful BASIC. Machine code programmers will find the programs \
- valuable examples of how to use the Interface 1 ROM routines, and should be interested by the way in which new \
- commands are added to BASIC. A later section will explain how this is done.
- The extensions to BASIC consist of a number of machine code routines, each of which makes up a new BASIC command, \
- along with a main program which will prepare the computer to run the new commands.
- The new BASIC includes improvements to the POKE, CAT, and BEEP commands, a better version of EDIT, more versatile \
- file handling for the Microdrives, an extension to the RS—232 channel, and a useful memory dump command which will \
- list the contents of an area of memory, in both hexadecimal and ASCII form.
- Sinclair Research have released two different versions of the Interface 1. Each of the versions contains a slightly \
- different program in its ROM. The newer version of the ROM has corrected a number of errors contained in the previous \
- edition, as well as adding some new routines. Because new code has been added to
- the Shadow ROM at various points, many of the routines in the ROM are no longer located at the same address as before. \
- As the extensions to BASIC given in this book make use of many routines from the Shadow ROM, you will have to do \
- slightly
- different things to implement the BASIC extensions, depending on which edition of the Interface 1 you own.
- First of all you'll have to figure out which edition of the Interface you own. Instructions on how to do this are \
- given in Appendix 8 on page 155.
- If you find you have an edition 1 ROM in your Interface 1, you will find instructions on how to add the new commands \
- to Basic on page 11 for those who have an assembler, or on page 7 for those who don't have access to an assembler.
- If you have an edition 2 ROM, then turn to Appendix 10 on page 161 if you have an assembler, or Appendix 9 on page 157 \
- if you don't, for instructions on how to add the new BASIC commands to your Spectrum.
- Although there are only two editions of the Shadow ROM at the moment, there is some possibility that Sinclair Research \
- may release further editions of the Interface 1. Should you own one of these, it is likely that the extended BASIC
- commands given here will not work properly with it. If the extended BASIC commands do not work for you, and you \
- suspect that you might have a third edition or later Shadow ROM, turn to Appendix 11 on page 165 to find out how you \
- can implement the new commands.
- Basic loader program
- (For owners of Interface 1s equipped with the edition 1 ROM)
- If you do not have an Assembler, you may enter the routines into your Spectrum with the following BASIC loader program.
- Enter this program into your Spectrum.
- 1 CLEAR 63743
- 10 FOR A=63744 TO 65046 STEP 12
- 20 PRINT "ADDRESS:";A''
- 30 LET C=0
- 40 FOR B=l TO 12
- 50 LET Z=A+B-1: IF Z<=65046 THEN INPUT X: PRINT X: POKE Z,X: LET =C+X
- 60 NEXT B
- 70 PRINT '"CHECKSUM=";C
- 80 INPUT "THIS IS WROMG ? (Y/N) ";LINE Y$: IF CODE Y$=89 OR CODE Y$=l2l THEN PRINT "Retype from address ";A: PAUSE \
- 100: CLS: GO TO 20
- 90 IF CODE Y$<>78 AND CODE Y$<>l10 THEN GO TO 80
- 100 CLS: NEXT A
- 110 PRINT "SAVING THE PROGRAM"
- 120 SAVE *"M";1;"SHADP"CODE 63744,1303
- When you have finished typing this program into the Spectrum, you should 'RUN' it. You should then type, from the \
- listing on the next page, the 12 bytes from the address shown on the screen. When you have typed the first 12 bytes, a \
- 'checksum' should be displayed on the screen; if it matches with the one printed on the listing, at the right—hand \
- side of each line, then you have not made mistakes in typing the numbers, and you may enter "N" or "n" to continue \
- with the next line. If the checksums do not match, you must enter 'y' or 'Y', and then retype the whole line.
- When all numbers have been entered, the program will automatically be saved on Microdrive cartridge (there must be a \
- cartridge with at least 2K free into Microdrive 1). IF you wish to save the program on tape, line 120 of the listing \
- should be modified. When at later time you wish to use the routines, you have simply to place the cartridge into \
- Microdrive I, and then to enter the following direct commands:
- CLEAR 63743: LOAD *"M";1;"SHADP"CODE: RANDOMIZE USR 63744
- And the new commands should be available. Note that if you use NEW command, you must re—enter the command 'RANDOMIZE \
- USR 63744' to reinitialise the VECTOR system variable.
- 63744: 207 49 33 9 249 34 183 92 201 215 24 0 1296
- 63756: 254 244 202 45 249 254 42 202 114 249 254 215 2324
- 63768: 202 11 250 254 227 202 188 251 254 229 202 12 2282
- 63780: 252 254 224 202 175 252 195 240 1 215 32 0 2042
- 63792: 254 42 194 75 249 215 121 28 205 183 5 215 1786
- 63804: 153 30 197 215 153 30 197 225 193 113 35 112 1653
- 63816: 195 193 5 215 130 28 254 44 194 240 1 215 1714
- 63828: 32 0 215 140 28 205 183 5 215 241 43 197 1504
- 63840: 213 215 153 30 80 89 225 193 120 177 202 193 1890
- 63852: 5 237 176 195 193 5 215 32 0 254 207 202 1721
- 63864: 102 250 246 32 254 108 194 197 249 215 32 0 1879
- 63876: 215 130 28 205 183 5 215 153 30 96 105 124 1489
- 63888: 205 135 30 125 205 135 30 62 32 205 169 30 1363
- 63900: 229 6 6 197 126 205 158 30 35 16 249 193 1450
- 63912: 225 126 230 127 254 32 56 6 254 128 48 2 1488
- 63924: 24 2 62 32 205 169 30 35 16 235 62 13 885
- 63936: 205 169 30 24 202 254 101 194 240 1 215 32 1667
- 63948: 0 215 130 28 205 183 5 215 153 30 253 203 1620
- 63960: 12 126 202 240 1 120 230 192 194 240 1 237 1795
- 63972: 67 73 92 237 123 61 92 33 7 250 229 42 1306
- 63984: 61 92 229 33 127 16 229 237 115 61 92 253 1545
- 63996: 54 0 255 215 169 15 33 56 15 229 199 225 1465
- 64008: 195 180 18 215 32 0 254 42 194 240 1 215 1586
- 64020: 121 28 254 44 194 240 1 215 121 28 205 183 1634
- 64032: 5 215 148 30 245 215 148 30 167 40 54 79 1376
- 64044: 6 0 197 215 148 30 167 40 44 79 6 0 932
- 64056: 197 215 153 30 197 205 0 7 225 209 193 241 1872
- 64068: 229 245 197 229 213 205 181 3 209 225 193 241 2370
- 64080: 167 237 66 48 240 61 225 32 235 33 193 5 1542
- 64092: 34 237 92 207 50 253 54 0 0 239 215 32 1413
- 64104: 0 205 30 6 205 183 5 205 109 6 62 2 1018
- 64116: 215 1 22 205 232 15 221 126 25 205 247 23 1537
- 64128: 205 196 18 33 9 251 17 24 0 205 5 251 1214
- 64140: 205 65 19 32 239 33 9 251 203 78 32 232 1390
- 64152: 58 9 251 33 12 251 182 230 2 194 169 250 1641
- 64164: 205 254 18 24 215 58 13 251 183 40 209 58 1528
- 64176: 10 251 183 32 203 221 126 41 221 190 13 40 1531
- 64188: 22 205 33 251 205 0 251 221 126 13 183 194 1704
- 64200: 128 250 221 126 41 221 119 13 195 128 250 221 1913
- 64212: 229 175 205 247 23 205 0 251 221 229 225 17 2027
- 64224: 44 0 25 205 178 251 205 0 251 205 56 29 1449
- 64236: 123 203 63 215 40 45 215 227 45 205 0 251 1632
- 64248: 221 225 205 196 16 195 193 5 62 13 195 102 1628
- 64260: 29 229 195 173 24 0 0 0 0 0 0 0 650
- 64272: 0 0 0 0 0 0 0 0 0 0 0 0 0
- 64284: 0 0 0 0 0 33 140 92 54 255 33 13 620
- 64296: 251 205 178 251 62 32 205 102 29 58 9 251 1633
- 64308: 203 87 194 62 251 62 245 195 102 29 33 24 1487
- 64320: 251 126 183 202 99 251 254 3 202 157 251 61 2040
- 64332: 245 62 228 205 102 29 58 29 251 230 31 198 1668
- 64344: 96 205 102 29 241 200 62 36 195 102 29 33 1330
- 64356: 32 251 126 230 192 192 43 62 202 205 102 29 1668
- 64368: 94 35 86 235 17 16 39 205 143 251 17 232 1370
- 64380: 3 205 143 251 17 100 0 205 143 251 17 19 1345
- 64392: 0 205 143 251 17 1 0 62 255 60 183 237 1414
- 64404: 82 48 250 25 246 48 195 102 29 62 175 205 1467
- 64416: 102 29 35 229 35 35 205 112 251 62 44 205 1344
- 64428: 102 29 225 195 112 251 6 10 126 205 102 29 1392
- 64440: 35 16 249 201 215 32 0 254 35 194 240 1 1472
- 64452: 215 121 28 205 183 5 215 148 30 245 215 148 1758
- 64464: 30 254 16 210 99 6 215 1 22 221 42 81 1197
- 64476: 92 221 126 4 254 77 194 45 6 221 203 24 1467
- 64488: 70 194 50 17 241 221 119 13 221 126 25 205 1502
- 64500: 247 23 33 255 0 34 201 92 205 132 11 175 1414
- 64512: 221 119 11 221 119 12 205 247 23 195 193 5 1571
- 64524: 215 32 0 215 130 28 205 183 5 215 148 30 1406
- 64536: 254 16 210 99 6 215 1 22 221 42 81 92 1259
- 64548: 221 126 4 254 71 194 45 6 221 203 24 70 1445
- 64560: 194 2 9 221 126 25 205 247 23 33 255 0 1340
- 64572: 34 201 92 205 165 17 56 19 40 14 221 203 1267
- 64584: 67 78 49 11 221 126 41 221 119 13 24 3 964
- 64596: 205 254 18 205 18 19 32 227 219 239 230 1 1667
- 64608: 202 197 26 205 75 26 218 163 17 221 110 69 1529
- 64620: 221 102 70 221 117 11 221 116 12 221 203 24 1539
- 64632: 198 205 62 30 205 196 18 221 126 13 221 190 1685
- 64644: 41 32 245 62 230 211 239 1 104 1 205 250 1621
- 64656: 24 221 229 225 11 55 0 25 205 120 24 62 1207
- 64668: 238 211 239 205 254 18 221 126 68 221 119 13 1933
- 64680: 175 205 247 23 195 193 5 215 32 0 254 33 1577
- 64692: 40 1l 254 47 40 33 254 63 40 54 195 240 1271
- 64704: 1 215 121 28 205 183 5 215 148 30 167 202 1520
- 64716: 245 253 50 16 254 215 148 30 61 50 15 254 1591
- 64728: 195 193 5 215 121 28 205 183 5 215 148 30 1543
- 64740: 50 17 254 215 148 30 50 18 254 175 50 22 1283
- 64752: 254 195 193 5 215 32 0 215 130 28 205 183 1655
- 64764: 5 215 148 30 254 1 40 12 62 3 253 203 1226
- 64776: 124 142 205 24 23 195 193 5 62 3 215 30 1230
- 64788: 23 33 17 0 167 237 66 218 47 5 205 19 1037
- 64800: 11 213 33 5 0 25 17 53 253 115 35 114 874
- 64812: 62 3 50 216 92 209 195 74 11 254 165 210 1541
- 64824: 64 12 253 203 1 134 254 32 56 85 32 4 1130
- 64836: 253 203 1 198 245 62 1 50 19 254 241 205 1732
- 64848: 60 12 58 15 254 71 58 14 254 184 48 5 1033
- 64860: 60 50 14 254 201 205 105 253 175 50 19 254 1640
- 64872: 201 62 1 50 19 254 61 50 14 254 58 20 1044
- 64884: 254 167 196 90 12 58 21 254 167 196 90 12 1517
- 64896: 58 18 254 71 58 22 254 60 184 32 8 58 1077
- 64908: 17 254 167 196 90 12 175 50 22 254 201 254 1692
- 64920: 13 32 12 58 19 254 167 62 1 50 19 254 941
- 64932: 200 24 194 254 6 32 33 42 14 254 58 16 1127
- 64944: 254 71 14 0 12 44 125 188 48 167 144 40 1107
- 64956: 4 48 251 24 243 197 62 32 205 53 253 193 1565
- 64968: 13 32 246 201 254 23 192 17 221 253 42 81 1575
- 64980: 92 1 5 0 9 115 35 114 201 50 15 92 729
- 64992: 17 229 253 24 237 17 53 253 205 210 253 58 1809
- 65004: 15 92 71 58 15 254 184 48 5 253 54 0 1049
- 65016: 10 239 58 14 254 144 200 48 5 237 68 79 1356
- 65028: 24 187 197 205 105 253 193 72 24 179 0 80 1519
- 65040: 20 12 60 1 13 10 0 116
- Assembler Listings
- (For Interface 1s equipped with the edition 1 Shadow ROM.)
- The following is a complete, fully commented assembler listing of the machine code programs which make the new BASIC \
- commands possible. These consist of a main program which sets up the new system variables needed by the Interface 1, \
- and a number of small programs, one of which is used by each new command. The equate statements used by these routines \
- are included in a seperate table at the end of the listings. To add the new BASIC commands to your Spectrum, enter the \
- assembler program on the following pages, as well as the table of EQU statements that follows it, into your assembler, \
- assemble it, and save the resulting machine code on tape or microdrive. When you wish to use the new BASIC commands, \
- load the machine code file into your Spectrum at 63744 (F900 Hex.), and do
- RANDOMIZE USR 63744
- to make the new commands available.
- All readers of this book should at least glance through this section, as interspersed with the listings of the new \
- commands are examples of their use, and explanations of their functions. A brief explanation of the manner in which \
- new commands are added to BASIC is given later in the book, and it may prove useful in understanding what is being \
- done in this section.
- Main program
- The program starts at the address F900 hex (63744 decimal), and is located above RAMTOP. When it is used for the first \
- time, you must use a command
- RANDOMIZE USR 63744
- to initialise the system variable VECTOR. You must do this whenever the initial VECTOR contents are defaulted back to \
- ERR_6 (01F0). This happens when you use a NEW command to delete the BASIC program from the memory.
- ORG 0F900H
- ;
- MAINPG EQU $
- ;
- RST ERROR_1 ;Create new system variables if
- DEFB HOOK31 ;nonexistent.
- LD HL,STSYN ;Store start address of new routine
- LD (VECTOR),HL ;into VECTOR.
- RET
- Note that initially 'hook code' +31 is used to create the new system variables if they do not already exist. Failure \
- to do so in your programs will cause a probable crash when you try to POKE something into the location where the 'new' \
- system variables should be.
- The address of the syntax module routine STSYN is then stored into VECTOR. This causes the routine STSYN to be used \
- whenever a command fails the syntax of the main ROM interpreter, and then that of the shadow ROM interpreter. The \
- system variable CH_ADD will point to the first character of the command that produces the error.
- The routine STSYN is listed below.
- STSYN RST CALBAS
- DEFW GET_CHAR ;Fetch command code.
- CP POKE ;Jump to the appropriate routine,
- JP Z,PGM1 ;depending on the command code.
- CP "*"
- JP Z,PGM3
- CP BEEP
- JP Z,PGM5
- CP READ
- JP Z,PGM7
- CP RESTORE
- JP Z,PGM8
- CP LPRINT
- JP Z,PGM9
- JP ERR_6 ;Give an error if none of these.
- Note that the 'main' ROM restart GET_CHAR is used to fetch the command code into the A register; then a jump is made \
- to the required syntax module routine. If the command code is still wrong, the error is confirmed by jumping to ERR_6.
- A simple 'double POKE' routine: Poke * x,y
- The first implemented 'new' command is a 'double POKE' command. That is, a POKE command that uses word operands (16 \
- bits) instead of byte operands (8 bits). The syntax is 'POKE *x,y•, where 'a' is the address in the range 0..65535, \
- and 'y' is the value to be poked at location 'a', again in the range 0..65535. Note that the standard Intel format is \
- used, i.e. the low byte goes before the high byte in memory. You may use the new POKE command, for example, to store \
- values into two—byte system variables:
- POKE *23675,32000
- is a rather straightforward way of changing to '32000' the contents of the UDG system variable, as compared with the \
- usual:
- POKE 23675,32000~256*INT (32000/256)
- POKE 23676,INT (32000/256)
- The machine code program used to do this is very simple:
- PGM1 RST CALBAS
- DEFW NEXT_CHAR ;Advance CH_ADD.
- CP "*" ;Jump if it is not a POKE *x,y command.
- JP NZ,PGM2
- RST CALBAS
- DEFW NEXT_2NUM ;Evaluate the two parameters.
- CALL ST_END ;Confirm end of statement.
- RST CALBAS
- DEFW FIND_INT2 ;Fetch number to be POKEd.
- PUSH BC ;Save it.
- RST CALBAS
- DEFW FIND_INT2 ;Fetch address.
- PUSH BC ;Move it into HL.
- POP HL
- POP BC ;Restore value.
- LD (HL),C ;POKE the low byte.
- INC HL
- LD (HL),B ;POKE the high byte.
- JP END1 ;Finished.
- Initially the syntax of the new command is checked; CH_ADD is advanced to the character that follows the token 'POKE', \
- and if the character '*' is not present, a jump is made to the command for pokeing strings into memory (because the \
- current command is not POKE *x,y).
- Assuming that our current command is POKE *x,y, the 'main' ROM routine NEXT_2NUM is then used to evaluate two numeric \
- expressions (separated by a comma), following the character pointed by CH_ADD. An error will occur if the
- expressions have incorrect syntax. Otherwise the syntax is correct and the call to ST_END returns to the 'main' ROM \
- during syntax checking. During runtime the execution continues, and the main ROM routine FIND_INT2 is used to fetch \
- the values from the calculator stack. After the POKE * has been done, control is returned to the main ROM interpreter \
- by jumping to END1.
- Pokeing strings into memory: POKE n,"s"
- This command makes it possible to POKE a string in memory, starting from the address 'n'. For example, the statement:
- POKE 30000, "FRED BLOGGS"
- Will POKE the ASCII values of the characters in the string "FRED BLOGGS", starting from the address 30000. You may \
- check this by reading back the values with PEEK:
- FOR A=30000 TO 30010: PRINT CHR$ PEEK A;: NEXT A
- Note that the routine fails the syntax of the interpreter by using a different parameter type (i.e. a string instead \
- of a number), while the previous routine used a '*' character following the command code.
- PGM2 RST CALBAS ;Evaluate the address.
- DEFW EXPT_1NUM
- CP COMMA ;A separator must be present.
- JP NZ,ERR_6 ;Report the error if it is not present.
- RST CALBAS ;Advance CH_ADD.
- DEFW NEXT_CHAR
- RST CALBAS ;Evaluate string expression.
- DEFW EXPT_EXP
- CALL ST_END ;Confirm end of statement,
- RST CALBAS ;Fetch string parameters.
- DEFW STK_FETCH
- PUSH BC ;Save 'length' and 'start'.
- PUSH DE
- RST CALBAS ;Fetch address.
- DEFW FIND_INT2
- LD D,B ;Move address into DE.
- LD E,C
- POP HL ;Restore string 'start' and 'length'.
- POP BC
- LD A,B ;Exit with null string.
- OR C
- JP Z,END1
- LDIR ;The actual POKE.
- JP END1 ;Finished.
- The routine is entered from the POKE *x,y routine with CH_ADD pointing to the character following the 'POKE' token. \
- The main ROM routines EXPT_ 1NUM and EXPT_EXP are then used, respectively to evaluate a numeric and a string
- expression. A comma must be placed between them as separator. During runtime, the main ROM routines STK_FETCH and \
- FIND_INT2 are used to fetch the string parameters, and the value of the numeric expression. No action is taken iF the
- string has null length.
- Memorydump: *L n
- This routine creates a new command '*L n' that lists the memory contents, starting from the address n, in both \
- hexadecimal and ASCII. Unprintable ASCII codes ate printed as spaces. For example, the following statement:
- *L 31920
- Will list the contents of the memory starting from address 31920. Note that when dumping memory at addresses lower \
- than 16384, the 'shadow' ROM code is shown. Try for example to dump from the address 695, that is the start of the \
- 'shadow
- ROM report messages table. The result will be as follows:
- 02B7 00 50 72 6F 67 72 Progr
- 02BD 61 6D 20 66 69 6E am fin
- 02C3 69 73 68 65 64 01 ished
- 02C9 41 6F 6E 73 65 6E Nonsen
- 02CF 73 65 20 69 6E 20 se in
- 02D5 42 41 53 49 43 02 BASIC
- ....
- ....
- The routine follows:
- PGM3 RST CALBAS ;Advance CH_ADD.
- DEFW NEXT_CHAR ;Jump if the command is CAT.
- CP CAT
- JP Z,PGM6
- OR 20H ;Make the letter lower case.
- CP "l" ;Jump if this is not an "*L" command.
- JP NZ,PGM4
- RST CALBAS
- DEFW NEXT_CHAR ;Advance CH_ADD.
- RST CALBAS
- DEFW EXPT_1NUM ;Evaluate start address.
- CALL ST_END ;Confirm end of statement.
- RST CALBAS ;Fetch start address.
- DEFW FIND_INT2
- LD H,B ;Move it into HL.
- LD L,C
- AGAIN LD A,H ;Display high byte of address in hex.
- CALL DISP_HEX
- LD A,L ;Display low byte.
- CALL DISP_HEX
- LD A,SPACE ;Print a space.
- CALL DISP_CH
- PUSH HL ;Save current address.
- LD B,6 ;Display 6 bytes.
- PUSH BC ;Save counter for later,
- L_LOOP LD A,(HL) ;Fetch a byte.
- CALL DISPHEX2 ;Display it in hex.
- INC HL ;Examine each byte in turn.
- DJNZ L_LOOP
- POP BC ;Restore counter and address.
- POP HL
- C_LOOP LD A,(HL) ;Fetch a byte.
- AND 7FH ;Clear bit 7.
- CP SPACE ;Reject codes lower than SPACE.
- JR C,REJECT
- CP 80H ;Reject codes greater than 7FH.
- JR NC,REJECT
- JR ACCEPT
- REJECT LD A,SPACE ;Replace invalid codes with 'space'
- ;code.
- ACCEPT CALL DISP_CH ;Print the character.
- INC HL ;Advance pointer.
- DJNZ C_LOOP ;Continue the toop.
- LD A,CR ;Finally print a carriage return.
- CALL DISP_CH
- JR AGAIN ;Jump back.
- This time, the interpreter syntax is failed by starting the command with a non—standard character, namely, a '*'. The \
- letter 'L' (for 'L'ist) maybe either upper or lower case.
- Note that the shadow ROM routines DISP_HEX, DISP_HEX2 and DISP_CH are used to print characters onto stream 2 (the \
- screen). Note also that the command will never end during runtime. This, however, will not result in an endless loop, \
- as you may simply press BREAK when the 'scroll' message is displayed on the screen, to stop the listing. The output \
- may be directed to a device other than the screen by first using an OPEN command. i.e. OPEN #2,"T" will direct the \
- output to the RS232 "T" channel.
- The main ROM routines EXPT_1NUM and FIND_INT2 are used to evaluate and fetch the given parameter 'n'.
- Modified EDIT function: *E n
- The normal 'EDIT' function is not very well implemented; if you wish, for example, to EDIT line 4385 of your program, \
- you must first make the line 'current' by using something like LIST 4385, and then (after having pressed BREAK to stop \
- the listing) press the EDIT key.
- By using this routine, you may type simply '*E 4385' to do the same thing. The listing of the routine follows:
- PGM4 CP "e" ;Error if it is not the '*E' command.
- JP NZ,ERR_6
- RST CALBAS ;Advance CH_ADD.
- DEFW NEXT_CHAR
- RST CALBAS ;Evaluate line number.
- DEFW EXPT_1NUM
- CALL ST_END ;Confirm end of statement.
- RST CALBAS ;Fetch line number.
- DEFW FIND_INT2
- BIT 7,(IY+PPC_HI) ;Accept only as 'direct' command.
- JP Z,ERR_6
- LD A,B ;Error with line number out of range.
- AND 0C0H
- JP NZ,ERR_6
- LD (E_PPC),BC ;Make this line 'current'.
- LD SP,(ERR SP) ;Clear machine stack.
- LD HL,ENDED ;Final return address.
- PUSH HL
- LD HL,(ERR_SP) ;Save current error address.
- PUSH HL
- LD HL,ED_ERROR ;The new error address.
- PUSH HL
- LD (ERR_SP),SP
- LD (IY+ERR_NR),0FFH ;Clear the error.
- RST CALBAS
- DEFW ED_EDIT ;Copies the line into the editing area.
- LD HL,ED_LOOP ;Return to 'EDitor LOOP', and to ENDED
- PUSH HL ;below when finished.
- RST MAIN_ROM
- ;
- ;NOTE: Main ROM in use.
- ;
- ENDED POP HL ;Remove +l303 from the stack.
- JP 12B4H ;Jump back to the main execution loop.
- Note that the command is rejected at runtime (BIT 7,PPC_HI) if it is not a 'direct' one: this is because an EDIT \
- command used within a program does not make sense.
- The command is also rejected if you specify wrong line numbers. If you use a nonexistent line number, the next \
- existent number is used.
- The routine enters the main ROM 'EDITOR' subroutine, after having copied the line into the editing area, and returns \
- to the main execution loop when finished.
- An improved sound command: BEEP *a,b,c,d
- The standard 'BEEP x,y' command is very limited: it will only make sounds of a constant pitch. This routine creates a \
- new 'BEEP' command that accepts four parameters, giving an endless range of possible sound effects.
- The syntax of the new command is 'BEEP * a,b,c,d', where 'a' and 'b' are the values that the main ROM 'BEEPER' \
- subroutine accepts as 'pitch' and 'length', 'c' is a 'step' value that will be subtracted from 'a' until it reaches \
- zero, and 'd' is a 'repeat' value that defines how many times the whole sound must be made. Try the following \
- statement:
- BEEP * 100,255,10,1
- The following BASIC program will generate a wide range of sounds:
- 10 LET a=RND*1000+10
- 20 LET b=RND*6+1
- 30 LET c=RND*50+1
- 40 LET d=RND*3+1
- 50 BEEP *a,b,c,d
- 60 GO TO 10
- The routine is listed below:
- PGM5 RST CALBAS ;Advance CH_ADD.
- DEFW NEXT_CHAR
- CP "*" ;The '*' must be present.
- JP NZ,ERR_6
- RST CALBAS ;Evaluste 'a','b'
- DEFW NEXT_2NUM
- CP COMMA ;A separator must be found after 'b'.
- JP NZ,ERR_6
- RST CALBAS ;Evaluate 'c','d'.
- DEFW NEXT_2NUM
- CALL ST_END ;Confirm end of statement.
- RST CALBAS ;Fetch 'd'.
- DEFW FND_INTl
- PUSH AF ;Save it.
- RST CALBAS ;Fetch 'c'.
- DEFW FND_INTl
- AND A ;Give an error if c=0.
- JR Z,RANGE
- LD C,A ;Otherwise move it into BC.
- LD B,0
- PUSH BC ;Save it.
- RST CALBAS ;Fetch 'b'.
- DEFW FND_INT1
- AND A ;Give an error if b=0.
- JR Z,RANGE
- LD C,A ;Move it into BC.
- LD B,0
- PUSH BC ;Save 'b' briefly.
- RST CALBAS ;Fetch 'a'.
- DEFW FIND_INT2
- PUSH BC ;Save it temporarily.
- CALL UNPAGE ;Use main ROM.
- POP HL ;Restore 'a', 'b', 'c' and 'd' values.
- POP DE
- POP BC
- POP AF
- LOOP2 PUSH HL ;Save 'a' for next pass.
- LOOP1 PUSH AF ;Save values.
- PUSH BC
- PUSH HL
- PUSH DE
- CALL BEEPER ;Emit a sound.
- POP DE ;Restore values.
- POP HL
- POP BC
- POP AF
- AND A
- SBC HL,BC ;Subtract 'step' from 'a'.
- JR NC,LOOP1 ;Continue while subtraction possible.
- DEC A ;Decrease 'd'
- POP HL ;Restore 'a' for repetition.
- JR NZ,L00P2 ;Repeat the sound until d=0.
- LD HL,END1 ;Note how the return is made to the
- LD (HD_11),HL ;shadow ROM.
- RST ERROR_1
- DEFB HOOK32
- ;
- RANGE LD (IY+ERR_NR),0 ;Call the error handling routine.
- RST ROMERR
- Note that 'b', 'c' and 'd' must be in the range l..255, ('d' may be set to 8, but this will give the same effect that \
- you would expect from a value of 256.)
- Be careful that you choose the right length for your sound, as the the BREAK key will not work in the middle of a sound.
- If you have some difficulty in choosing the correct 'a' and 'b' values, you may calculate them as shown below:
- a = 437500/frequency-30.l25
- b = frequency * time
- (frequency=Hz, time=sec.)
- You may also use the following BASIC program which calculates the values for A and B, starting from the 'x', 'y' \
- values used in a normal BEEP command. For example, the sound obtained with BEEP 0.01,10 requires '908' and '4' as A \
- and B
- values.
- 10 DATA 261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392, 415.3, 440, 466.16, 493.88
- 20 INPUT "TIME (SEC.) ? ";t
- 30 INPUT "PITCH ? ";p
- 40 LET i=INT p: LET pi=p-i
- 50 LET pk=(pi*.0577622606)+1
- 60 LET a=i+60: LET b=-6
- 70 LET b=b+1: LET a~a-12
- 80 IF SGN a()-1 THEN GO TO 70
- 90 LET a=a+l2
- 100 RESTORE: FOR x=0 TO a: READ c: NEXT x
- 110 LET f=(pk*c)*2-b: IF f*t=0 THEN PRINT "ERROR": STOP
- 120 PRINT "A=";INT (437500/f-30.125)'"B=";INT (f*t)
- A faster and more complete catalogue:* CAT n
- After some 'general purpose' commands come some more complicated routines that use the new Interface's devices. This \
- routine adds a new command '* CAT n' that gives a full catalogue of a cartridge held in the microdrive 'n'.
- The command runs about 2—3 seconds faster than the standard 'CAT n' command, does not limit the output to 59 names, \
- and provides information on the nature of the file, its length, etc., that is not given when the standard 'CAT' \
- command is used.
- Since the names are printed as they are found on the cartridge, the list is not alphabetically ordered.
- Along with each filename the following information will appear:
- 'PRINT' If it is a PRINT—type file.
- 'CODE sssss,nnnnn' If it is a 'bytes' file; 'sss' and 'nnn' are respectively
- the start address and the length of the file.
- 'DATA x' If it is a numeric array named 'x'.
- 'DATA x$' If it is a string array named 'x$'
- 'LINE nnnnn' If it is a BASIC program with autostart at line 'nnn'.
- If nothing is printed after the filename, then the file is a normal BASIC program saved without the autostart.
- The routine is listed below.
- PGM6 RST CALBAS ;Advance CH_ADD.
- DEFW NEXT_CHAR
- CALL EXPT_NUM ;Evaluate drive number.
- CALL CHECK_M_2 ;Check range of drive number.
- CALL ST_END ;Confirm end of statement.
- LD A,2 ;Use stream 2 (screen).
- RST CALBAS
- DEFW CHAN_OPEN
- CALL SET_T_MCH ;Create a temporary "m" channel.
- LD A,(IX+CHDRIV) ;Turn on drive motor.
- CALL SEL_DRIVE
- CATLOOP CALL GET_M_HD02 ;Get a header.
- LD HL,RDESC ;And a record descriptor from the address
- LD DE,18H ;RDESC.
- CALL GETD
- CALL CHKS_HD R ;Repeat until the checksum is correct.
- JR NZ,CATLOOP
- LD HL,RDESC ;Repeat also if loaded wrong block type
- BIT 0,(HL) ;(header).
- JR NZ,CATLOOP
- LD A,(RDESC) ;Jump forward with 'not free' sectors.
- LD HL,RDESC+3
- OR (HL)
- AND 2
- JP NZ,PRI_NA
- CALL RES_B_MAP ;Mark 'free' sectors.
- JR CATLOOP
- ;
- PRI_NA LD A,(RDESC+4) ;Ignore names starting with CHR$ 0.
- OR A
- JR Z,CATLOOP
- LD A,(RDESC+1) ;Ignore other than first records.
- OR A
- JR NZ,CATLOOP
- LD A,(IX+HDNUMB) ;Jump forward when the whole tape has
- CP (IX+CHREC) ;been examined.
- JR Z,ENDCAT
- CALL OUTNAM ;Examine current record.
- CALL PRCR ;Print a carriage return.
- LD A,(IX+CHREC) ;Jump unless first time (CHREC=0).
- OR A
- JP NZ,CATLOOP
- LD A,(IX+HDNUMB) ;Store current sector number (to
- LD (IX+CHREC),A ldetect when the whole tape has been
- JP CATLOOP ;examined).
- ;
- ENDCAT PUSH IX ;Save channel start address.
- XOR A ;Turn off drive motors.
- CALL SEL_DRIVE
- CALL PRCR ;Leave a blank line.
- PUSH IX ;Make HL point to HDNANE.
- POP HL
- LD DE,2CH
- ADD HL,DE
- CALL PRNANE ;Print cartridge name.
- CALL PRCR ;Print a carriage return.
- CALL FREESECT ;Fetch number of 'free' sectors.
- LD A,E
- SRL A ;A holds the number of Kbytes left.
- RST CALBAS ;Store this number on calculator stack.
- DEFW STACK_A
- RST CALBAS ;Print the number on the screen.
- DEFW PRINT_FP
- CALL PRCR ;Final carriage return.
- POP IX ;Restore channel start address.
- CALL DEL_M_BUF ;Reclaim the channel.
- JP END1 ;Finished.
- ;
- PRCR LD A,CR ;Print a carriage return.
- JP PRCHAR
- ;
- GETD PUSH HL ;Save start address.
- JP GT_M_BLK ;Fetch descriptor and header information.
- ;
- RDESC DEFB l8H ;Space to store record descriptor.
- ;
- OUTNAM LD HL,SCR_CT ;Suppresa scrolling.
- LD (HL),0FFH
- LD HL,RDESC+4 ;Print record name.
- CALL PRNAME
- LD A,SPACE ;Follow it with a space.
- CALL PRCHAR
- LD A,(RDESC) ;This is 'RECFLG'.
- BIT 2,A ;Jump if this is not a
- JP NZ,NOTPRINT ;'PRINT—type' file.
- LD A,PRINT ;Otherwise print the keyword 'PRINT'.
- JP PRCHAR
- ;
- LD A,(HL)
- OR A ;Jump with type=0 (program files).
- JP Z,PROG
- CP 3 ;Jump with type=3 (bytes).
- JP Z,BYTES
- DEC A ;Save zero flag (set with numeric
- PUSH AF ;arrays).
- LD A,DATA ;Print the keyword DATA.
- CALL PRCHAR
- LD A,(RDESC+20) ;Fetch array name.
- AND 1FH ;Clear bit 5,6,7.
- ADD A,60H ;Obtain an ASCII code.
- CALL PRCHAR ;Print array name.
- POP AF ;Return with numeric arrays.
- RET Z
- LD A,"$" ;But print '$' with string arrays.
- JP PRCHAR
- ;
- PROG LD HL,RDESC+23 ;Fetch high byte of autostart line no.
- LD A,(HL)
- AND 0C0H ;Return if no autostart was specified.
- RET NZ
- DEC HL ;Point to the low byte.
- LD A,LINE ;Print the keyword LINE, and then
- CALL PRCHAR ;the line number:
- ;
- FPRINT LD E,(HL) ;Fetch entry indirectly.
- INC HL
- LD D,(HL)
- EX DE,HL ;Move value into DE.
- ;
- PRNUM LD DE,10000 ;Print first digit.
- CALL PRDIG
- LD DE,1000 ;Print second digit.
- CALL PRDIG
- LD DE,100 ;Print third digit.
- CALL PRDIG
- LD DE,10 ;Print fourth digit.
- CALL PRDIG
- LD DE,1 ;Print last digit.
- PRDIG LD A,-1 ;Counter.
- OUTD INC A ;Increment the counter.
- OR A ;Clear carry flag.
- SBC HL,DE ;'Trial subtraction'.
- JR NC,OUTD ;Continue until borrowing found.
- ADD HL,DE ;Balance last SBC.
- OR 30H ;Make the counter an ASCII character
- JP PRCHAR ;and print it.
- ;
- BYTES LD A,CODE ;Print the keyword CODE.
- CALL PRCHAR
- INC HL ;Save pointer to 'length'.
- PUSH HL
- INC HL
- INC HL
- CALL FPRINT ;Print the 'start'.
- LD A,COMMA ;Print a comma.
- CALL PRCHAR
- POP HL ;Finally print the 'length'.
- JP FPRINT
- ;
- PRNAME LD B,10 ;Counts ten characters.
- PRLOOP LD A,(HL) ;Fetch character,
- CALL PRCHAR ;Print it.
- INC HL ;Advance the pointer.
- DJNZ PRLOOP ;Loop for the whole name.
- RET
- The routine can be divided into eleven different sections:
- 1. A 'temporary "m" channel' and map is created in the CHANS area.
- 2. The required Microdrive is turned on.
- 3. The current sector number is stored into CHREC.
- 4. A 'header' is loaded from the cartridge into the "m" channel header area.
- 5. The 'record descriptor' and the 'header informations' are loaded into the RDESC area.
- 6. If the 'header' indicates 'free' sector, the appropriate map bit is reset and the program loops back to step (4)
- 7. The filename and the various information are taken from the RDESC area and printed on the screen.
- 8. The program continues looping back to (4) until the whole tape has been examined; this is done by comparing the \
- current sector number against CHREC one.
- 9. The cartridge name is taken from HDNAME and printed.
- 10. The number of 'free sectors' is used to print the number of Kbytes left in the cartridge.
- 11. The Microdrive motor is turned off, and the channel is reclaimed.
- Names starting with CHR$ 18 are not printed; records other than 'first' ones are not examined, so as to avoid the \
- printing of a filename more than once.
- Note that the form *CAT #S;N is not supported, because there is not sufficient time to send the information fetched to \
- a channel other than the screen, before the next tape sector is due to be examminined. If you wish to direct the \
- catalogue to a printer, you must use first a command such as:
- OPEN #2;"m";d;"CAT"
- and then use the *CAT n command. Finally 'CLOSE #2' will send the catalogue to the Microdrive. It can then be printed \
- with either:
- MOVE "m";d;"CAT" TO #3 (with the ZX printer)
- MOVE "m";d;"CAT" TO "b" (with RS232 printers)
- The catalogue can then be erased with ERASE "m";n;"CAT" (where 'n' is the drive number).
- In this case, you must take care that the output of the catalogue will not require more than 512 characters to be \
- printed (otherwise unpredictable results may occur when the Spectrum tries to send the record to the Microdrive while \
- the CAT command is operative). This can be done by making sure that there are fewer than 20 files on the cartridge.
- Note that to fail the syntax of the interpreter, the command begins with a '*' character; the command may not begin \
- with a 'new' command token, such as CAT, SAVE, ERASE, CLS, etc.
- Pseudo-random file handling: READ #S,N
- This command will permit a 'pseudo—random' handling of Microdrive files. When READ #S,N is executed, the 'read' \
- Microdrive channel attached to the stream 'S' is used, and record 'n' of that file is loaded into the channel buffer.
- Since the Microdtive system splits the main 'PRINT—type' files into records 512 bytes long, you may write items with \
- 'length=512', thereby having each record contain a single item, and then read back that item with the READ #S,N \
- command.
- Such an application is shown by using the following BASIC program. Each item is made by 8 elements (length=63 \
- characters + carriage return) of an array, exactly 512 bytes.
- Without the READ #S,N command you have to read sequentially all items before reaching the desired one.
- 10 DIM a$(24,63)
- 20 REM Some data for the file
- 30 DATA "THE MICRODRIVES", "give you fast access to a large memory.", "", "Each Microdrive can hold up to 100 Kbytes \
- on a single", "removable cartridge.", "Note that the Microdrive nearest the computer is always known as", "Microdrive \
- 1, and the next along is Microdrive 2, and so on.", "There is also a light on the front of each Microdrive."
- 40 DATA "THE CARTRIDGES", "come in a protective box; and should always be kept in their", "box when not in use.", \
- "But remember...", "Never take the cartridge out of the Microdrive while the light", "is on.", "Never switch the power \
- on or of while a cartridge is in the", "Microdrive."
- 50 DATA "THE NETWORK", "enables you and your friends to play computer games together", "and to send each other \
- programs and data.", "This means that only one of you need ever type in a program.", "Using the lead supplied with \
- each Interface you can link up", "as few as two and as many as 64 Spectrum computers."
- 60 OPEN #4;"M";1;"FILE"
- 70 FOR a=l TO 24: READ a$(a): NEXT a
- 80 CLOSE #4
- 90 CLEAR: REM The file has been cleared.
- 100 OPEN #4;"M";1;"FILE"
- 110 CLS: PRINT "Press a key for your choice: "''"0. MICRODRIVES"''"l. CARTRIDGES"''"2. NETWORK"''"3. STOP"
- 120 PAUSE 0: LET a$=INKEY$; IF a$<"0" OR a$>"3" THEN GO TO 110
- 130 IF a$="3" THEN CLOSE #4: STOP
- 140 READ #4,VAL a$
- 150 CLS: FOR a=1 TO 8: INPUT #4;a$: PRINT a$: NEXT a
- 160 PAUSE 0: GO TO 110
- If the stream(s) specified in the command is not opened, the error "invalid stream" will occur. "Invalid device \
- expression" will occur if the stream is not attached to an "m" channel; "Reading a 'write' file" will occur if the \
- channel is opened for writing.
- The cartridge is simply searched for the 'n'th record of the file 'n' being in range 0..255), then it is loaded and \
- CHBYTE cleared so as to direct INKEY$ and INPUT commands to the first byte loaded.
- If the record is not found, or if any reading error occurs, the error 'File not found' will be reported. The listing \
- of the routine follows.
- PGM7 RST CALBAS ;Advance CH_ADD.
- DEFW NEXT_CHAR
- CP "#" ;A hash sign must be present
- JP NZ,ERR_6 ;after READ.
- RST CALBAS ;Evaluate 's','n'
- DEFW NEXT_2NUM
- CALL ST_END ;Confirm end of statement.
- RST CALBAS ;Fetch 'n'.
- DEFW FND_INT1
- PUSH AF ;Save it for later.
- RST CALBAS ;Fetch 's'.
- DEFW FND_INT1
- CP 10H ;Give an error if 's' is greater than 15
- JP NC,NREPORT-2
- RST CALBAS
- DEFW CHAN_OPEN ;Use this stream.
- LD IX,(CURCHL) ;Fetch channel start address.
- LD A,(IX+4) ;Fetch channel specifier.
- CP "M" ;Error if not an "M" channel.
- JP NZ,NREPORT—3
- BIT 0,(IX+CHFLAG) ;Error if the file is opened for
- JP NZ,RWF—ERR ;writlng.
- POP AF ;Store record number into CHREC.
- LD (IX+CHREC),A
- LD A,(IX+CHDRIV) ;The drive motor is turned on.
- CALL SEL_DRIVE
- LD HL,0FFH ;Counts 255 sectors.
- LD (SECTOR),HL
- CALL GET_R_LP ;Fetch record.
- XOR A ;C1ear CHBYTE.
- LD (IX,CHBYTE),A
- LD (IX+CHBYTE+1),A
- CALL SEL_DRIVE ;Switch off drive motor.
- JP END1 ;Finished.
- Adding data to a file: RESTORE #S
- Normally, if you try to write data onto a Microdrive file that has previously been CLOSEd, the error 'Writing to a \
- 'read' file' will occur. This makes the operation of extending a file with more data difficult, as one has to create a \
- new file, copy into it the 'old' one and the 'new' data, and then erase the 'old' file. This is not easy, and is a \
- very slow process.
- This command will convert the 'read' file attached to the stream 's' back to a 'write' file, thus permiting the \
- addition of more data. When you have finished adding data, you may CLOSE the stream that returns a 'read' file. You \
- may use RESTORE #S again to convert it into a 'write' file if you wish.
- The following BASIC program will demonstrate this.
- 5 PRINT "CREATING THE FILE"
- 10 OPEN #4;"M";1;"NUMBERS"
- 20 FOR N=1 TO 10
- 30 PRINT #4;N'N*N
- 40 NEXT N
- 50 CLOSE #4
- 60 PRINT '"READING THE FILE"
- 70 OPEN #4;"M";l;'NUMBERS"
- 80 PRINT
- 90 FOR B=1 TO 10
- 100 INPUT #4;M;N
- 110 PRINT "THE SQUARE OF ";M;" IS ";N
- 120 NEXT B
- 130 PRINT '"EXTENDING THE FILE"
- 140 RESTORE #4
- 150 FOR N=11 TO 20
- 160 PRINT #4;N'N*N
- 170 NEXT N
- 180 CLOSE #4
- 190 PRINT '"READING EXTENDED FILE"
- 200 OPEN #4;"M";1;"NUMBERS"
- 210 PRINT
- 220 FOR B=l TO 20
- 230 INPUT #4;M;N
- 240 PRINT "THE SQUARE OF ";M;" IS ";N
- 250 NEXT B
- 260 CLOSE #4
- The routine is as folllows:
- PGM8 RST CALBAS ;Advance CH_ADD.
- DEFW NEXT CHAR
- RST CALBAS
- DEFW EXPT_1NUM ;Evaluate stream number.
- CALL ST_END ;Confirm end of statement.
- RST CALBAS ;Fetch stream number.
- DEFW FND_INT1
- CP 10H ;Reject stream number > 15.
- JP NC,NREPORT-2
- RST CALBAS ;Use this stream.
- DEFW CHAN_OPEN
- LD IX,(CURCHL) ;Fetch channel start address.
- LD A,(IX+4) ;Fetch channel specifier.
- CP "M" ;Error if not an "m" channel.
- JP NZ,NREPORT—3
- BIT 0,(IX+CHFLAG) ;Error also with 'write' files.
- JP NZ,NREPORT—N
- LD A,(IX+CHDRIV) ;Turn on drive motor.
- CALL SEL_DRIVE
- LD HL,0FFH ;Counts through 255 sectors.
- LD (SECTOR),HL
- LOOP CALL G_HD_R ;Fetch header and data block.
- JR C,NXTS ;Jump with any error.
- JR Z,RESBIT ;Jump with 'free' sectors.
- BIT 1,(IX+RECFLG) ;Jump if this is not the last record in
- JR Z,NXTS ;the file.
- LD A,(IX+HDNUMB) ;Otherwise fetch sector number to CHREC.
- LD (IX+CHREC),A
- JR NXTS
- RESBIT CALL RES_B_MAP ;Mark 'free' sector.
- NXTS CALL DEC_SECT ;Continue until the whole tape has been
- JR NZ,LOOP ;examined.
- IN A,(0EFH) ;Error with write—protected cartridge.
- AND 1
- JP Z,RS—SH
- CALL RD_SECTOR ;Fetch the EOF record.
- JP C,RS—SH2 ;Error with wrong checksum.
- LD L,(IX+RECLEN) ;Use RECLEN as current position.
- LD H,(IX+RECLEN+l)
- LD (IX+CHBYTE),L
- LD (IX+CHBYTE+1),H
- SET 0,(IX+CHFLAG) ;Make this a 'write' file.
- CALL IN_CHK ;Set 'free sector' descriptor.
- SLOOP CALL GET_M_HD02 ;Fetch a header block.
- LD A,(IX+CHREC) ;Continue if this is not the one.
- CP (IX+HDNUMB)
- JR NZ,SLOOP
- LD A,0E6H ;Start writing.
- OUT (0EFH),A
- LD BC,0168H ;Wait to create a first gap.
- CALL DELAY_BC
- PUSH IX ;Make HL point to data block preamble.
- POP HL
- LD DE,37H
- ADD HL,DE
- CALL OUT_M_BUF ;Erase this sector.
- LD A,0EEH ;'End of writing' signal.
- OUT (0EFH),A
- CALL RES_B_MAP ;Mark 'free' this sector,
- LD A,(IX+RECNUM) ;Copy RECNUM into CHREC.
- LD (IX+CHREC),A
- XOR A Switch off drive motor.
- CALL SEL_DRIVE
- JP END1 ;Finished.
- The steps involved in doing the RESTORE #S command are as follows:
- 1. A 'Microdrive map' is set—up, for use when the channel is made a 'write' channel.
- 2. The last record of the file is loaded into the channel area.
- 3. That record is erased from the cartridge.
- 4. The channel is marked 'write channel'.
- As with the READ #S,N command, errors are reported if the stream 'S' is closed, or if it is opened with other than "m" \
- channel, or with "m" channels opened for writing.
- Extending the RS-232 channel
- This routine creates three new commmands for time user who has an RS232 printer connected to their Spectrum.
- Time first command is LPRINT ? n. If n=1, a new RS232 channel is opened, so subsequent LPRINT and LLIST commands will \
- use this for their outputs. If n=0, the "p" channel is defaulted for the LPRINT and LLIST Commands (the ZX Printer).
- The channel opened has more features than the normal "t" channel. The TAB function and the comma are supported on the \
- printer, the 'leading space bug' present with the "t" channel has been corrected, the CR and LF codes are \
- re—definable, an auto CR feature is supported, and finally a re—definable form—feed code is sent after a certain \
- amount of lines printed, so as to advance to the next page before the printing head reaches the end of the sheet.
- The second command is LPRINT ! x,y. The parameter 'x' will define the width of the line. If, for example, you specify \
- a width equal to 32, the standard Spectrum screen format is used. A width of 40, 80, 132 columns, or other, is \
- suitable depending on your choice, and on the maximum width that your printer allows. The parameter 'y' will define \
- the number of columns used as step when printing the 'comma' control code. The default value for 'x' and 'y' are 80 \
- and 20.
- The last command is LPRINT / x,y. In this case, 'x' will define the number of lines that will be printed before the \
- form feed code (which advances to the next page) is sent to the printer (default=60, suitable for 66—line sheets). The \
- parameter 'y' is the form—feed code that your printer accepts; the standard value is 12. You may store codes other \
- than form—feed, such as linefeed, etc., to obtain different results when the 'x' lines have been printed.
- The CR code is sent as 'CR' followed by 'LF' (Line Feed). If your printer does not need the LF code, you may end up \
- with a double spacing between lines; the problem may be eliminated with POKE 65045,0.
- The assembly code for our final extension to BASIC is listed below.
- PGM9 RST CALBAS ;Advance CH_ADD.
- DEFW NEXT CHAR
- CP "!"
- JR Z,OUT1 ;Jump with LPRINT !x,y
- CP "/"
- JR Z,OUT2 ;Jump with LPRINT /x,y
- CP "?"
- JR Z,OUT3 ;jump with LPRINT ?n
- JP ERR_6 ;Error if none of these.
- ;
- OUT1 RST CALBAS ;Evaluate 'x,y'.
- DEFW NEXT_2NUM
- CALL ST_END ;Confirm end of statement.
- RST CALBAS ;Fetch 'y'.
- DEFW FND_INT1
- AND A ;Reject spacing=0.
- JP Z,OTRNG
- LD (CMMSP),A ;Store this value.
- RST CALBAS ;Fetch 'x'.
- DEFW FND_INT1
- DEC A ;Range of 'x' is from 0 onwards.
- LD (WIDTH),A ;Store the value.
- JP END1 ;Finished.
- ;
- OUT2 RST CALBAS ;Evaluate 'x,y'
- DEFW NEXT_2NUM
- CALL ST_END ;Confirm end of statement.
- RST CALBAS ;Fetch 'y'
- DEFW FND_INT1
- LD (FFC),A ;Store it.
- RST CALBAS ;Fetch 'x'.
- DEFW FND_ NT1
- LD (LPAGE),A ;Store it.
- XOR A
- LD (CLINE),A ;Clear line counter.
- JP END1 ;Finished.
- ;
- OUT3 RST CALBAS ;Advance CH_ADD.
- DEFW NEXT_CHAR
- RST CALBAS
- DEFW EXPT_1NUM ;Evaluate 'n'
- CALL ST_END ;Confirm end of statement.
- RST CALBAS ;Fetch 'n'
- DEFW FND_INT1
- CP 1
- JR Z,NEWOUT ;Open new channel if n=1.
- LD A,3 ;Otherwise stream 3 reverts to "p"
- RES 1,(IY+FLAGS3) ;channel.
- CALL CLOSE
- JP END1 ;Finished.
- ;
- NEWOUT LD A,3
- RST CALBAS
- DEFW STR_DATA1 ;Fetch current stream data.
- LD HL,11H
- AND A
- SBC HL,BC
- JP C,NREPORT—C ;Error if stream is already opened.
- CALL OP_RS_CH ;Open a "t" channel.
- PUSH DE ;Save stream data.
- LD HL,5 ;Make HL point to 'address of output
- ADD HL,DE ;routine'.
- LD DE,NRSOUT ;Change this address to NRSOUT below.
- LD (HL),E
- INC HL
- LD (HL),D
- LD A,3 ;Use stream 3.
- LD (5CD8H),A
- POP DE ;Restore stream data.
- JP OP_STREAM ;Attach channel to a stream.
- ;
- NRSOUT CP 0A5H ;Use shadow ROM routine with token codes.
- JP NC, TCHAN—OUT+4
- RES 0,(IY+FLAGS) ;Clear 'leading space' flag.
- CP SPACE ;Jump forward with control codes lower
- JR C,CTRL ;than 20H.
- JR NZ,NOSPC ;Jump if not a space.
- SET 0,(IY+FLAGS) ;Otherwise set 'leading space' flag.
- NOSPC PUSH AF ;Save the code temporarily.
- LD A,1 ;Accept next CR code.
- LD (CLRCR),A
- POP AF ;Restore the code.
- CALL TCHAN_OUT ;Use "t" channel to print it,
- LD A,(WIDTH)
- LD B,A
- LD A,(POSN)
- CP B
- JR NC,NLIN ;Jump if POSN>WIDTH.
- INC A ;Otherwise increment POSN.
- LD (POSN),A
- RET
- ;
- NLIN CALL ENDLI ;Advance to next line.
- XOR A ;Disable next CR code.
- LD (CLRCR),A
- RET
- ;
- ENDLI LD A,1 ;Accept next CR code.
- LD (CLRCR),A
- DEC A
- LD (POSN),A ;Clear POSN.
- LD A,(CRCD) ;Fetch CR code.
- AND A
- CALL NZ,BCHAN_OUT ;Send it unless zero.
- LD A,(LFEED) ;Fetch LF code.
- AND A
- CALL NZ,BCHAN_OUT ;Send it unless zero.
- LD A,(LPAGE)
- LD B,A
- LD A,(CLINE)
- INC A
- CP B
- JR NZ,NOFEED ;Jump if not the end of the page.
- LD A,(FFC) ;Fetch form feed code.
- AND A
- CALL NZ,BCHAN_OUT ;Send it unless zero.
- XOR A
- NOFEED LD (CLINE),A ;Store new line number.
- RET
- ;
- CTRL CP CR ;Jump if the code is not CR.
- JR NZ,NOCR
- LD A,(CLRCR)
- AND A ;Check current state of CR flag.
- LD A,1 ;Reset flag to 1 for later.
- LD (CLRCR),A
- RET Z ;Do not do a CR if CLRCR=0.
- JR ENDLI ;Otherwise loop back.
- ;
- NOCR CP PRCOMMA ;Jump if not a comma.
- JR NZ,NOCOMMA
- LD HL,(POSN) ;L= POSN H= WIDTH
- LD A,(CMMSP)
- LD B,A
- LD C,0
- ONESPC INC C ;Increment counters.
- INC L
- LD A,L
- CP H
- JR NC,NLIN ;Jump if POSN>=WIDTH.
- CHKPOS SUB B ;Jump if reached the correct place, or
- JR Z,SPLOOP ;continue if not.
- JR NC,CHKPOS
- JR ONESPC
- ;
- SPLOOP PUSH BC ;Print 'C' spaces by calling recursively
- LD A,SPACE ;this routine.
- CALL NRSOUT
- POP BC
- DEC C
- JR NZ,SPLOOP
- RET
- ;
- NOCOMMA CP TAB ;Return if not the TAB code.
- RET NZ
- LD DE,PAR1 ;Alter output address.
- ;
- ALTOP LD HL,(CURCHL)
- LD B,5
- ADD HL,BC
- LD (HL),E ;Store new output address.
- INC HL
- LD (HL),D
- RET
- ;
- PAR1 LD (TVDATA+1),A ;Store 'n'.
- LD DE,PAR2 ;Output address for next byte.
- JR ALTOP
- ;
- PAR2 LD DE,NRSOUT ;Restore initial output address.
- CALL ALTOP
- LD A,(TVDATA+1) ;Fetch column 'n'.
- LD B,A
- LD A,(WIDTH)
- CP B
- JR NC,GOOD
- OTRNG LD (IY+ERR_NR),0AH ;Error if 'n' is greater than WIDTH.
- RST ROMERR
- GOOD LD A,(POSN)
- SUB B
- RET Z ;Return if already in place.
- JR NC,GRT ;Jump if POSN>'n'.
- NEG ;A=number of spaces required.
- LD C,A
- JR SPLOOP ;Jump back.
- GRT PUSH BC
- CALL ENDLI ;First advance to next line.
- POP BC
- LD C,B
- JR SPLOOP ;Jump back to insert the spaces.
- ;
- POSN DEFB 0
- WIDTH DEFB 80
- CMMSP DEFB 20
- FFC DEFB 12
- LPAGE DEFB 60
- CLRCR DEFB 1
- CRCD DEFB CR
- LFEED DEFB 0AH
- CLINE DEFB 0
- ;
- END
- The EQU statements given here define all the labels referred to in the preceding program:
- ;
- ;Shadow ROM addresses
- ;
- MAIN_ROM EQU 00H
- CALBAS EQU 10H
- SH_ERR EQU 20H
- ROMERR EQU 08H
- NEWVAR EQU 30H
- ERR_6 EQU 01F0H
- NREPORT—C EQU 052FH
- ST_END EQU 05B7H
- END1 EQU 05C1H
- EXPT_NUM EQU 061EH
- NREPORT—2 EQU 0663H
- CHECK_M_2 EQU 066DH
- NREPORT—3 EQU 062DH
- UNPAGE EQU 0700H
- NREPORT—N EQU 0902H
- OP_RS_CH EQU 0B13H
- OP_STREAM EQU 0B4AH
- TCHAN_ OUT EQU 0C3CH
- BCHAN_OUT EQU 0C5AH
- SET_T_MCH EQU 0FE8H
- DEL_M_BUF EQU 10C4H
- RWF—ERR EQU 1132H
- GET_R_LP EQU 1184H
- RS—SH2 EQU 11A3H
- G_HD_RC EQU 11A5H
- GET_M_HD2 EQU 12C4H
- RES_B_MAP EQU 12FEH
- DEC_SECT EQU 1312H
- CHKS_HD_R EQU 1341H
- CLOSE EQU 1718H
- SEL_DRIVE EQU 17F7H
- OUT_M_BUF EQU 1878H
- GT_M_BLK EQU 18ADH
- DELAY_BC EQU 18FAH
- RD_SECTOR EQU 1A4BH
- RS—SH EQU 1AC5H
- FREESECT EQU 1D38H
- PRCHAR EQU 1D66H
- IN_CHK EQU 1E3EH
- DISP_HEX EQU 1E87H
- DISPHEX2 EQU IE9EH
- DISP_CH EQU 1EA9H
- ;
- ;Main ROM addresses
- ;
- ERROR_1 EQU 08H
- GET_CHAR EQU 18H
- NEXT_CHAR EQU 20H
- BEEPER EQU 03B5H
- ED_LOOP EQU 0F38H
- ED_EDIT EQU 0FA9H
- ED_ERROR EQU 107FH
- CHAN_OPEN EQU 1601H
- STR_DATA1 EQU 1727H
- NEXT_2NUM EQU 1C79H
- EXPT_1NUM EQU 1C82H
- EXPT_EXP EQU 1C8CH
- FND_INT1 EQU 1E94H
- FIND_INT2 EQU 1E99H
- STK_FETCH EQU 2BF1H
- STACK_A EQU 2D28H
- PRINT_FP EQU 2DE3H
- ;
- ;System variables
- ;
- TVDATA EQU 5C0EH
- ERR_SP EQU 5C3DH
- E_PPC EQU 5C49H
- CHURCHL EQU 5C51H
- SCR_CT EQU 5C8CH
- VECTOR EQU 5CB7H
- SECTOR EQU 5CC9H
- HD_11 EQU 5CEDH
- ;
- ;Offsets
- ;
- ERR_NR EQU 00H
- FLAGS EQU 01H
- CHBYTE EQU 0BH
- PPC_HI EQU 0CH
- CHREC EQU 0DH
- CHFLAG EQU 18H
- CHDRIV EQU 19H
- HDNUMB EQU 29H
- RECFLG EQU 43H
- RECNUM EQU 44H
- RECLEN EQU 45H
- FLAGS3 EQU 7CH
- ;
- ;Hook codes
- ;
- HOOK31 EQU 31H
- HOOK32 EQU 32H
- ;
- ;Keywords
- ;
- BEEP EQU 0D7H
- CAT EQU 0CFH
- CODE EQU 0AFH
- DATA EQU 0E4H
- LINE EQU 0CAH
- LPRINT EQU 0E0H
- POKE EQU 0F4H
- PRINT EQU 0F5H
- READ EQU 0E3H
- RESTORE EQU 0E5H
- ;
- ;ASCII
- ;
- PRCOMMA EQU 06H
- CR EQU 0DH
- TAB EQU 17H
- SPACE EQU 28H
- COMMA EQU 2CH
- Extending Spectrum BASIC
- The information given in this section, together with the examples given earlier should be sufficient to allow \
- experienced machine code programmers to write their own new BASIC commands, and incorporate them into the Spectrum's \
- BASIC. Non—programmers may still be interested in the details of the Spectrum's BASIC interpreter, and of the \
- ingenious mechanism used to extend it. Please note that this information is primarily designed to give a general \
- explanation of how we have implemented our extended BASIC commands. It is not intended to be a step by step guide to \
- writing new BASIC commands. A fuller explanation of this material is given in The Spectrum Microdrive Book by Dr. Ian \
- Logan, also published by Melbourne House.
- We should first consider the workings of the Spectrums syntax checking routine. When the syntax checker detects an \
- error in a statement, either as it is entered, or at runtime, a jump is made to the error handling routine. This is \
- done by a RST 8 instruction, followed by a byte which defines the error type. Note the similarities between this and \
- the hook codes discussed earlier. As with the normal hook codes, the RST 8 causes a jump to the Shadow ROM where \
- there is a second examination of the current BASIC statement, to see if it really is an error.
- It is this 'second chance' that makes it possible for the new BASIC commands provided by the Interface 1 to exist. \
- These new commands are perceived as errors by the Spectrums ROM, so the error routine is called. This passes control \
- to the Interface 1, where the Shadow ROM does its own syntax checking, recognizes the new commands, and performs the \
- appropriate action for each new command, before passing control back to the main Spectrum ROM. Code is provided in the \
- Shadow ROM for checking commands starting with the following keywords: CAT, FORMAT, MOVE, ERASE, OPEN, SAVE, LOAD, \
- VERIFY, MERGE, CLS, and CLEAR.
- More interesting to us, however, is what happens when a statement 'fails the syntax' (that is, is found to be \
- syntactically incorrect) of both the main ROM and the Shadow ROM. When this happens, the Shadow ROM decides that it \
- really has
- found an error, and jumps to the address which is stored in a system variable called VECTOR. This address is normally \
- that of a main ROM error handling routine, which will print out an error message and cease execution. However, since \
- the variable VECTOR is in RAM, we can change the value it holds to that of our own syntax checking routine, which will \
- check the statement yet again, to see if it is one of the new commands that we have defined. If the statement is one \
- of our new statements, our syntax checker will call a machine language subroutine which will perform the appropriate \
- actions before returning control to the main ROM, otherwise it will call a routine to print an error message.
- So, the control routine that must be added to handle a new statement must have two parts: Firstly, there must be a \
- syntax routine which will identify the new command, any parameters that go with it, and the end of the statement it is \
- in. Secondly, there must be a routine which will do the actual work of the command. Finally, of course, the system \
- variable VECTOR must have been redirected to point to the syntax routine, so that 'errors' detected by the Shadow ROM \
- will be redirected to your routine.
- The syntax of your new command can be anything which will be rejected by the syntax checkers in both the main ROM and \
- the Shadow ROM. Note however, that your command must not start with any of the eleven keywords which are recognised
- by the Shadow ROM (see above).
- The execution of the new commands then, is a fairly complex procedure, comprised of the following steps:
- (i) Command is rejected as being syntactically incorrect by the syntax checking routine in main ROM. Accordingly, an \
- error routine is called, using a RST 8 command.
- (ii) This causes control to be transfered to the syntax checking routine in the Shadow ROM.
- (iii) The Shadow ROM syntax checker rejects your statement, and calls the routine whose address is stored in the \
- variable VECTOR. This would normally be the main ROMs "report an error" routine, but since you have previously changed \
- the contents of VECTOR to point to your own syntax checking routine, it will be your routine that is called.
- (iv) Your syntax routine checks to see that you have given what it regards as a correct command. Once it decides that \
- you have, it calls a routine which you have written to do whatever task is required of the new BASIC command.
- (v) Your routine returns control to the BASIC program which is currently running.
- Although the task of extending the Spectrum's BASIC is quite complex a close study of the examples given in this book \
- should be quite rewarding.
- THE SHADOW ROM DISASSEMBLY
- The restart routines
- THE 'RETURN TO MAIN ROM' RESTART
- This restart is used to return to the "main" ROM, starting from the address held in the stack before calling this \
- routine.
- 0000 MAIN-ROM POP HL Remove return address from the
- machine stack.
- 0001 LD (FLAGS3),+00 Clear FLAGS3.
- 0005 JP 0700,UNPAGE Return to 'main' ROM.
- THE 'START'
- This is the main entry point to the 'shadow' ROM; it is paged in when the Program Counter reaches the address +0008 \
- that is, the address of the main ROM 'ERROR' routine. (The other time in which the "shadow" ROM is paged in is when \
- the Program Counter reaches the address +1708 i.e., the middle of the CLOSE command routine, which is not able to deal \
- with Interface's channels.)
- 0008 ST-SHADOW LD HL,(CH-ADD) The first instruction is common to
- both ROMs.
- 000B POP HL Get the return address
- 000C PUSH HL (usually points to the error code)
- 000D JP 009A,START-2 Jump forward.
- THE 'CALL A MAIN ROM ROUTINE' RESTART
- This routine allows for a subroutine in the 'main' ROM to be called from the 'shadow' ROM, and can be called by using \
- a RST 10 instruction, followed by the address of the 'main' ROM subroutine.
- 0010 CALBAS LD (H-L),HL Save HL into SBRT.
- 0013 POP HL Get the return address (points to the
- address following the RST 10).
- 0014 PUSH DE Save DE temporarily.
- 0015 JR 0081,CALBAS-2 Jump forward.
- 0017 DEFB +FF Unused location.
- THE 'TEST IF SYNTAX IS BEING CHECKED' RESTART
- This corresponds to the 'main' ROM 'SYNTAX-Z' subroutine. A test of bit 7 of FLAGS wHL give the Zero flag set during \
- syntax checking, and reset during
- execution.
- 0018 CHKSYNTAX BIT 7,(FLAGS) Test bit 7 of FLAGS.
- 001C RET Finished.
- 001D DEFB +FF,+FF,+FF Unused locations.
- THE 'SHADOW ERROR' RESTART
- Jumps to the required routine to deal with 'new' report messages. This routine can be called by using a RST 20 \
- instruction followed by the error code (in the range +FF...+16).
- 0020 SH-ERR RST 18,CHKSYNTAX Jump to ST-ERROR if checking
- 0021 JR Z,0068,ST-ERROR syntax, or
- 0023 JR 003A,TEST-SP to TEST-SP during runtime.
- 0025 DEFB +FF,+FF,+FF Unused locations.
- THE 'MAIN ROM ERROR' RESTART
- Before calling this routine, (ERR-NR) must contain the error code.
- 0028 ROMERR RES 3,(TVFLAG) Signal 'the mode is to be considered
- unchanged'
- 002C JR 0040,RMERR-2 jump forward.
- 002E DEFB +FF,+FF Unused locations.
- THE 'CREATE NEW SYSTEM VARIABLES' RESTART
- The routine is entered at 01F7.
- 0030 NEWVARS JP 01F7,CRT-VARS Jump forward immediately.
- 0033 DEFB +FF,+FF,+FF Unused locations.
- 0036 DEFB +FF,+FF
- THE 'MASKABLE INTERRUPT' ROUTINE
- While the 'shadow' ROM is paged-in, the keyboard is not scanned.
- 0038 INT-SERV EI Enable interrupts.
- 0039 RET Return immediately.
- THE 'TEST-SP' ROUTINE
- Check if it is necessary to print the required report message.
- 003A TEST-SP CALL 0077,CHECK-SP Use 'main' ROM error handler if
- required.
- 003D JP 0258,REP-MSG Print the report message.
- THE 'MAIN ROM ERROR' ROUTtNE
- The pressing of BREAK during the loading of 'autorun' programs wHL reset the system; otherwise the error routine \
- continues.
- 0040 RMERR-2 RST 18,CHKSYNTAX Jump forward if checking syntax.
- 0041 JR Z,0068,ST-ERROR
- 0043 CALL 0077,CHECK-SP Use 'main' ROM error handler if
- required.
- 0046 CALL 17B9,RCL-T-CH Reclaim all temporary channels &
- switch off drive motors.
- 0049 BIT 1,(FLAGS3) Jump forward if not
- 004D JR Z,0068,ST-ERROR during the loading of
- 004F BIT 4,(FLAGS3) an 'autorun' program.
- 0053 JR Z,0068,ST-ERROR
- 0055 LD A,(ERR-NR) Fetch the error code.
- 0058 CP +14 Check if attempting to BREAK into the
- loading of an autorun program.
- 005A JR NZ,0068,ST-ERROR Jump if not.
- 005C LD HL,+0000 Otherwise reset the system
- 005F PUSH HL by jumping to the address
- 0060 RST 0,MAIN-ROM +0000 in the 'main' ROM.
- 0061 DEFB +FF,+FF,+FF Unused locations.
- 0064 DEFB +FF,+FF
- THE 'NON-MASKABLE INTERRUPT' ROUTINE
- As with maskable interrupts, there are no service routines.
- 0066 NMINT-SRV RETN Return immediately.
- THE 'ST-ERROR' ROUTINE
- This routine must be entered with the error code in (ERR-NR), and has the same effect as the 'main' ROM 'ERROR' restart.
- 0068 STERROR LD HL,(CHADD) The address of the character reached
- 006B LD (X-PTR),HL by the interpreter is copied into
- the error pointer.
- 006E LD SP,(ERR-SP) Clear machine stack.
- 0072 LD HL,+16C5 Return via 'main' ROM 'SET-STK'
- 0075 PUSH HL routine to the error handler
- 0076 RST 0,MAIN-ROM routine.
- THE 'CHECK-SP' ROUTINE
- Use the 'main' ROM error handler only if bit 2 of FLAGS3 is set.
- 0077 CHECK-SP BIT 2,(FLAGS3) Return. (Normally bit 2 is always
- 007B RET Z reset)
- 007C LD SP,(ERR-SP) Make error handler routine the
- 0080 RST 0,MAIN-ROM return addrcs0 & exit.
- THE 'CALBAS-2' ROUTINE
- This routine uses the SBRT area to call the required routine in the 'main' ROM.
- 0081 CALBAS-2 LD E,(HL) Fetch the address of the subroutine
- 0082 INC HL to be called Into the DE
- 0083 LD D,(HL) register pair.
- 0084 LD (5CBD),DE Use the address with the CALL in
- SBRT area.
- 0088 INC HL Points to the return address.
- 0089 EX (SP),HL Exchange with initial value of DE
- register pair (see 0014).
- 008A EX DE,HL Restore initial value of DE.
- 008B LD HL,+0000 Signal "a 'main' ROM routine has been
- 008E PUSh HL called".
- 008F LD HL,+0008 Return address to the shadow ROM
- 0092 PUSH HL is +0008.
- 0093 LD HL,+5CB9 Call indirectly the
- 0096 PUSH HL SBRT subroutine after having
- 0097 JP 0700,UNPAGE paged-out the 'shadow' ROM.
- The control routine
- This routine is called from ST-SHADOW at 0008 when the shadow ROM is paged-in. It has 3 main tasks:
- - If the paging of the shadow ROM is the return after a call to a 'main' ROM
- subroutine, then it returns to the calling routine.
- - If an Interface's channel has been requested, it jumps to the required 'input'
- or 'output' routine.
- - If an error has occurred in the 'main' ROM, a check is made to see if the
- error code is a 'hook code' (and calls the required routine if it is). If it
- is not a 'hook code', then it checks to determine whether the error is
- "Nonsense in BASIC", "Invalid filename", or "Invalid stream". If it is any of
- these, probably a 'new' command has been used. If so, the routine
- corresponding to the command is called, otherwise the error is produced by
- jumping to the address 01F0 (held in the VECTOR system variable - thus
- altering this address to point a routine in RAM wHL give the possLDility of
- adding more 'new' commands). In all other cases, the main ROM error handler
- is used.
- 009A START-2 PUSH AF Save A register.
- 009B LD A,H Check if the return address
- 009C OR L is zero.
- 009D JR NZ,00A5,START-3 Jump forward if it is not.
- 009F POP AF Otherwise a 'main' ROM routine
- 00A0 POP HL has been called; clear stack.
- 00A1 LD HL,(H-L) Restore HL and return to the
- 00A4 RET calling routine.
- Now see if an Interface's channel has been requested.
- 00A5 START-3 PUSH DE Save DE temporarily.
- 00A6 LD DE,+15FE If a channel has been requested,
- this is the return address stored by
- the CALL 162C inside the 'main' ROM
- 'CALL-SUB' subroutine.
- 00A9 SBC HL,DE Jump forward if no
- 00AB POP DE channels have been requested.
- 00AC JR NZ,00BC,START-4
- 00AE POP AF Restore A register (character to be
- transmitted if during 'output').
- 00AF LD HL,+0700 Make return address the
- 00B2 PUSH HL UNPAGE routine.
- 00B3 LD HL,+0004 DE now holds (address of routine
- pointer - 4).
- 00B6 ADD HL,DE HL holds the address of the routine
- pointer.
- 00B7 LD E,(HL) Fetch the low byte.
- 00B8 INC HL
- 00B9 LD D,(HL) Fetch the high byte.
- 00BA EX DE,HL Move the address to HL.
- 00BB JP (HL) Jump to the appropriate 'input' or
- 'output' routine.
- At this point, the shadow ROM has surely been paged-in by an error in the 'main' ROM.
- 00BC START-4 RST 30,NEWVARS Create interface variables if
- 00BD LD A,+01 non-existent, then send some
- 00BF OUT (+F7),A signals to the Interface 1.
- 00C1 LD A,+EE
- 00C3 OUT (+EF),A
- 00C5 POP AF Remove A temporarily.
- 00C6 POP HL Return address (points to the error
- code after a RST 8).
- 00C7 PUSH AF Save A again.
- 00C8 RST 10,CALBAS This calls a single 'LD A,(HL)'
- 00C9 DEFW +007B instruction, so the error code is
- fetched from the main ROM code.
- 00CB LD (ERR-NR),A Store the error code.
- 00CE CP +FF Check if the error is 'OK'.
- 00D0 JR NZ,00E9,TESTCODE Jump if it is not.
- 00D2 BIT 1,(FLAGS3) This is set when using the 'shadow'
- ROM for the first time (i.e. after
- a NEW command).
- 00D6 JR Z,00E7,NREPORT-0 Give an error if not the first time.
- 00D8 BIT 7,(PPC-hi) Give an error also if the
- 00DC JR Z,00E7,NREPORT-0 line is not in the editing area.
- 00DE LD HL,(E-LINE) Otherwise fetch the command code from
- 00E1 LD A,(HL) the editing area.
- 00E2 CP +F7 Check if the command is 'RUN'.
- 00E4 JP Z,0A95,LOAD-RUN Load the 'run' program from
- Microdrive if so.
- 'Program finished'
- 00E7 NREPORT-0 RST 20,SH-ERR Call the error handling
- 00E8 DEFB +FF routine.
- The error code in A determines the task to be executed.
- 00E9 TEST-CODE SUB +1B Reduce the range.
- 00EB JP NC,1981,HOOK-CODE Jump if it's a hook code, or an
- invalid code (greater than 0-32).
- 00EE CP +F0 Jump if the error is
- 00F0 JR Z,00FB,COPYCHADD 'Nonsense in BASIC'.
- 00F2 CP +F3 Also if 'Invalid filename'.
- 00F4 JR Z,00FB,C0PYCHADD
- 00F6 CP +FC Or 'Invalid stream'.
- 00F8 JP NZ,0028,ROMERR If none of these, use 'main' ROM
- error handler to signal the error.
- 00FB COPYCHADD LD HL,(CH-ADD) The character pointer
- 00FE LD (CHADD-),HL is saved.
- 0101 POP AF Clear the stack.
- 0102 BIT 5,(FLAGX) Use 'main' ROM error handler also if
- 0106 JP NZ,0028,ROMERR in INPUT mode, or
- 0109 BIT 0,(FLAGS3) during execution of a 'new' command.
- 010D JP NZ,0028,ROMERR
- 0110 SET 0,(FLAGS3) Signal "execution of a 'new' command"
- 0114 RST 18,CHKSYNTAX Jump if during runtime.
- 0115 JR NZ,011B,RUNTIME
- 0117 LD (PPC-hi),+FF Signal "syntax time".
- Now a loop is entered to find the line that has produced the error.
- 011B RUNTIME LD B,(SUBPPC) Statement counter.
- 011E LD C,+00 Counter of ' " ' characters.
- 0120 BIT 7,(PPC-hi) Jump forward if the line
- 0124 JR Z,0130,PROG-LINE is in the program area.
- 0126 PUSH BC Save counters.
- 0127 RST 10,CALBAS Call main ROM 'E-LINE-NO' (it fetches
- 0128 DEFW +19FB the number of the line in the editing
- area, but is actually used to update
- CH-ADD to the 1st char. in the line).
- 012A POP BC Restore counters.
- 012B RST l0,CALBAS Call GET-CHAR in the main ROM to
- 012C DEFW +0018 update HL to the 1st character in
- the line.
- 012E JR 016F,S-STAT Jump forward.
- 0130 PROG-LINE LD HL,(PROG) Fetch start of program area.
- 0133 SC-L-LOOP LD A,(PPC-hi) Compare the number of the tine to be
- 0136 CP (HL) searched with that of the 'current'
- line.
- 0137 JR NC,013B,TEST-LOW Jump if the 'current' line no. is
- less than or equal to that of the
- line to be searched for.
- Nonsense in BASIC.
- 0139 NREPORT-1 RST 20,SH-ERR Call the error handling
- 013A DEFB +00 routine.
- 013B TEST-LOW INC HL Points to low byte of line no.
- 013C JR NZ,0144,LINE-LEN Jump if the 'current' line is not the
- expected one.
- 013E LD A,(PPC-lo) Compare also the high byte of
- 0141 CP (HL) the line numbers.
- 0142 JR C,0139,NREPORT-1 Give an error if the line dDEs
- not exist.
- 0144 LINE-LEN INC HL Increment the pointer.
- 0145 LD E,(HL) Fetch low byte of the length.
- 0146 INC HL
- 0147 LD D,(HL) Fetch high byte.
- 0148 INC HL Points to start of the line.
- 0149 JR Z,0l6F,S-STAT Jump if the line is found,
- 014B ADD HL,DE otherwise points to next line.
- 014C JR 0l33,SC-L-LOOP Continue until found.
- 014E SKIP-NUN LD DE,+0006 Length of a floating point number.
- 0151 ADD HL,DE Skip the floating point representat.
- This loop advances the pointer 'HP until it reaches the start of the statement that has produced the error.
- 0152 EACH-ST LD A,(HL) Get a character from line.
- 0153 CP +0E Is it the 'number' marker ?
- 0155 JR Z,0l4E,SKIP-NUM If so, advance the pointer after the
- 'number'.
- 0157 INC HL Points to next character.
- 0158 CP +22 Is the character a '"'?
- 015A JR NZ,015D,CHKEND Jump it it is not.
- 015C DEC C Decrement counter for each '"' found
- 015D CHKEND CP +3A Is the character a colon?
- 015F JR Z,0165,CHKEVEN Jump if it is.
- 0161 CP +CB Jump unless the character is 'THEN'.
- 0163 JR NZ,0l69,CHKEND-L Check whether the number of quotes
- 0165 CHKEVEN BIT 0,C found is even (i.e. colon or THEN
- are out of a string).
- 0167 JR Z,016F,S-STAT Jump if the statement is finished.
- 0169 CHKEND-L CP +80 Check whether the line is finished.
- 016B JR NZ,0152,EACH-ST Continue the loop if not.
- 016D JR 0139,NREPORT-1 Give an error (because a wrong number
- of quotes have been found).
- 016F S-STAT DJNZ 0152,EACH-ST Continue with next statement.
- 0171 DEC HL Now HL holds the start address of the
- required statement.
- 0172 LD (CH-ADD),HL Update CH-ADD to this address.
- 0175 RST 18,CHKSYNTAX Jump forward if during runtime.
- 0176 JR NZ,01AA,CL-WORK
- 0178 BIT 7,(PPC-hi) Give an error report if the line is
- 017C JP Z,01F0,ERR-6 not in the editing area.
- The final loop is made during syntax checking, for removing all 6-byte floating point numbers inserted in the line by \
- the 'main' ROM interpreter.
- 017F DEC HL This balances the INC below.
- 0180 LD C,+00 Clear C register.
- 0182 RCLN-NUM INC HL Points to next character.
- 0183 LD A,(HL) Fetch the character.
- 0184 CP +0E Jump if the character is not the
- 0186 JR NZ,01A5,NEXTNUM start of a 'number'.
- 0188 PUSH BC Save the counter.
- 0189 LD BC,+0006 '6' bytes have to be reclaimed.
- 018C RST 10,CALBAS Call RECLAIM-2 in the 'main' ROM to
- 018D DEFW +19E8 reclaim the 'number'.
- 018F PUSH HL Save HL (points after the reclaimed
- 'number' ).
- 0190 LD DE,(CHADD-) Jump forward if the '6' bytes
- 0194 AND A reclaimed were after the character
- 0195 SBC HL,DE pointed by CHADD-.
- 0197 JR NC,01A3,NXT-1
- 0199 EX DE,HL Otherwise CHADD- needs to be updated.
- First move it into HL.
- 019A LD BC,+0006 The character pointed by CHADD- has
- 019D AND A been moved '6' bytes down.
- 019E SBC HL,BC
- 01A0 LD (CHADD-),HL Store the new value.
- 01A3 NXT-1 POP HL Restore pointer and counter.
- 01A4 POP BC
- 01A5 NEXTNUM LD A,(HL) Jump back into the loop until
- 01A6 CP +0D the line is finished.
- 01A8 JR NZ,0182,RCLM-NUM
- Now the working areas and the new system variables are cleared.
- 01AA CL-WORK RST 10,CALBAS Clear work areas by calling main
- 01AB DEFW +16BF ROM 'SET-WORK' routine.
- 01AD CALL 024D,RES-VARS Reset some 'new' variables to +FF.
- Finally, the command code is fetched from the line, and if it is a 'new' command, the appropriate routine is called.
- 01B0 RST 10,CALBAS Call NEXT-CHAR in the main ROM to
- 01B1 DEFW +0020 fetch the command code.
- 01B3 SUB +CE Reduce range of the code.
- 01B5 CP +01 Ia the command a 'CAT'
- 01B7 JP Z,0486,CAT-SYN Check CAT syntax if so.
- 01BA CP +02 Also for 'FORMAT',...
- 01BC JP Z,04B4,FRMT-SYN
- 01BF CP +03 ...'MOVE',...
- 01C1 JP Z,053D,MOVE-SYN
- 01C4 CP +04 ...'ERASE',...
- 01C6 JP Z,053l,ERASE-SYN
- 01C9 CP +05 ...'OPEN',...
- 01CB JP Z,04ED,OPEN-SYN
- 01CE CP +2A ...'SAVE',...
- 01D0 JP Z,082F,SAVE-SYN
- 01D3 CP +21 ...'LOAD',...
- 01D5 JP Z,0894,LOAD-SYN
- 01D8 CP +08 ...'VERIFY',...
- 01DA JP Z,089E,VERIF-SYN
- 01DD CP +07 ...'MERGE',...
- 01DF JP Z,08A8,MRG-SYN
- 01E2 CP +2D ...'CLS#',...
- 01E4 JP Z,0559,CLS#-SYN
- 01E7 CP +2F ...and 'CLEAR#' command.
- 01E9 JP Z,057F,CLR#-SYN
- If the command that has produced the error was none of these, a jump is made to the address held in VECTOR system \
- variable.
- 01EC ERR-V LD HL,(VECTOR) Jump to the address held in
- 01EF JP (HL) VECTOR (normally ERR-6 below).
- Now the error produced by the main ROM is confirmed.
- 01F0 ERR-6 LD HL,(CHADD-) Restore initial CH-ADD contents.
- 01F3 LD (CH-ADD),HL
- 01F6 RST 28,ROMERR Give the appropriate error.
- THE 'CREATE NEW SYSTEMS VARIABLES' ROUTINE
- This routine is used to create the 'new' system variables if nonexistent and it is called from the restart 0030. Many \
- variables are initialised to its default value.
- 01F7 CRT-VARS LD HL,(CHANS) Fetch start of channel area.
- 01FA LD DE,+A349 This is FFFF-5CB6.
- 01FD ADD HL,DE The carry flag is now set it the
- CHANS area starts after the
- address +5CB6.
- 01FE JR C,0235,VAR-EXIST Jump if the 'new' variables already
- exist.
- 0200 LD HL,+0224 Pre-load machine-stack with the
- 0203 PUSH HL address DEFAHLT below.
- 0204 LD HL,(STKBOT) Clear the calculator
- 0207 LD (STKEND),HL stack.
- 020A LD HL,+5C92 Set MEM with the address of
- 020D LD (MEM),HL MEMBOT area.
- 0210 LD HL,+5CB5 One location before the new space
- is needed.
- 0213 LD BC,+003A Length of space needed.
- 0216 LD DE,+0000 Signal 'a main ROM routine has been
- 0219 PUSH DE called'.
- 021A LD E,+08 Store return address to the
- 021C PUSH DE shadow ROM.
- 021D LD DE,+1655 Return address to main ROM
- 0220 PUSH DE is MAKE-ROOM.
- 0221 JP 0700,UNPAGE
- After the 'insertion' of the new space has been made, the program continues here with the initialisation of some \
- variables.
- 0224 DEFAULT LD HL,+023A Base address of 'default values'
- table.
- 0227 LD BC,+0013 Length of table.
- 022A LD DE,+5CB6 Start of 'new variables' area.
- 022D LDIR Store default values.
- 022F LD A,+01 Set COPIES to +01.
- 0231 LD (COPIES),A
- 0234 RET Finished.
- If the new variables already exist, bit 1 of FLAGS3 is reset.
- 0235 VAR-EXIST RES 1,(FLAGS3) 'New variables already exist'.
- 0239 RET Finished.
- THE 'SYSTEM VARIABLES DEFAHLT VALDES' TABLE
- This table contains the default values of all the 'new' system variables from FLAGS3 to SER-FL.
- 023A DEFB +02 Default value for FLAGS3 (bit 1 is
- set to signal that the aheadow ROM
- has been paged for the first time
- (see 00D2).
- 023B DEFW +01F0 Default for VECTOR is ERR-6 address.
- 023D LD HL,+0000 This short subroutine is the SBRT
- 0240 CALL +0000 'variable', used to call main ROM
- 0243 LD (H-L),HL routines from the shadow ROM.
- 0246 RET
- 0247 DEFW +000C default for BAUD is +000C
- (i.e. 9600 baud).
- 0249 DEFB +01 Default for NTSTAT.
- 024A DEFB +00 Default for IOBORD colour (black).
- 024B DEFW +0000 Default for SER-FL.
- THE 'RESET NEW SYSTEM VARIABLES' SUBROUTINE
- Before using the 'new' system variables from NTRESP to HD-11, their values
- are reset to +FF.
- 024D RES-VARS LD HL,NTRESP Points to the 1st variable.
- 0250 LD B,+22 The block is made by '34' bytes.
- 0252 EACH-VAR LD (HL),+FF Store +FF in all the bytes in
- 0254 INC HL the block.
- 0255 DJNZ 0252,EACH-VAR
- 0257 RET Finished.
- THE 'SHADOW REPORT PRINTING' ROUTINE
- This routine is very similar to 'MAIN-3' (+1303) in the 'main' ROM, but the
- report message printed is one of the 'shadow' report.
- 0258 REP-MSG LD (FLAGS3),+00 First clear FLAGS3.
- 025C EI Enable interrupts.
- 025D HALT Accept one interrupt.
- 025E CALL 17B9,RCL-T-CH Reclaim temporary channels and
- switch off drive motors.
- 0261 RES 5,(FLAGS) Signal 'ready for a new key'.
- 0265 BIT 1,(FLAGS2) Jump if the printer buffer
- 0269 JR Z,026E,FETCH-ERR has not been used, otherwise call
- 026B RST 10,CALBAS COPY-BUFF in the main ROM to empty
- 026C DEFW +0ECD the buffer.
- 026E FETCH-ERR POP HL This address points to the error code
- (after a RST 20).
- 026F LD A,(HL) Fetch error code.
- 0270 LD (ERR-NR),A Store it into ERR-NR.
- 0273 INC A Increment error number.
- 0274 PUSH AF Save the new value.
- 0275 LD HL,+0000 The system variables
- 0278 LD (FLAGX),H FLAGX, X-PTR-hi and DEFADD are all
- 027B LD (X-PTR-hi),H set to zero.
- 027E LD (DEFADD),HL
- 0281 INC L Now HL holds +0001.
- 0282 LD (+5C16),HL Displacement for stream 0 is made
- +0001 (i.e. reset stream 0 to the
- "K" channel).
- 0285 RST 10,CALBAS Clear work areas, calculator stack
- 0286 DEFW +16B0 by calling SET-MIN.
- 0288 RES 5,(FLAGX) Signal 'editing mode'.
- 028C RST 10,CALBAS Clear lower screen by calling
- 028D DEFW +0D6E CLS-LOWER.
- 028F SET 5,(TVFLAG) Signal 'the lower screen is to be
- cleared'.
- 0293 RES 3,(TVFLAG) Signal 'the mode is to be conside-
- red unchanged'.
- 0297 POP AF Restore error number.
- 0298 LD HL,+02B7 Base address of 'report messages'
- table.
- 029B LD B,+04 Hake BC hold a sufficiently high
- number.
- 029D CPIR Advance HL to the required report
- message in the table.
- 029F PR-REP-LP LD A,(HL) Fetch character of message.
- 02A0 CP +20 Print it unless reached the
- 02A2 JR C,02AC,END-PR-MS 'marker' of next message.
- 02A4 PUSH HL Save pointer.
- 02A5 RST 10,CALBAS Call main ROM 'PRINT-A' restart
- 02A6 DEFW +0010 to print the character.
- 02A8 POP HL Restore pointer.
- 02A9 INC HL Point to next character.
- 02AA JR 029F,PR-REP-LP Continue with next character.
- 02AC END-PR-MS LD SP,(ERR-SP) Clear machine stack.
- 02B0 INC SP Ignore also the address +1303
- 02B1 INC SP pointed by ERR-SP (that is
- replaced with the +1349 below).
- 02B2 LD HL,+1349 Return to the main ROM in the
- 02B5 PUSH HL middle of the 'print report message
- 02B6 RST 0,MAIN-ROM routine.
- THE 'SHADOW' REPORT MESSAGES
- Before each report there is the correspondent error code, incremented by 1.
- 02B7 DEFB +00
- 02B8 DEFM "Program finished"
- 02C8 DEFB +01
- 02C9 DEFM "Nonsense in BASIC"
- 02DA DEFB +02
- 02DB DEFM "Invalid stream number"
- 02F0 DEFB +03
- 02F1 DEFM "Invalid device expression"
- 030A DEFB +04
- 030B DEFM "Invalid name"
- 0317 DEFB +05
- 0318 DEFM "Invalid drive number"
- 032C DEFB +06
- 032D DEFM "Invalid station number"
- 0343 DEFB +07
- 0344 DEFM "Missing name"
- 0350 DEFB +08
- 0351 DEFM "Missing station number"
- 0367 DEFB +09
- 0368 DEFM "Missing drive number"
- 037C DEFB +0A
- 037D DEFM "Missing baud rate"
- 038E DEFB +0B
- 038F DEFM "Header mismatch error"
- 03A4 DEFB +0C
- 03A5 DEFM "Stream already open"
- 03B8 DEFB +0D
- 03B9 DEFM "Writing to a 'read' file"
- 03D1 DEFB +0E
- 03D2 DEFM "Reading a 'write' file"
- 03E8 DEFB +0F
- 03E9 DEFM "Drive 'write' protected"
- 0400 DEFB +10
- 0401 DEFM "Microdrive full"
- 0410 DEFB +11
- 0411 DEFM "Microdrive not present"
- 0427 DEFB +12
- 0428 DEFM "File not found"
- 0436 DEFB +13
- 0437 DEFM "Hook code error"
- 0446 DEFB +14
- 0447 DEFM "CODE error"
- 0451 DEFB +15
- 0452 DEFM "MERGE error"
- 045D DEFB +16
- 045E DEFM "Verification has failed"
- 0475 DEFB +17
- 0476 DEFM "Wrong file type"
- 0485 DEFB +18
- The syntax checking routines
- The routines in this section of the shadow ROM check the syntax of the 'new' commands and call the command routines \
- during runtime.
- THE 'CAT' COMMAND SYNTAX ROUTINE
- This routine checks that the command is in the form CAT n, or CAT #s,n then sets S-STR1 and D-STR1 system variables \
- before exiting in syntax time or executing the CAT during runtime.
- 0486 CAT-SYN LD HL,S-STR1 First make the screen
- 0489 LD (HL),+02 'current' stream.
- 048B RST 10,CALBAS Advance CH-ADD with a call to
- 048C DEFW +0020 'NEXT-CHAR' in the main ROM.
- 048E CP +0D If the line ends here, jump to
- 0490 JR Z,0494,MISSING-D produce an error.
- 0492 CP +3A Give an error also if the
- 0494 MISSING-D JP Z,0683,NREPORT-9 statement ends with a colon.
- 0497 CP +23 Jump if after the keyword
- 0499 JR NZ,04A6,CAT-SCRN there is not the 'hash' character.
- 049B CALL 064E,EXPT-STRM Otherwise evaluate stream number.
- 049E CALL 05B1,SEPARATOR Give an error if after the stream
- 04A1 JR NZ,04B2,OREPORT-1 number there is no separator.
- 04A3 RST 10,CALBAS Advance CH-ADD to next
- 04A4 DEFW +0020 character.
- 04A6 CAT-SCRN CALL 061E,EXPT-NUM Evaluate drive number.
- 04A9 CALL 05B7,ST-END Confirm end of statement and exit
- during syntax time.
- 04AC CALL 066D,CHECK-M-2 Checks that drive number held in
- D-STR1 is in range.
- 04AF JP 1E70,CAT-RUN Do the CATalogue.
- 'Nonsense, in BASIC'
- 04B2 OREPORT-1 RST 20,SH-ERR Call the error handling
- 04B3 DEFB +00 routine.
- THE 'FORMAT' COMMAND SYNTAX ROUTINE
- A FORMAT command may have one of the following forms: FORMAT "m";n;"name" -FORMAT "b";n - FORMAT "t";n - FORMAT "n";n. \
- This routine handles all forms and
- sets N-STR1, L-STR1 and D-STR1 as required before exiting during syntax checking, or executing the command during \
- runtime.
- 04B4 FRMT-SYN CALL 05F2,EXPT-SPEC Evaluate (string)(separator)(number)
- and set L-STR1, D-STR1.
- 04B7 CALL 05Bl,SEPARATOR If there is not a further
- 04BA JR NZ,04BF,NO-FOR-M separator, no filename is to be
- expected, so jump.
- 04BC CALL 062F,EXPT-NAME Evaluate "name" and set N-STR1.
- 04BF NO-FOR-M CALL 05B7,ST-END Confirm end of statement and exit
- during syntax checking.
- 04C2 LD A,(L-STR1) Fetch channel specifier.
- 04C5 CP +54 Jump with FORMAT "T"
- 04C7 JR Z,04CD,FOR-B-T
- 04C9 CP +42 Test for FORMAT "B" - note that the
- routine is the same as that of
- FORMAT "T".
- 04CB JR NZ,04D3,NOT-FOR-B Jump with "N" and "M" channels.
- 04CD FOR-B-T CALL 06B0,TEST-BAUD Check that D-STR1 holds a valid baud
- rate.
- 04D0 JP 0AC9,SET-BAUD Set BAUD variable from D-STR1 value
- (the actual FORMAT with RS232 link).
- 04D3 NOT-FOR-B CP +4E Jump if not a FORMAT "N" command.
- 04D5 JR NZ,04E7,FOR-M
- 04D7 CALL 068F,TEST-STAT Check that D-STR1 holds a valid
- station number.
- 04DA LD A,(D-STR1) Give an error if attempting to
- 04DD AND A FORMAT "n"';0 (i.e. with the
- 04DE JP Z,069F,NREPORT-6 'broadcast' specifier).
- 04E1 LD (NTSTAT),A This is the actual FORMAT command
- with the network.
- 04E4 JP 05C1,END1 Finished.
- 04E7 FOR-M CALL 0685,TEST-MNAM Check that the various parameters
- are correct.
- 04EA JP 1E75,FOR-RUN Do the FORMAT "M" command.
- ThE 'OPEN' COMMAND SYNTAX ROUTINE
- This routine deals with OPEN #s;"m";n;"name" - OPEN #s;"b" - OPEN #s;"t" -
- OPEN #s;"n";n commands. All parameters are stored into S-STR1, N-STR1, D-STR1 and L-STR1 variables before exiting \
- during syntax checking or executing the command during runtime.
- 04ED OPEN-SYN CALL 064E,EXPT-STRM Evaluate stream number.
- 04F0 CALL 05B1,SEPARATOR Give an error report if the separator
- 04F3 JR NZ,04B2,OREPORT-1 has been missed after 'stream no.'
- 04F5 CALL 05F2,EXPT-SPEC Evaluate channel specifier,
- (separator numeric expression).
- 04F8 CALL 05B1,SEPARATOR Jump if no further separator is
- 04FB JR NZ,0500,NOT-OP-M present.
- 04FD CALL 062F,EXPT-NAME Otherwise evaluate "name".
- 0500 NOT-OP-M CALL 05B7,ST-END Confirm end of statement and exit
- if syntax is being checked.
- 0503 LD A,(S-STR1) Fetch stream number.
- 0506 RST 10,CALBAS Call main ROM 'STR-DATA1' routine;
- 0507 DEFW +1727 on exit, BC holds 'stream data'.
- 0509 LD HL,+0011 In fact, jump if the current stream
- 050C AND A is already opened with a 'new'
- 050D SBC HL,BC channel.
- 050F JR C,052F,NREPORT-C
- 0511 LD A,(L-STR1) Fetch channel specifier.
- 0514 CP +54 Jump if opening a 't' channel.
- 0516 JR Z,051C,OPEN-RS
- 0518 CP +42 Jump if not a 'b' channel.
- 051A JR NZ,051F,NOT-OP-B
- 051C OPEN-RS JP 0B47,OP-RSCHAN Do the OPEN referred to RS232 link.
- 051F NOT-OP-B CP +4E Jump if not a 'n' channel (i.e.
- 0521 JR NZ,0520,OP-M-C with 'm' channel).
- 0523 CALL 068F,TEST-STAT Check that D-STR1 holds a valid
- station number.
- 0526 JP 0EA3,OPEN-N-ST Do the OPEN referred to the network.
- 0529 OP-M-C CALL 0685,TEST-MNAM Check that all parameters are valid.
- 052C JP 1E7A,OP-RUN Do the OPEN "M" command.
- 'Stream already open'
- 052F NREPORT-C RST 20,SH-ERR Call the error handling
- 0530 DEFB +0B routine.
- THE 'ERASE' COMMAND SYNTAX ROUTINE
- This command has only one form and, thus, this routine is more straightforward than the preceding ones.
- 0531 ERASE-SYN CALL 06A3,EXPT-EXPR Evaluate ("m";n;"name")
- 0534 CALL 05B7,ST-END Confirm end of statement and exit
- during syntax checking.
- 0537 CALL 0685,TEST-MNAM Check that all parameters are
- valid.
- 053A JP 1E66,ERASE-RUN Do the ERASE command.
- THE 'MOVE' COMMAND SYNTAX ROUTINE
- A 'MOVE' command requires two sets of parameters, for the 'input' channel and for the 'output' channel. These \
- parameters are stored respectively in the two areas D-STR1 and D-STR2.
- 053D MOVE-SYN CALL 06B9,EXPT-EXP1 Evaluate stream number, or channel
- expression.
- 0540 CALL 059F,EX-D-STR Exchange D-STR1 and D-STR2 contents.
- 0543 RST 10,CALBAS Call GET-CHAR in the main ROM.
- 0544 DEFW +0018
- 0546 CP +CC The keyword 'TO' must be present
- 0548 JR NZ,0584,NONSENSE between the two expressions.
- 054A CALL 06B9,EXPT-EXP1 Evaluate 2nd stream number, or
- channel expression.
- 054D CALL 059F,EX-D-STR Exchange again D-STR areas.
- 0550 RST 10,CALBAS Call GET-CHAR in the main ROM.
- 0551 DEFW +0018
- 0553 CALL 05B7,ST-END Confirm end of statement and exit
- during syntax checking.
- 0556 JP 1E6B,MOVE-RUN Do the MOVE command,
- THE 'CLS#' COMMAND ROUTINE
- This routine has the tasks of both 'syntax checking' and 'execution'. During runtime, ATTR-P, ATTR-T, MASK-P, MASK-T, \
- P-FLAG and BORDCR system variables are reset to the 'initiaP value (as after a NEW command).
- 0559 CLS#-SYN RST 10,CALBAS Advance CH-ADD after the
- 055A DEFW +0020 keyword CLS.
- 055C CP +23 The character must be a '#'.
- 055E JR NZ,0584,NONSENSE
- 0560 RST 10,CALBAS Advance CH-ADD again.
- 0561 DEFW +0020
- 0563 CALL 05B7,ST-END Confirm end of statement and exii
- during syntax checking.
- 0566 LD HL,+0038 +38 is the attribute byte.
- 0569 LD (ATTR-P),HL Store +38 into ATTR-P, clear MASK-P.
- 056C LD (ATTR-T),HL Store +38 into ATTR-T, clear MASK-T.
- 056F LD (BORDCR),L Store +38 also for lower screen
- attribute.
- 0572 LD (P-FLAG),H Clear P-FLAG.
- 0575 LD A,+07 Set white border.
- 0577 OUT (+FE),A
- 0579 RST 10,CALBAS Call main ROM 'CLS' routine.
- 057A DEFW +0D6B
- 057C JP 05Cl,END1 Finished.
- THE 'CLEAR#' COMMAND ROUTINE
- As in the previous routine, this routine both 'checks' and 'executes' the command. All streams are closed in turn, \
- with bit 1 of FLAGS3 set to signal
- that the remaining buffer contents are to be erased (no data is sent, as
- opposed to the case of a CLOSE# command).
- 057F CLR#-SYN RST 10,CALBAS Advance CH-ADD.
- 0580 DEFW +0020
- 0582 CP +23 The character must be a '#'.
- 0584 NONSENSE JP NZ,04B2,OREPORT-1
- 0587 RST 10,CALBAS Advance CH-ADD again.
- 0588 DEFW +0020
- 058A CALL 05B7,ST-END Confirm end of statement and exit
- during syntax checking.
- 058D XOR A Start with stream 0.
- 058E ALL-STRMS PUSH AF Save stream number.
- 058F SET 1,(FLAGS3) Signal 'CLEAR# command'.
- 0593 CALL 1718,CLOSE Close the current stream.
- 0596 POP AF Restore stream number.
- 0597 INC A Each stream in turn is examined.
- 0598 CP +10 Continue until all streams 0..15
- 059A JR C,058E,ALL-STRMS have been closed.
- 059C JP 05C1,END1 Finished.
- THE 'EXCHANGE FILE SPECIFIERS' SUBROUTINE
- This subroutine exchanges the contents of D-STR1 area with those of the D-STR2 area and vice-versa.
- 059F EX-D-STR LD HL,+5CD6 Start of first area.
- 05A2 LD DE,+5CDE Start of 2nd area.
- 05A5 LD B,+08 Both areas are 8 bytes in length.
- 05A7 ALL-BYTES LD A,(DE) Fetch a byte from D-STR2.
- 05A8 LD C,(HL) Fetch a byte from D-STR1.
- 05A9 LD (HL),A Store into D-STR1 the byte coming
- from D-STR2.
- 05AA LD A,C Byte from D-STR1.
- 05AB LD (DE),A Store it into D-STRZ.
- 05AC INC HL Advance the pointers.
- 05AD INC DE
- 05AE DJNZ 05A7,ALL-BYTES Continue until the areas have
- been exchanged.
- 05B0 RET Finished.
- THE 'SEPARATOR' SUBROUTINE
- This short subroutine is called several times to see if the character held in the accumulator is a valid separator \
- (i.e. a comma or a semicolon). A return with the Zero flag reset is made if the character is not a separator.
- 05B1 SEPARATOR CP +2C Is the character a comma?
- 05B3 RET Z Return with zero flag set if so.
- 05B4 CP +3B Is the character a semicolon?
- 05B6 RET Return with zero flag set if so.
- THE 'END OF STATEMENT' ROUTINE
- After the syntax of the 'new' commands has been checked, a jump is made here to confirm that the statement is \
- finished. An error report is given if there are some characters left in the line. A return is made to the calling \
- routine only during runtime, otherwise the control returns to the 'main' ROM interpreter.
- 05B7 ST-END CP +0D Jump if the statement ends
- 05B9 JR Z,05BF,TEST-RET with ENTER.
- 05BB CP +3A Give an error if character is not
- 05BD JR NZ,0584,NONSENSE a colon (i.e. the statement is not
- finished).
- 05BF TEST-RET RST 18,CHKSYNTAX Return only during runtime,
- 05C0 RET NZ otherwise continue below.
- THE 'RETURN TO THE MAIN INTERPRETER' ROUTINE
- The control returns to the main interpreter, when a 'new' command has been checked or executed, for the interpretation \
- of the next statement.
- 05C1 END1 LD SP,(ERR-SP) Clear machine stack.
- 05C5 LD (ERR-NR),+FF Clear error code.
- 05C9 LD HL,+1BF4 Return address to main ROM is
- 05CC RST 18,CHKSYNTAX STMT-NEXT if syntax being checked.
- 05CD JR Z,05E0,RETAD-RUN-SYN
- 05CF LD A,+7F Give, an error if BREAK is pressed
- 05D1 IN A,(+FE) during runtime.
- 05D3 RRA
- 05D4 JR C,05DD,RETAD-RUN
- 05D6 LD A,+FE
- 05D8 IN A,(+FE)
- 05DA RRA
- 05DB JR NC,05E2,BREAK-PGM
- 05DD RETAD-RUN LD HL,+1B7D Return address during runtime is
- STMT-R-1.
- 05E0 RETAD-SYN PUSH HL Save the return address.
- 05E1 RST 0,MAIN-ROM Return to the main ROM interpreter.
- 'BREAK into program'
- 05E2 BREAK-PGM LD (ERR-NR),+14 Store the error code and call
- 05E6 RST 28,ROMERR the error handling routine.
- THE 'EVALUATE STRING EXPRESSION' SUBROUTINE
- A call to the main ROM 'EXPT-EXP' (class-9A) subroutine is made, to evaluate a string expression. During runtime the \
- parameters of the string (start and length) are returned in the DE and BC register pairs.
- 05E7 EXPT-STR RST 10,CALBAS Call 'EXPT-EXP' in the main ROM.
- 05E8 DEFW +1C8C
- 05EA RST 18,CHKSYNTAX Return if syntax is being checked
- 05EB RET Z
- 05EC PUSH AF Save the zero flag and the character
- following the string.
- 05ED RST 10,CALBAS Call 'STK-FETCH' in the main ROM to
- 05EE DEFW +2BF1 fetch the parameters.
- 05F0 POP AF Zero flag reset to signal 'runtime'
- 05F1 RET Finished.
- THE 'EVALUATE CHANNEL SPECIFIER' SUBROUTINE
- The subroutine is entered at EXPT-SPEC or at EXP-SPEC2 depending upon whether or not the character pointer is to be \
- updated to the next character. A single character string is evaluated, and its upper case ASCII value is stored into
- L-STR1 during runtime. If a separator is present after the single character string, then the routine continues into \
- EXPT-NUM.
- 05F2 EXPT-SPEC RST 10,CALBAS Advance CH-ADD.
- 05F3 DEFW +0020
- 05F5 EXP-SPEC2 CALL 95E7,EXPT-STR Evaluate string expression.
- 05F8 JR Z,060C,TEST-NEXT Jump if syntax is being checked.
- 05FA PUSH AF Save the character following the
- string.
- 05FB LD A,C 'A' holds the low byte of the
- string length.
- 05FC DEC A Jump if there is more than one
- 05FD OR B character in the string (also if the
- 05FE JR NZ,062D,NREPORT-3 string is null).
- 0600 LD A,(DE) Fetch the channel specifier.
- 0601 RST 10,CALBAS Call 'ALPHA' to see whethe nt isi
- 0602 DEFW +2C8D valid letter.
- 0604 JR NC,062D,NREPORT-3 Jump if it is not a valid letter
- 0606 AND +DF Make the letter upper case.
- 0608 LD (L-STR1),A Store the channel specifier.
- 060B POP AF The 'next character' is restored.
- 060C TEST-NEXT CP +0D Return if it is ENTER, or a colon,
- 060E RET Z
- 060F CP +3A
- 0611 RET Z
- 0612 CP +A5 Return also with a keyword.
- 0614 RET NC
- 0615 CALL 05B1,SEPARATOR Otherwise a separator must be found.
- 0618 JP NZ,04B2,OREPORT-1 Give an error if not found.
- 061B RST 10,CALBAS A numeric expression (i.e. drive
- 061C DEFW +0020 no.,station no., baud rate) is
- expected. But first advance CH-ADD
- past the separator.
- THE 'EVALUATE NUMERIC EXPRESSION' SUBROUTINE
- This subroutine is used whenever a single numeric expression is to be evaluated. The result is returned during runtime \
- into the BC register pair and into the
- D-STR1 system variable.
- 061E EXPT-NUM RST 10,CALBAS Call EXPT-NUM in the main ROM to
- 061F DEFW +1C82 evaluate the expression.
- 0621 RST 18,CHKSYNTAX Return if syntax is being checked.
- 0622 RET Z
- 0623 PUSH AF Save character following the
- expression and zero flag.
- 0624 RST 10,CALBAS Call FIND-INT2 to fetch the
- 0625 DEFW +1E99 value from calculator stack.
- 0627 LD (D-STR1),BC Store the value.
- 062B POP AF Restore character and zero flag.
- 062C RET Finished.
- 'Invalid device expression'
- 062D NREPORT-3 RST 20,SH-ERR Call the error handling
- 062E DEFB +02 routine.
- THE 'EVALUATE FILENAME' SUBROUTiNE
- A string expression is evaluated and, provided that the length is within the range 1..10 characters, the 'length' and \
- the 'start' of that string are stored into N-STR1 and (N-STR1 + 2).
- 062F EXPT-NAME RST 10,CALBAS Advance CH-ADD.
- 0630 DEFW +0020
- 0632 CALL 05E7,EXPT-STR Evaluate the string.
- 0635 RET Z Return if syntax is being checked.
- 0636 PUSH AF Save zero flag and 'next character'.
- 0637 LD A,C Give an error with null string.
- 0638 OR B
- 0639 JR Z,064C,NREPORT-4
- 063B LD HL,+000A Give the error also if 'length'
- 063E SBC HL,BC exceeds ten characters.
- 0640 JR C,064C,NREPORT-4
- 0642 LD (N-STR1),BC Store the 'length'.
- 0646 LD (N-STR1+2),DE Store the 'start'.
- 064A POP AF Restore A and zero flag.
- 064B RET Finished.
- 'Invalid name'
- 064C NREPORT-4 RST 20,SH-ERR Call the error handling
- 064D DEFB +03 routine.
- THE 'EVALUATE STREAM NUMBER' SUBROUTINE
- A single numeric expression is evaluated and the result, in the range 0..15, is stored into S-STR1 variable during \
- runtime.
- 064E EXPT-STRM RST 10,CALBAS Advance CH-ADD.
- 064F DEFW +0020
- 0651 RST 10,CALBAS Call EXPT-1NUM to evaluate a numeric
- 0652 DEFW +1C82 expression.
- 0654 RST 18,CHKSYNTAX Return if syntax is being checked.
- 0655 RET Z
- 0656 PUSH AF Save 'next character' and zero flag.
- 0657 RST 10,CALBAS Call FIND-INT1 to fetch the value.
- 0658 DEFW +1E99
- 065A CP +10 Test for numbers greater than 15.
- 065C JR NC,0663,NREPORT-2
- 065E LD (S-STR1),A Store stream number.
- 0661 POP AF Restore A and zero flag.
- 0662 RET Finished.
- 'Invalid stream number'
- 0663 NREPORT-2 RST 20,SH-ERR Call the error handling
- 0664 DEFB +01 routine.
- THE 'CHECK "M" PARAMETERS' SUBROUTINE
- A return to the calling routine is made only if L-STR1 denotes the Microdrive device being used, and if D-STR1 holds a \
- valid drive number.
- 0665 CHECK-M LD A,(L-STR1) Fetch channel specifier.
- 0668 CP +4D Is it "M"?
- 066A JP NZ,062D,NREPORT-3 Report the error if it is not.
- 066D CHECK-M-2 LD DE,(D-STR1) Fetch drive number.
- 0671 LD A,E Report an error if zero.
- 0672 OR D
- 0673 JR Z,0681,NREPORT-5
- 0675 INC DE Test against +FFFF.
- 0676 LD A,E Report an error if no drive number
- 0677 OR D has been evaluated.
- 0678 JR Z,0683,NREPORT-9
- 067A DEC DE Balance the 'INC' above.
- 067B LD HL,+0008 Is drive number within range 1..8?
- 067E SBC HL,DE
- 0680 RET NC Return if in range.
- 'Invalid drive number'
- 0681 NREPORT-5 RST 20,SH-ERR Call the error handling
- 0682 DEFB +04 routine.
- 'Missing drive number'
- 0683 NREPORT-9 RST 20,SH-ERR Call the error handling
- 0684 DEFB +08 routine.
- THE 'CHECK "M" PARAMETERS AND FILENAME' SUBROUTINE
- This subroutine adds to the tests performed by the previous one, also a check to N-STR1-hi, that holds +FF when no \
- filename has been evaluated.
- 0685 TEST-MNAM CALL 0665,CHECK-M Check "m" parameters.
- 0688 LD A,(N-STR1-hi) Fetch high byte of name length.
- 068B AND A Is it 0?
- 068C RET Z Return if so.
- 'Missing name'
- 068D RST 20,SH-ERR Call the error handling
- 068E DEFB +06 routine.
- THE 'CHECK STATION NUMBER' SUBROUTINE
- A return to the calling routine is made only if D-STR1 holds a valid station number in the range 0..64.
- 068F TEST-STAT LD DE,(D-STR1) Fetch station number.
- 0693 INC DE Test against +FFFF.
- 0694 LD A,E
- 0695 OR D No station number has been
- 0696 JR Z,06A1,NREPORT-8 evaluated, so give an error
- 0698 DEC DE Balance the 'INC' above.
- 0699 LD HL,+0040 Return only if the value is no
- 069C SBC HL,DE greater than 64 decimal.
- 069E RET NC
- 'Invalid station number'
- 069F RST 20,SH-ERR Call the error handling
- 06A0 DEFB +05 routine.
- 'Missing station number'
- 06A1 NREPORT-8 RST 20,SH-ERR Call the error handling
- 06A2 DEFB +07 routine.
- THE 'EVALUATE "X";N;"NAME"' SUBROUTINE
- A call to the subroutine EXPT-SPEC will evaluate the '"X";N', while the subroutine EXPT-NAME is used to evaluate the \
- filename. A separator must be found between them.
- 06A3 EXPT-EXPR CALL 05F2,EXPT-SPEC Evaluate channel specifier and drive
- number.
- 06A6 CALL 05B1,SEPARATOR A separator must be present.
- 06A9 JP NZ,04B2,OREPORT-1
- 06AC CALL 062F,EXPT-NAME Evaluate the filename.
- 06AF RET Finished.
- THE 'CHECK BAUD RATE' SUBROUTINE
- This routine simply checks that D-STR1 holds a valid baud rate (i.e. it is not set to +FFFF). Any value below +FFFF is \
- accepted (but later rounded to the nearest 'standard' value).
- 06B0 TEST-BAUD LD HL,(D-STR1) Fetch baud rate.
- 06B3 INC HL Accept any value except +FFFF.
- 06B4 LD A,L
- 06B5 OR H
- 06B6 RET NZ
- 'Missing baud rate'
- 06B7 RST 20,SH-ERR Call the error handling
- 06B8 DEFB +09 routine.
- THE 'EVALUATE STREAM OR EXPRESSION' SUBROUTINE
- This subroutine is used to deck the syntax of the MOVE Command. If the 'current' character is a hash sign (#), then a \
- stream number is evaluated and stored into S-STR1 during runtime. Otherwise a channel expression like '"x";n ["name"]' \
- is evaluated, and N-STR1, D-STR1 and L-STR1 are set as required and, if the channel specifier is "M" or "N", the \
- parameters are checked to be in range.
- 06B9 EXPT-EXP1 RST 10,CALBAS Advance CH-ADD.
- 06BA DEFW +0020
- 06BC CP +23 Is the present code an hash sign?
- 06BE JP Z,064E,EXPT-STRM Evaluate stream number if so,
- 06C1 CALL 05F5,EXP-SPEC2 otherwise evaluate "x";n.
- 06C4 CALL 05B1,SEPARATOR Jump if there is no further
- 06C7 JR NZ,06CC,ENDHERE separator.
- 06C9 CALL 062F,EXPT-NAME Otherwise deal with "filename".
- 06CC ENDHERE RST 18,CHKSYNTAX Return if syntax is being checked.
- 06CD RET Z
- 06CE LD A,(LSTR-1) Fetch channel specifier.
- 06D1 CP +54 Return if It is "T".
- 06D3 RET Z
- 06D4 CP +42 Return if it is "B".
- 06D6 RET Z
- 06D7 CP +4E But check station no. if it is "N".
- 06D9 JP Z,068F,TEST-STAT
- 06DC JP 0685,TEST-MNAM Otherwise check "m" parameters.
- 06DF...06FF Unused locations (all set to .FF).
- THE 'UNPAGE' SUBROUTINE
- This subroutine is actually made by a single RET instruction, but the hardware detects that the Program Counter \
- reaches the address +0700 and pages-in the 'main' ROM.
- 0700 UNPAGE RET RETurn to 'main' ROM.
- THE 'EVALUATE PARAMETERS' SUBROUTINE
- This very important subroutine is called to evaluate the syntax of the SAVE, LOAD, VERIFY and MERGE commands referred \
- to the 'new' channels. The subroutine is entered with CH-ADD pointing to the command code; on exit during runtime the \
- variables D-STR1, L-STR1, N-STR1, HD-00, HD-0B, HD-0D, HD-0F, HD-11 are properly set.
- 0701 EXPT-PRMS RST 10,CALBAS The next character is fetched from
- 0702 DEFW +0020 the line.
- 0704 CP +2A It must be a '*'.
- 0706 JR NZ,073C,OREP-1-2 Give an error if not a '*'.
- 0708 RST 10,CALBAS Advance CH-ADD past the '*'.
- 0709 DEFW +0020
- 070B CALL 05F5,EXP-SPEC2 Evaluate "x";n.
- 070E CALL 05B1,SEPARATOR Check that the separator dDEs exist.
- 0711 JR NZ,0716,NO-NAME Jump if no name is to be expected.
- 0713 CALL 062F,EXPT-NAME Evaluate "filename".
- 0716 NO-NAME PUSH AF The next character is saved.
- 0717 LD A,(L-STR1) Fetch channel specifier.
- 071A CP +4E Jump if the channel is not "N",
- 071C JR NZ,0122,NOT-NET
- 071E SET 3,(FLAGS3) otherwise signal "networking".
- 0722 NOT-NET POP AF Restore 'next character'.
- 0723 CP +0D Jump if the statement ends with
- 0725 JR Z,0750,END-EXPT ENTER, or
- 0727 CP +3A with a colon.
- 0729 JR Z,0750,END-EXPT
- 072B CP +AA Jump if the statement continues with
- 072D JR Z,0771,SCREEN$ SCREEN$.
- 072F CP +AF Jump with CODE.
- 0731 JR Z,0789,CODE
- 0733 CP +CA Jump with LINE.
- 0735 JR Z,973E,LINE
- 0737 CP +E4 Jump with DATA, otherwise give
- 0739 JP Z,07D2,DATA an error report.
- 'Nonsense in BASIC'
- 073C OREP-1-2 RST 20,SH-ERR Call the error handling
- 073D DEFB +00 routine.
- Now deal with LINE.
- 073E LINE RST 10,CALBAS Advance CH-ADD.
- 073F DEFW +0020
- 0741 RST 10,CALBAS Call EXPT-1NUM to evaluate the
- 0742 DEFW +1C82 autostart line number.
- 0744 CALL 05B7,ST-END Confirm end of statement, and exit
- during syntax checking.
- 0747 RST 10,CALBAS Fetch the autostart line number from
- 0748 DEFW +1E99 the calculator stack.
- 074A LD (HD-11),BC Store autostart line number.
- 074E JR 0753,PROG Jump forward.
- If there are no parameters (i.e. BASIC program), the syntax checking ends here.
- 0750 END-EXPT CALL 05B7,ST-END Confirm end of statement and exit
- during syntax checking.
- 0753 PROG XOR A Store 0 into HD-00 (signalling
- 0754 LD (HD-00),A 'program' file type).
- 0757 LD HL,(E-LINE) Address past the last location of
- variables area.
- 075A LD DE,(PROG) The 'start' of data is fetched
- 075E LD (HD-0D),DE from PROG, and stored into HD-0D.
- 0762 SCF This calculates
- 0763 SBC HL,DE ((E-LINE)-(PROG))-1, i.e. the length
- of the program and its variables.
- 0765 LD (HD-0B),HL The 'length' is stored.
- 0768 LD HL,(VARS) Now calculate (VARS)-(PROG),
- 076B SBC HL,DE i.e. the length of the program only.
- 076D LD (HD-0F),HL Store it into HD-0F.
- 0770 RET Finished.
- If the token is SCREEN$, the parameters are entered directly into the system variables.
- 0771 SCREEN$ RST 10,CALBAS Advance CH-ADD.
- 0772 DEFW +0020
- 0774 CALL 05B7,ST-END Confirm end of statement and exit
- during syntax checking.
- 0777 LD HL,+1B00 The 'length' of the display file
- 077A LD (HD-0B),HL and attributes is stored.
- 077D LD HL,+4000 The start address of the display
- 0780 LD (HD-0D),HL file.
- 0783 LD A,+03 Signal 'bytes' file type.
- 0785 LD (HD-00),A
- 0788 RET Finished.
- Now deal with CODE.
- 0789 CODE RST 10,CALBAS Advance CH-ADD.
- 078A DEFW +0020
- 078C CP +0D If there ate no further parameters,
- 078E JR Z,079A,DEFLT-0 jump to use '0' as default value.
- 0790 CP +3A Jump it there are parameters to be
- 0792 JR NZ,PAR-1 evaluated (i.e. the next character
- is not a colon).
- 0794 BIT 5,(FLAGS3) Give an error if SAVE "name"CODE is
- 0798 JR NZ,OREP-1-2 encountered by itself
- 079A DEFLT-0 RST 10,CALBAS A call to main ROM routine 'USE-ZERO'
- 079B DEFW +1CE6 is made to use a value of zero as
- default
- 079D JR 07A7,TEST-SAVE Jump forward.
- 079F PAR-1 RST 10,CALBAS Otherwise call EXPT-1NUM to use the
- 07A0 DEFW +1C82 specified value.
- 07A2 CALL 0581,SEPARATOR Jump if a separator is present.
- 07A5 JR Z,0782,PAR-2
- 07A7 TEST-SAVE BIT 5,(FLAGS3) Give an error if a parameter has been
- 07AB JR NZ,073C,OREP-l-2 missed in a SAVE name CODE command.
- 07AD RST 10,CALBAS Use zero also for the 2nd parameter,
- 07AE DEFW +1CE6
- 07B0 JR 07B8,END-CODE Jump forward.
- 07B2 PAR-2 RST 10,CALBAS Advance CH-ADD.
- 07B3 DEFW +0020
- 07B5 RST 10,CALBAS Evaluate the 2nd parameter by calling
- 07B6 DEFW +1CB2 EXPT-1NUM.
- 07B8 END-CODE RST 10,CALBAS Call GET-CHAR to fetch the 'last'
- 07B9 DEFW +0018 character in the statement.
- 07BB CALL 05B7,ST-END Confirm end of statement and exit if
- syntax is being checked.
- 07BE RST 10,CALBAS Fetch the "length" from the
- 07BF DEFW +1E99 calculator stack and
- 07C1 LD (HD-0B),BC store it.
- 07C5 RST 10,CALBAS Fetch the "start" from the calculator
- 07C6 DEFW +1E99 stack and store it.
- 07C8 LD (HD-0D),BC
- 07CC LD A,+03 Signal 'bytes' file type.
- 07CE LD (HD-00),A
- 07D1 RET Finished.
- Finally the routine to evaluate DATA parameters.
- 07D2 DATA BIT 6,(FLAGS3) Jump unless attempting to MERGE
- 07D6 JR Z,07DA,NO-M-ARR an array.
- 'MERGE error'
- 07D8 RST 20,SH-ERR Call the error handling
- 07D9 DEFB +14 routine.
- 07DA NO-M-ARR RST 10,CALBAS Advance CH-ADD to point to
- 07DB DEFW +0020 the array name.
- 07DD RST 10,CALBAS Call LOOK-VARS to look for the
- 07DE DEFW +28B2 array name.
- 07E0 SET 7,C Set bit 7 of array name.
- 07E2 JR NC,07F2,EXISTING Jump if handling an existing array.
- 07E4 LD HL,+0000 Signal 'using a new array'.
- 07E7 BIT 4,(FLAGS3) Jump forward if LOADing the array.
- 07EB JR NZ,080E,LD-DATA
- 07ED LD (ERR-NR),+01 Give the error report 'Variable not
- 07F1 RST 28,ROMERR found' if trying to SAVE a
- nonexistent array.
- 07F2 EXISTING JR Z,07F6,G-TYPE Continue only when handling a numeric
- or alphanumeric array,
- NOTE: This test fails to exclude simple strings, but the 'bug' (present in the main ROM) is corrected at 07FF.
- 07F4 NONS-BSC RST 20,SH-ERR 'Nonsense in BASIC'
- 07F5 DEFB +00
- 07F6 G-TYPE RST 18,CHKSYNTAX Jump forward if syntax is
- 07F7 JR Z,081C,END-DATA being checked.
- 07F9 BIT 5,(FLAGS3) Jump forward if not during a SAVE
- 07FD JR Z,0803,VR-DATA command.
- 07FF BIT 7,(HL) Give an error if trying to SAVE
- 0801 JR Z,07F4,NONS-BSC a simple string.
- 0803 VR-DATA INC HL Point to the 'length' of the array.
- 0804 LD A,(HL) Fetch low byte.
- 0805 LD (HD-0B-lo),A Store it.
- 0808 INC HL Point to high byte of 'length'.
- 0809 LD A,(HL) Fetch high byte.
- 080A LD (HD-0B-hi),A Store it.
- 080D INC HL Advance to the start of the
- array.
- 080E LD-DATA LD A,C Store array name into HD-0F.
- 080F LD (HD-0F-lo),A
- 0812 LD A,+01 Signal 'numeric array'.
- 0814 BIT 6,C Jump if really a numeric array.
- 0816 JR Z,0819,NUM-ARR
- 0818 INC A Otherwise A=2 to signal
- 'alphanumeric array'.
- 0819 NUM-ARR LD (HD-00),A Store file type.
- 081C END-DATA EX DE,HL DE holds the 'start' of the array
- (or +0000 with 'NEW' array to be
- loaded).
- 081D RST 10,CALBAS Advance CH-ADD.
- 081E DEFW +0020
- 0820 CP +29 Check that the ')' dDEs exist.
- 0822 JR NZ,07F4,NONS-BSC Report an error if not.
- 0824 RST 10,CALBAS Advance CH-ADD.
- 0825 DEFW +0020
- 0827 CALL 05B7,ST-END Confirm end of statement and exit
- during syntax checking.
- 082A LD (HD-0D),DE Store "start" of the array.
- 082E RET Finished.
- THE 'SAVE' COMMAND SYNTAX ROUTINE
- The actual saving is handled directly with "B" and "N" channels, or by SAVE-RUN if the 'N" channel is being used.
- 082F SAVE-SYN SET 5,(FLAGS3) Signal "Saving".
- 0833 CALL 0701,EXPT-PRMS Check syntax and set variables.
- 0836 LD A,(L-STR1) Fetch channel specifier.
- 0839 CP +42 Jump with "B" channel being used.
- 083B JR Z,084F,SA-HEADER
- 083D CP +4E Jump with other than "N" channel
- 083F JR NZ,0849,SAVE-M being used (i.e. with "M" channel).
- 0841 CALL 068F,TEST-STAT Check station number.
- 0844 CALL 0EA9,OP-TEMP-N Open a temporary "N" channel.
- 0847 JR 084F,SA-HEADER Jump forward.
- 0849 SAVE-M CALL 0685,TEST-MNAM Check "M" parameters.
- JP 1E7F,SAVE-RUN Jump forward.
- Now a loop is entered to SAVE to the "N" or "B" devices the 'header', i.e. the nine bytes taken from the system \
- variables HD-00 to HD-11.
- 084F SA-HEADER LD B,+09 Nine bytes are to be saved.
- 0851 LD HL,+5CE6 Start of HD variables.
- 0854 HD-LOOP CALL 0880,SA-BYTE Save the byte pointed by HL.
- 0857 INC HL Each header byte in turn is saved.
- 0858 DJNZ 0854,HD-LOOP
- 085A LD HL,(HD-0D) Fetch 'start of data block'.
- 085D BIT 3,(FLAGS3) Jump if "B" channel is being used.
- 0861 JR Z,086E,SA-BLOCK
- 0863 LD A,(HD-00) Jump also if saving a block of memory
- 0866 CP +03 (i.e. SAVE..CODE).
- 0868 JR NC,086E,SA-BLOCK
- 086A LD DE,+0014 Otherwise the data to be saved have
- 086D ADD HL,DE been moved up by '276' bytes after
- the insertion of the "N" channel.
- 086E SABLOCK LD BC,(HD-0B) Fetch the 'length' of the block.
- 0872 SA-BLK-LP LD A,C Jump forward when the counter has
- 0873 OR B reached zero.
- 0874 JR Z,087D,S-BLK-END
- 0876 CALL 0880,SA-BYTE Send the byte pointed by HL.
- 0879 DEC BC Decrement 'length'.
- 087A INC HL Point to next byte.
- 087B JR 0872,SA-BLK-LP Jump back until the whole block has
- been saved.
- 087D S-BLK-END JP 0988,TST-MR-M Jump forward to send the 'end of
- file' block (only with Network).
- THE 'SAVE A BYTE TO NETWORK OR RS232 LINK' SUBROUTINE
- The byte pointed by the HL register pair is fetched and sent by using the "B" or the "N" channel output routing, \
- depending upon the state of bit 3 of the FLAGS3 variable.
- 0880 SA-BYTE PUSH HL Save HL and BC register pairs.
- 0881 PUSH BC
- 0882 BIT 3,(FLAGS3) Test 'networking' bit.
- 0886 LD A,(HL) Fetch the byte to be saved.
- 0887 JR NZ,088E,SA-NET Jump if network is being used.
- 0889 CALL 0C5A,BCHAN-OUT Otherwise send the byte through the
- RS232 link.
- 088C JR 0891,SA-B-END Exit.
- 088E SA-NET CALL 0D6C,NCHAN-OUT Use "N" channel output routine to
- send the byte.
- 0891 SA-B-END POP BC Restore registers and return.
- 0892 POP HL
- 0893 RET
- TUE 'LOAD' COMMAND SYNTAX ROUTINE
- The syntax is checked with a single call to the EXPT-PRMS subroutine.
- 0894 LOAD-SYN SET 4,(FLAGS3) Signal 'doing a LOAD command'.
- 0898 CALL 0701,EXPT-PRMS Check syntax and set variables.
- 089B JP 08AF,LD-VF-MR Do the LOAD.
- THE 'VERIFY' COMMAND SYNTAX ROUTINE
- Again the syntax checking is handled by EXPT-PRMS.
- 089E VERIF-SYN SET 7,(FLAGS3) Signal 'doing a VERIFY command'.
- 08A2 CALL 0701,EXPT-PRMS Check syntax and set variables.
- 08A5 JP O8AF,LD-VF-MR Do the VERIFY.
- THE 'MERGE' COMMAND SYNTAX ROUTINE
- The syntax is handled by EXFT-PRMS the routine continues into the LOAD-VERIFY-MERGE routine below.
- 08A8 MRG-SYN SET 6,(FLAGS3) Signal 'doing a MERGE command'.
- 08AC CALL 0701,EXPT-PRMS Check syntax and set variables.
- THE "LOAD-VERIFY-MERGE' COMMANDS ROUTINE
- The action to be performed depends on the state of bits 4,6,7 of FLAGS3. The 'old' header Is expected to be in the HD \
- area, and is immediately transferred into the D-STR2 area, while the 'new' header is loaded into the HD area.
- 08AF LD-VF-MR LD HL,+5CE6 Start of HD area.
- 08B2 LD DE,+5CDE Start of D-STR2 area.
- 08B5 LD BC,+0007 There are '7' bytes to be copied
- (HD-11 is not affected).
- 08B8 LDIR Copy the 'old' header into the D-STR2
- area.
- 08BA LD A,(L-STR1) Fetch channel specifier.
- 08BD CP +4E Jump if network is being used.
- 08BF JR Z,08CD,TS-L-NET
- 08C1 CP +42 Jump if RS232 link is being used.
- 08C3 JR Z,08D3,TS-L-RS
- 08C5 CALL 0685,TEST-MNAM Check "M" parameters.
- 08C8 CALL 1580,F-M-HEAD Fetch first nine bytes from cartridge
- and store into HD area.
- 08CB JR 08F2,TEST-TYPE Jump forward.
- 08CD TS-L-NET CALL 068F,TEST-STAT Check station number.
- 08D0 CALL 0EA9,OP-TEMP-N Open a temporary "N" channel.
- 08D3 TS-L-RS LD HL,+5CE6 Start of HD area.
- 08D6 LD B,+09 Nine bytes are now expected.
- 08D8 LD-HEADER PUSH HL Save HL and BC register pairs.
- 08D9 PUSH BC
- 08DA BIT 3,(FLAGS3) Jump if using RS232 link.
- 08DD JR Z,08E7,LD-HD-RS
- 08E0 LD-HD-NET CALL 0D12,NCHAN-IN Fetch a byte from "N" channel.
- 08E3 JR NC,08E0,LD-HD-NET Repeat until the byte is acceptable.
- 08E5 JR 08EC,LD-HDR-2 Jump forward.
- 08E7 LD-HD-RS CALL 0B81,BCHAN-IN Fetch a byte from RS232 link.
- 08EA JR NC,08E7,LD-HD-RS Repeat until the byte is acceptable.
- 08EC LD-HDR-2 POP BC Restore registers.
- 08ED POP HL
- 08EE LD (HL),A Store the byte into the HO area.
- 08EF INC HL Advance the pointer.
- 08F0 DJNZ 08D8,LD-HEADER Go around the loop again.
- 08F2 TEST-TYPE LD A,(5CDE) Fetch 'old' type from D-STR2
- 08F5 LD B,A area and store into B register.
- 08F6 LD A,(HD-00) Fetch 'new' file type.
- 08F9 CP B Compare with the 'old' one.
- 08FA JR NZ,0902,NREPORT-N Give an error if it does not match.
- 08FC CP +03 Jump if handling a block of bytes.
- 08FE JR Z,0911,T-H-CODE
- 0900 JR C,0904,TST-MERGE Jump with other types (but refuse
- types greater than 3).
- 'Wrong file type'
- 0902 NREPORT-N RST 20,SH-ERR Call the error handling
- 0903 DEFB +16 routine.
- 0904 TST-MERGE BIT 6,(FLAGS3) Jump if doing a MERGE.
- 0908 JR NZ,0967,MERGE-BLK
- 090A BIT 7,(FLAGS3) Jump if not doing a VERIFY (i.e.
- 090E JP Z,09A3,LD-PR-AR doing a LOAD).
- Now deal with loading of files of type 3 (i.e. CODE and SCREENS), or verifying of all file types.
- 0911 T-M-CODE BIT 6,(FLAGS3) Allow for the loading or
- 0915 JR Z,0919,LD-BLOCK verifying, but not for the mergeing
- of a 'CODE' block.
- 'MERGE error'
- 0917 RST 20,SH-ERR Call the error handling
- 0918 DEFB +14 routine.
- 0919 LD-BLOCK LD HL,(+5CDF) Get 'old' length from D-STR2.
- 091C LD DE,(HD-0B) Get 'new' length.
- 0920 LD A,H Jump forward if 'old' length is 0
- 0921 OR L (i.e. not specified in the command).
- 0922 JR Z,0932,LD-BLK-2
- 0924 SBC HL,DE Accept the 'old' length if it is
- 0926 JR NC,0932,LD-BLK-2 greater than or equal to the
- 'new' one.
- 0928 BIT 4,(FLAGS3) But give an error if attempting
- 092C JR Z,0930,NREPORT-L to LOAD or VERIFY a larger block
- than has been requested.
- 'CODE error'
- 092E RST 20,SH-ERR Call the error handling
- 092F DEFB +13 routine.
- 'Verification has failed'
- 0930 NREPORT-L RST 20,SH-ERR Call the error handling
- 0931 DEFB +15 routine.
- 0932 LD-BLK-2 LD HL,(5CE1) Get 'old' start from D-STR2.
- 0935 LD A,(IX+4) Fetch specifier from the channel area.
- 0938 CP +CD Jump if not "M"+80, i.e. not a
- 093A JR NZ,0941,LD-BLK1 temporary "M" channel.
- 093C LD HL,(5CE4) But if the "M" channel is being
- used, the 'start' has been stored
- into +5CE4 (see +1583).
- 093F JR 0952,LD-BLK4 Jump forward.
- 0941 LD-BLK-3 BIT 3,(FLAGS3) Jump if not using the network.
- 0945 JR Z,0952,LD-BLK-4
- 0947 LD A,(HD-00) Jump if it is a block of bytes.
- 094A CP +03
- 094C JR Z,0952,LD-BLK-4
- 094E LD BC,+01l4 Otherwise the data has been moved
- 0951 ADD HL,BC up by '276' bytes after the
- insertion of the "N" channel.
- 0952 LD-BLK-4 LD A,H Use 'old' start if it has been
- 0953 OR L specified in the command,
- 0954 JR NZ,0959,LD-BLK-5 otherwise use 'new' start.
- 0956 LD HL,(HD-0D)
- 0959 LD-BLK-5 LD A,(HD-00) Use the 'start' in HL for types
- 095C AND A other than 'program'.
- 095D JR NZ,0962,LD~NO-PGM
- 095F LD HL,(PROG) But with 'program' type, the 'start'
- is pointed by PROG.
- 0962 LD-NO-PGM CALL 0A5C,LV-ANY Do the actual LOADing or VERIFYing.
- 0965 JR 0988,TST-MR-M Jump forward to close the channel
- used.
- Now consider the MERGEing of a program.
- 0967 MERGE-BLK LD A,(HD-11-hi) Continue only if the content of
- 096A AND +C0 HD-11 is sufficiently high, i.e. if
- 096C JR NZ,0973,NO-AUTOST the program was not saved with
- 'autostart'
- 096E CALL 17B9,RCL-T-CH Otherwise reclaim channels and give
- 0971 RST 20,SH-ERR a 'MERGE error'.
- 0972 DEFB +14
- 0973 NO-AUTOST LD BC,(HD-0B) Fetch 'length' of program to be
- 0977 PUSH BC merged and save it.
- 0978 INC BC Allows for a further location to
- insert the 'end marker'.
- 0979 RST 10,CALBAS Call BC-SPACES to make the
- 097A DEFW +0030 required room in workspace.
- 097C LD (HL),+80 Mark the end of the space.
- 097E EX DE,HL HL now points to the start of the
- space created.
- 097F POP DE Restore length of program.
- 0980 PUSH HL Save 'start' pointer.
- 0981 CALL 0A5C,LV-ANY Load the program in the workspace.
- 0984 POP HL Restore 'start' pointer.
- 0985 RST 10,CALBAS Do the mergeing with the existing
- 0986 DEFW +08CE program by entering into the main
- ROM 'MERGE' control routine.
- 0988 TST-MR-M LD A,(IX+4) Jump if the specifier is not "M"+80
- 098B CP +CD i.e. if other than "M" channel has
- 098D JR NZ,0994,TST-MR-N been used.
- 098F CALL 12A9,CLOSE-M2 Close the "M" channel.
- 0992 JR 09A0,MERGE-END Jump forward.
- 0994 TST-MR-N BIT 3,(FLAGS3) Exit immediately if the "B" output
- 0998 JR Z,09A0,MERGE-END has been used.
- 099A CALL 0EF5,SEND-NEOF Why?
- 099D CALL 17B9,RCL-T-CH Reclaim the channel.
- 09A0 MERGE-END JP 05C1,END1 Finished.
- The final branch of the routine deals with the LOADIng of a program or an array.
- 09A3 LD-PR-AR LD DE,(HD-0B) Fetch 'new' length.
- 09A7 LD HL,(5CE1) Fetch 'old' start (set to 0 when
- loading a 'new' array).
- 09AA PUSH HL Save it temporarily.
- 09AB LD A,H Jump if not a 'new' array.
- 09AC OR L
- 09AD JR NZ,09B5,LD-PROG
- 09AF INC DE Increment 'length' by 3, i.e. allows
- 09B0 INC DE for the insertion of array name and
- 09B1 INC DE two-byte length.
- 09B2 EX DE,HL Move 'length' into HL.
- 09B4 JR 09BE,TST-SPACE Jump forward.
- 09B5 LD-PROG LD HL,(5CDF) Fetch 'old' length (i.e. length of
- existing program or array) from
- D-STR2 area.
- 09B8 EX DE,HL HL holds the 'new' length.
- 09B9 SCF Jump forward if the program (or
- 09BA SBC HL,DE array) being loaded is no longer
- 09BC JR C,09C7,TST-TYPE than the existing one.
- 09BE TST-SPACE LD DE,+0005 Otherwise a check must be made to
- 09C1 ADD HL,DE ensure that there is sufficient space
- 09C2 LD B,H in memory for the program (or array)
- 09C3 LD C,L to be loaded, with a call to main ROM
- 09C4 RST 10,CALBAS 'TEST-ROOM' subroutine.
- 09C5 DEFW +1F05
- 09C7 TST-TYPE POP HL Restore 'old' start (+0000 when
- handling a 'new' array).
- 09C8 LD A,(HD-00) Jump if 'type' indicates a
- 09CB AND A BASIC program (+00).
- 09CC JR Z,0A15,SET-PROG
- 09CE LD A,H Jump unless an 'old' array is to be
- 09CF OR L erased before
- 09D0 JR Z,09F3,CRT-NEW loading the 'new' one.
- 09D2 LD A,(IX+4) If the channel specifier denotes
- 09D5 CP +CD other than temporary "M" channels
- 09D7 JR NZ,09DE,T-LD-NET (i.e. "M"+80H), the 'start' is
- already held in HL.
- 09D9 LD HL,(5CE4) Otherwise the start address of the
- array is fetched from D-STR2 area.
- 09DC JR 09E8,RCLM-OLD
- 09DE T-LD-NET BIT 3,(FLAGS3) Jump if using the 515232 link.
- 09E2 JR Z,09E8,RCLM-OLD
- 09E4 LD DE,+0114 Otherwise the array has been moved
- 09E7 ADD HL,DE '276' bytes up after the insertion
- of "N" channel.
- 09E8 RCLM-OLD DEC HL Points to the high byte of 'array
- length'.
- 09E9 LD B,(HL) Fetch high byte.
- 09EA DEC HL Points to the low byte.
- 09EB LD C,(HL) Fetch low byte.
- 09EC DEC HL Points to the array name.
- 09ED INC BC Include 'length' and 'name' in the
- 09EE INC BC array length.
- 09EF INC BC
- 09F0 RST 10,CALBAS Call RECLAIM-2 to delete the array.
- 09F1 DEFW +19E8
- 09F3 CRT-NEW LD HL,(E-LINE) Points to the end of variables area.
- 09F6 DEC HL
- 09F7 LD BC,(HD-0B) Fetch the length of the array to be
- loaded.
- 09FB PUSH BC Save it.
- 09FC INC BC Include in the length one byte for
- 09FD INC BC array name and two for 'length of
- 09FE INC BC array
- 09FF LD A,(5CE3) Fetch array name from D-STR2 area.
- 0A02 PUSH AF Save it briefly.
- 0A03 RST 10,CALBAS Call MAKE-ROOM to create the space
- 0A04 DEFW +1655 for the array.
- 0A06 INC HL Points to the first 'new' location
- inserted.
- 0A07 POP AF Restore array name and store into
- 0A08 LD (HL),A the 1st location.
- 0A09 POP DE Fetch 'array length'.
- 0A0A INC HL Store it into the following two
- 0A0B LD (HL),E locations.
- 0A0C INC HL
- 0A0D LD (HL),D
- 0A0E INC HL The array will be loaded from this
- location.
- 0A0F END-LD-PR CALL 0A5C,LV-ANY Load array or BASIC program.
- 0A12 JP 0988,TST-MR-M Jump back to close the channel.
- If the file loaded is a program, the space required is to be crested and some actions to be performed.
- 0A15 SET-PROG RES 1,(FLAGS3) Signal 'no autostart'
- 0A19 LD DE,(PROG) Fetch start of existing program.
- 0A1D LD HL,(E-LINE) Fetch end of existing program.
- 0A20 DEC HL
- 0A21 RST 10,CALBAS Call RECLAIM-1 in the main ROM to
- 0A22 DEFW +19E5 delete the program.
- 0A24 LD BC,(HD-0B) Fetch length of program and variables.
- 0A28 LD HL,(PROG) Fetch start address of program.
- 0A2B RST 10,CALBAS Call MAKE-ROOM to create the
- 0A2C DEFW +1655 required space.
- 0A2E INC HL Points to the first location.
- 0A2F LD BC,(HD-0F) Fetch program length.
- 0A33 ADD HL,BC Calculate and store the start of
- 0A34 LD (VARS),HL variables area.
- 0A37 LD A,(HD-11-hi) This is set to +FF when no autostart
- 0A3A LD H,A is required.
- 0A3B AND +C0
- 0A3D JR NZ,0A4E,NO-AUTO Jump with 'no autostart'.
- 0A3F SET 1,(FLAGS3) Signal 'autostart' (see +0049).
- 0A43 LD A,(HD-11-lo) Fetch low byte of autostart line
- 0A46 LD L,A number.
- 0A47 LD (NEWPPC),HL Store autostart line no.
- 0A4A LD (NSPPC),+00 Clear NSPPC to signal 'jump'.
- 0A4E NO-AUTO LD HL,(PROG) Fetch start address of program area.
- 0A51 LD DE,(HD-0B) Fetch program length.
- 0A55 DEC HL Make DATADD point to the last byte
- 0A56 LD (DATADD),HL of the CHANS area.
- 0A59 INC HL Balance the DEC above.
- 0A5A JR 0A0F,END-LD-PR Jump back to LOAD the new program.
- THE 'LOAD OR VERIFY' SUBROUTINE
- This subroutine is used to LOAD or VERIFY (depending upon the state of bit 7 of FLAGS3 system variable) a block of \
- bytes. It must be entered with the 'start' and the 'length' in the HL and DE register pairs, and with all system \
- variables properly set.
- 0A5C LV-ANY LD A,D Return if 'length' is zero.
- 0A5D OR E
- 0A5E RET Z
- 0A5F LD A,(IX+4) Fetch channel specifier and jump if
- 0A62 CP +CD handling with RS232 or network.
- 0A64 JR NZ,0A6A,LV-BN
- 0A66 CALL 15A9,LV-MCH LOAD or VERIFY from Microdrive.
- 0A69 RET Finished.
- 0A6A LV-BN PUSH HL Save 'start' and 'length'.
- 0A6B PUSH DE
- 0A6C BIT 3,(FLAGS3) Jump if RS232 link is being used.
- 0A70 JR Z,0A79,LV-B
- 0A72 LV-N CALL 0D12,NCHAN-IN Fetch a byte by using the "N" channel
- 0A75 JR NC,0A72,LV-N Input routine.
- 0A77 JR 0A7E,LV-BN-E Jump forward.
- 0A79 LV-B CALL 0B81,BCHAN-IN Fetch a byte by using the "B" channel
- 0A7C JR NC,0A79,LV-B input routine.
- 0A7E LV-BN-E POP DE Restore 'length' and decrease it.
- 0A7F DEC DE
- 0A80 POP HL Restore 'start'.
- 0A81 BIT 7,(FLAGS3) Jump when VERIFYING.
- 0A85 JR NZ,0A8A,VR-BN
- 0A87 LD (HL),A The actual LOAD, i.e. store the
- received byte.
- 0A88 JR 0A8F,LVBN-END Jump forward.
- 0A8A VR-BN CP (HL) The actual VERIFY, i.e. compare the
- received byte with that held in
- memory.
- 0A8B JR Z,0A8F,LVBN-END Continue only if the bytes are equal.
- 'Verification has failed'
- 0A8D RST 20,SH-ERR Call the error handling
- 0A8E DEFB +15 routine.
- 0A8F LVBN-END INC HL Move 'start' on to address the next
- location.
- 0A90 LD A,E Repeat until 'length' has reached 0.
- 0A91 OR D
- 0A92 JR NZ,0A6A,LV-BN
- 0A94 RET Finished.
- THE 'LOAD "RUN" PROGRAM' ROUTINE
- First the various system variables are properly set, then a nine-byte header is fetched from the first record of the \
- program called 'run'. The routine continues
- into the middle of the LOAD~VERIFY-MERGE commands routine.
- 0A95 LOAD-RUN LD BC,+0001 Load from drive 1.
- 0A98 LD (D-STR1),BC
- 0A9C LD BC,+0003 The filename 'run' is three
- 0A9F LD (N-STR1),BC characters in length.
- 0AA3 LD BC,+0AC6 The filename is stored from this
- 0AA6 LD (N-STR1+2),BC location.
- 0AAA SET 4,(FLAGS3) Signal 'loading'.
- 0AAE CALL 0753,PROG Set HD variablea as required.
- 0AB1 LD HL,+5CE6 Copy 'old' header into D-STR2 area.
- 0AB4 LD DE,+5CDE
- 0AB7 LD BC,+0009
- 0ABA LDIR Clear the 'jump' signal set by using
- 0ABC SET 7,(NSPPC) the RUN command.
- 0AC0 CALL 1580,F-M-HEAD Load the 'new' 9-byte header.
- 0AC3 JP 08F2,TEST-TYPE Jump back in the middle of the
- LOAD-VERIFY-MERGE commands routine.
- 0AC6 DEFM "run" The 'run' filename.
- The RS-232 link routines
- THE 'SET "BAUD" SYSTEM VARIABLE' ROUTINE
- This routine is entered with a baud rate in the range 0. .65534 in the system
- variable D-STR1. It rounds the value to the nearest 'standard' value and sets the BAUD system variable with the \
- appropriate timing constant. It is used by the 'FORMAT' command routine.
- 0AC9 SET-BAUD LD BC,(D-STR1) Fetch baud rate.
- 0ACD LD HL,+0AEF Start of RS232 timing constants table.
- 0AD0 NXT-ENTRY LD E,(HL) Fetch an entry in the DE register
- 0AD1 INC HL pair.
- 0AD2 LD D,(HL)
- 0AD3 INC HL
- 0AD4 EX DE,HL Pass the value to HL.
- 0AD5 LD A,H Fetch high byte.
- 0AD6 CP +48 Jump if the end of the table has been
- 0AD8 JR NC,0AE4,END-SET reached.
- 0ADA AND A Jump also if this value is greater
- 0ADB SBC HL,BC than or equal to the supplied one.
- 0ADD JR NC,0AE4,END-SET
- 0ADF EX DE,HL Restore the 'pointer' in HL.
- 0AE0 INC HL Skip the constant and jump back
- 0AE1 INC HL to examine the next table entry.
- 0AE2 JR 0AD0,NXT-ENTRY
- 0AE4 END-SET EX DE,HL Restore the pointer in HL.
- 0AE5 LD E,(HL) Fetch the timing constant.
- 0AE6 INC HL
- 0AE7 LD D,(HL)
- 0AE8 LD (BAUD),DE Store the constant.
- 0AEC JP 05C1,END1 Finished.
- THE 'RS232 TIMING CONSTANTS' TABLE
- The '9' entries in this table are the 'standard' baud rate values (from 75 to 19200), each one followed by the 'timing \
- constant' to be stored in the BAUD system variable.
- 0AEF DEFW +0032 First baud rate=50 (but the constant
- 0AF1 DEFW +0A82 is for 75 baud).
- 0AF3 DEFW +006E 2nd baud rate=110.
- 0AF5 DEFW +04C5 Constant for 110 baud.
- 0AF7 DEFW +012C 3rd baud rate=300.
- 0AF9 DEFW +01BE Constant for 300 baud.
- 0AFB DEFW +0258 4th baud rate=600.
- 0AFD DEFW +00DE Constant.
- 0AFF DEFW +04B0 5th baud rate=1200.
- 0B01 DEFW +006E Constant.
- 0B03 DEFW +0960 6th baud rate=2400.
- 0B05 DEFW +0036 Constant.
- 0B07 DEFW +12C0 7th baud rate=4800.
- 0B09 DEFW +001A Constant.
- 0B0B DEFW +2580 8th baud rate=9600.
- 0B0D DEFW +000C Constant.
- 0B0F DEFW +4B00 Last baud rate=l9200.
- 0B11 DEFW +0005 Constant.
- THE 'OPEN RS232 CHANNEL IN CHANS AREA' SUBROUTINE
- This subroutine opens a permanent "B" or "T" channel (depending upon the specifier held in L-STR1) at the end of the \
- CHANS area. On return, the DE
- register pair will hold the start of the channel.
- 0B13 OP-RS-CH LD HL,(PROG) The start address
- 0B16 DEC HL of the channel.
- 0B17 LD BC,+000B The channel is '11' bytes in length.
- 0B1A PUSH BC
- 0B1B RST 10,CALBAS Call MAKE-ROOM to create the required
- 0B1C DEFW +1655 space.
- 0B1E POP BC Restore 'length'.
- 0B1F PUSH DE Save address of last byte in the
- inserted area.
- 0B20 CALL 1691,REST-N-AD Restore start address of 'filename' if
- it has been moved up after the
- insertion of the new space.
- 0B23 POP DE Restore 'end of channel' address.
- 0B24 LD HL,+0B6E Last byte in the "T" channel data
- table.
- 0B27 LD BC,+000B Length of the table.
- 0B2A LDDR Copy the 'T' channel data.
- 0B2C INC DE Point to the 1st location of the
- channel.
- 0B2D LD A,(L-STR1) Fetch channel specifier.
- 0B30 CP +42 Return if the requested channel was
- 0B32 RET NZ not the 'B' channel.
- 0B33 PUSH DE Save channel start address.
- 0B34 LD HL,+0005 Point to the 'shadow ROM output
- 0B37 ADD HL,DE routine' pointer.
- 0B38 LD DE,+0C5A the address of the BCHAN—OUT routine.
- 0B3B LD (HL),E Store the low byte.
- 0B3C INC HL
- 0B3D LD (HL),D Store the high byte.
- 0B3E INC HL Point to the 'shadow ROM input
- routine' pointer.
- 0B3F LD DE,+0B75 The address of the B—INPUT routine,
- 0B42 LD (HL),E Store the low byte.
- 0B43 INC HL
- 0B44 LD (HL),D Store the high byte.
- 0B45 POP DE Restore channel start address.
- 0B46 RET Finished.
- THE 'ATTACH CHANNEL TO A STREAM' ROUTINE
- The entry point is OP-RSCHAN if the channel is "B" or "T", otherwise the routine is entered at OP-STREAM with "N" \
- channel (from 0EA6), with DE holding the channel start address. The correct displacement is calculated for the stream \
- whose number is held in S-STR1, and stored in the STRMS area.
- 0B47 OP-RSCHAN CALL 0Bl3,OP-RS-CH Create the channel area.
- 0B4A OP-STREAM LD HL,(CHANS) Calculate the displacement to be
- 0B4D DEC HL stored in STRMS.
- 0B4E EX DE,HL
- 0B4F AND A
- 0B50 SBC HL,DE
- 0B52 EX DE,HL Pass the displacement to DE.
- 0B53 LD HL,+5C16 Location in STRMS for stream 0.
- 0B56 LD A,(S-STR1) Fetch stream number and
- 0B59 RLCA double it.
- 0B5A LD C,A Move the offset to the BC register
- 0B5B LD B,+00 pair.
- 0B5D ADD HL,BC Index into the STRMS area.
- 0B5E LD (HL),E Store the displacement.
- 0B5F INC HL
- 0B60 LD (HL),D
- 0B61 JP 05C1,END1 Finished.
- THE '"T" CHANNEL DATA' TABLE
- The '11' bytes that composes a "T" RS232 channel are as follows:
- 0B64 DEFW +0008 Main ROM 'output' routine.
- 0B66 DEFW +0008 Main ROM 'input' routine.
- 0B68 DEFB +54 "T" (channel specifier).
- 0B69 DEFW +0C3C Shadow ROM 'output' routine.
- 0B6B DEFW +0B6F Shadow ROM 'input' routine.
- 0B6D DEFW +000B Length of this channel.
- THE '"T" CHANNEL INPUT' ROUTINE
- The actual 'input' is handled by the CALL-INP routine; the service routine is TCHAN-IN below.
- 0B6F T-INPUT LD HL,+0B7B Address of TCHAN-IN routine.
- 0B72 JP 0CBD,CALL-INP Jump forward.
- THE '"B" CHANNEL INPUT' ROUTINE
- As with the "T" channel, the 'input' is handled by CALL-INP; however the service routine is BCHAN-IN.
- 0B75 B-INPUT LD HL,+0B81 Address of BCHAN-IN routine.
- 0B78 JP 0CBD,CALL-INP Jump forward.
- THE '"T" CHANNEL INPUT' SERVICE ROUTINE
- The only difference in respect to the "B" input is that the most significant bit of the received character is always \
- cleared.
- 0B7B TCHAN-IN CALL 0B81,BCHAN-IN Use the "B" channel input service
- routine.
- 0B7E RES 7,A Accept only codes in the range +00...
- +7F (ASCII 7 bit).
- 0B80 RET Finished.
- THE '"B" CHANNEL INPUT' SERVICE ROUTINE
- This subroutine is also called by using the hook code +1D; it always returns
- carry set if an acceptable byte has been read in the A register from the RS232 link, or zero flag set when no byte has \
- been read.
- 0B81 BCHAN-IN LD HL,+5CC7 Fetch contents of SER-FL-lo system
- 0B84 LD A,(HL) variable.
- 0B85 AND A Proceed in receiving the byte if it
- 0B86 JR Z,0B8E,REC-BYTE holds zero.
- 0B88 LD (HL),+00 Otherwise clear SER-FL-lo and fetch
- 0B8A INC HL the byte from SER-FL-hi.
- 0B8B LD A,(HL)
- 0B8C SCF Signal 'acceptable code'.
- 0B8D RET
- 0B8E REC-BYTE LD A,+7F Read port +7FFE.
- 0B90 IN A,(+FE)
- 0B92 RRCA Rotate bit 0 into carry.
- 0B93 JR C,0B9A,REC-PROC Jump if SPACE not being pressed.
- 0B95 LD (ERR-NR),+14 Otherwise give the 'Break into
- 0B99 RST 28,ROMERR program' error report.
- 0B9A REC-PROC DI Disable interrupts.
- 0B9B LD A,(IOBORD) Fetch new border colour.
- 0B9E OUT (+FE),A Change border colour.
- 0BA0 LD DE,(BAUD) Fetch timing constant.
- 0BA4 LD HL,+0320 Repeat '800' times the test.
- 0BA7 LD B,D Copy timing constant into the BC
- 0BA8 LD C,E register pair.
- 0BA9 SRL B Make BC hold (constant/2).
- 0BAB RR C
- 0BAD LD A,+FE Make high the CTS line.
- 0BAF OUT (+EF),A
- Now a loop is entered to check if a 'start bit' is found from the TXdata line. A 'start bit' is detected if the TXdata \
- line is high for at least '77' T cycles. If after about 25 ms no 'start bit' is found, the routine continues forward.
- 0BB1 READ-RS IN A,(+F7) Read TXdata line.
- 0BB3 RLCA Shift state into carry.
- 0BB4 JR NC,0BC5,TST-AGAIN Jump if the line has a low level.
- 0BB6 IN A,(+F7) Repeat the test three times, i.e. make
- 0BB8 RLCA sure that TXdata is still high after
- 0BB9 JR NC,0BC5,TST-AGAIN 77 T cycles,
- 0BBB IN A,(+F7)
- 0BBD RLCA
- 0BBE JR NC,0BC5,TST-AGAIN
- 0BC0 IN A,(+F7)
- 0BC2 RLCA
- 0BC3 JR C,0BD1,START-BIT Jump if the beginning of a 'start bit'
- is found.
- 0BC5 TST-AGAIN DEC HL Decrease the counter.
- 0BC6 LD A,H Repeat the test until the counter
- 0BC7 OR L reaches zero.
- 0BC8 JR NZ,0BB1,READ-RS
- 0BCA PUSH AF Save zero flag set.
- 0BCB LD A,+EE Make the CTS line low again.
- 0BCD OUT (+EF),A
- 0BCF JR 0BF0,WAIT-1 Jump forward to repeat the test.
- This loop is used to read the eight data bits that follows the 'start' bit. First, a delay equal to ((BAUD)*1.5)*26 T \
- cycles is entered, so the first reading is made at the middle of the first data bit. The seven subsequent readings are \
- separated by a delay of (47+26*(BAUD)) T cycles, that is the length of each bit.
- 0BD1 START-BIT LD H,B Get (BAUD/2) into HL.
- 0BD2 LD L,C
- 0BD3 LD B,+80 Set a marker into bit 7.
- 0BD5 DEC HL Decrease HL three times, i.e. short
- 0BD6 DEC HL the loop by 78 T cycles, balancing
- 0BD7 DEC HL the time spent before.
- 0BD8 SERIAL-IN ADD HL,DE Add (BAUD) to HL.
- 0BD9 NOP Wait 4 T cycles.
- 0BDA BD-DELAY DEC HL Insert a delay (26*BAUD) T cycles in
- 0BDB LD A,H length.
- 0BDC OR C
- 0BDD JR NZ,0BDA,BD-DELAY
- 0BDF ADD A,+00 Wait 7 T cycles.
- 0BE1 IN A,(+F7) Read a bit.
- 0BE3 RLCA Shift it into carry flag, then into
- 0BE4 RR B the B register.
- 0BE6 JR NC,0BD8,SERIAL-IN Repeat until the 'marker' is found
- (i.e., 8 bits have been read),
- 0BE8 LD A,+EE Make the CTS line having a low level.
- 0BEA OUT (+EF),A
- 0BEC LD A,B Fetch the received byte.
- 0BED CPL Complement it (the bits are sent
- inverted through the RS232 link).
- 0BEE SCF Signal 'acceptable codes' when exit.
- 0BEF PUSH AF Save the byte and carry flag.
- 0BF0 WAIT-1 ADD HL,DE Make HL hold (BAUD).
- 0BF1 WAIT-2 DEC HL Wait until the first stop bit is
- 0BF2 LD A,H finished.
- 0BF3 OR L
- 0BF4 JR NZ,0BF1,WAIT-2
- 0BF6 ADD HL,DE
- 0BF7 ADD HL,DE
- 0BF8 ADD HL,DE HL now holds (BAUD)*3.
- Now a loop similar to that at 0BB1 is entered. If the TXdata line is found high for at least 77 T cycles, the \
- 'sending' device is sending the 'start' bit for a second byte, even if the CTS line has a low signal level. This byte \
- is to be read and stored into SER-FL.
- 0BF9 T-FURTHER DEC HL Decrease counter.
- 0BFA LD A,L Repeat test until it has reached 0.
- 0BFB OR H
- 0BFC JR Z,0C36,END-RS-IN Exit if there is no further byte to
- be received.
- 0BFE IN A,(+F7) Read TXdata line.
- 0C08 RLCA Shift received bit into carry.
- 0C01 JR NC,0BF9,T-FURTHER Jump back with TXdats low.
- 0C03 IN A,(+F7) Otherwise repeat the test three times
- 0C05 RLCA to ensure that TXdata is still
- 0C06 JR NC,0BF9,T-FURTHER high after 77 T cycles,
- 0C08 IN A,(+F7)
- 0C0A RLCA
- 0C0B JR NC,0BF9,T-FURTMER
- 0C0D IN A,(+F7)
- 0C0E RLCA
- 0C10 JR NC,0BF9,T-FURTHER
- 0C12 LD H,D Fetch timing constant into HL.
- 0C13 LD L,E
- 0C14 SRL H Calculate (BAUD)/2 into HL.
- 0C16 RR L
- The next instructions are the same as those stored from 0BD3 above, so they are not commented.
- 0C18 LD B,+00
- 0C1A DEC HL
- 0C1B DEC HL
- 0C1C DEC HL
- 0C1D SER-IN-2 ADD HL,DE
- 0C1E NOP
- 0C1F BD-DELAY2 DEC HL
- 0C20 LD A,H
- 0C21 OR L
- 0C22 JR NZ,0C1F,BD-DELAY2
- 0C24 ADD A,+00
- 0C26 IN A,(+F7)
- 0C28 RLCA
- 0C29 RR B
- 0C2B JR NC,0C1D,SER-IN-2
- Finally, the last byte received is stored into SER-FL, and the first one returned into the A register.
- 0C2D LD HL,+5CC7 Points to SER-FL-lo
- 0C30 LD (HL),+01 Set it to +01, indicating that
- SER-FL-hi holds a valid byte.
- 0C32 INC HL Points to SER-FL-hi.
- 0C33 LD A,B Fetch the received byte.
- 0C34 CPL Complement it and store into
- 0C35 LD (HL),A SER-FL-hi.
- 0C36 END-RS-IN CALL 0CA9,BORDREST Restore border colour.
- 0C39 POP AF Restore first byte and flags.
- 0C3A EI Enable interrupts.
- 0C3B RET Finished.
- THE '"T" CHANNEL OUTPUT' ROUTINE
- The "t" channel output involves the 'sending' over the RS232 link of the character held into the A register, provided \
- that it is within the range +20...+7F. Characters from +80 to +A4 are sent as '?', while tokens are de-tokenised. \
- Codes lower than +20 are ignored, except for +0D that sends both CR and LF codes. The routine unfortunately contains a \
- mistake as it does not suppress the 'leading space' flag (bit 0 of FLAGS) as required. The result is that when sending \
- two tokens (i.e., THEN GOTO), two spaces are inserted between them, instead of one. The correct routine should include \
- the following two instructions after the final 'RET C': 'JR NZ,BCHAN-OUT' and 'SET 0,(FLAGS)', and a 'RES 0,(FLAGS)' \
- before the 'CP +7F'.
- 0C3C TCHAN-OUT CF +A5 Jump if the code is not a token code.
- 0C3E JR C,0C46,NOT-TOKEN
- 0C40 SUB +A5 Reduce range of token,
- 0C42 RST 10,CALBAS and detokenise it by calling
- 0C43 DEFW +0C10 recursively this routine via main ROM
- 0C45 RET 'PO-TOKENS' routine.
- 0C46 NOT-TOKEN CP +7F Jump if the character is not a
- 0C48 JR C,0C4C,NOT-GRAPH graphic character.
- 0C4A LD A,+3F Otherwise send a '?'.
- 0C4C NOT-GRAPH CP +0D Is the code 'ENTER'?
- 0C4E JR NZ,0C57,NOT-CR Jump if not.
- 0C50 CALL 0C5A,BCHAN-OUT Otherwise send the CR code.
- 0C53 LD A,+0A Follow it with a linefeed code.
- 0C55 CALL 0C5A,BCHAN-OUT
- 0C57 NOT-CR CP +20 Ignore all codes lower than +20,
- 0C59 RET C otherwise use BCHAN-OUT below to send
- the character.
- THE '"B" CHANNEL OUTPUT' ROUTINE
- The 8 bits that forms the byte held in the A register are sent inverted through the RS232 link, after an initial \
- 'start' bit (high), and followed by two 'stop' bits (or rather a 'double length' stop bit, with low signal level). As \
- with 'b' channel input, the bits have a fixed length, depending upon the selected baud rate. This subroutine is also \
- called by the 'hook code' +1E.
- 0C5A BCHAN-OUT LD B,+0B Counts '11' bits.
- 0C5C CPL Invert the eight data bits.
- 0C5D LD C,A C holds the byte to be sent.
- 0C5E LD A,(IOBORD) Fetch new border colour.
- 0C61 OUT (+FE),A Change border colour.
- 0C63 LD A,+EF Reset CTS and select RS232.
- 0C65 OUT (+EF),A
- 0C67 CPL
- 0C68 OUT (+F7),A Make RXdata have a low signal level.
- 0C6A LD HL,(BAUD) Fetch timing constant.
- 0C6D LD D,H Copy into DE register pair.
- 0C6E LD E,L
- 0C6F BD-DEL-1 DEC DE Firstly wait (26*(BAUD)) T cycles.
- 0C70 LD A,D
- 0C7l OR E
- 0C72 JR NZ,0C6F,BD-DEL-1
- 0C74 TEST-DTR LD A,+7F Read port +7FFE (SPACE key).
- 0C76 IN A,(+FE)
- 0C78 OR +FE Read port +FEFE (CAPS SHIFT key) only
- 0C7A IN A,(+FE) if SPACE is being pressed.
- 0C7C RRA Test bit 0.
- 0C7D JP NC,0CB4,BRK-INOUT Give an error if BREAK is pressed.
- 0C80 IN A,(+EF) Read DTR line.
- 0C82 AND +08 Only bit 3.
- 0C84 JR Z,0C74,TEST-DTR Jump back until DTR is found high.
- 0C86 SCF Set carry flag (start bit).
- 0C87 DI Disable interrupts.
- 0C88 SER-OUT-L ADC A+00 In fact, shift carry into bit 0 of
- accumulator.
- 0C8A OUT (+F7),A Send this bit over RS232 link.
- 0C8C LD D,H Copy timing constant into DE.
- 0C8D LD E,L
- 0C8E BD-DEL-2 DEC DE Wait 26*(BAUD) T cycles after having
- 0C8F LD A,D sent each bit.
- 0C90 OR E
- 0C9l JR NZ,0C8E,BD-DEL-2
- 0C93 DEC DE Wait 6 T cycles.
- 0C94 XOR A Clear A for next pass.
- 0C95 SRL C Shift the bit to be sent into carry.
- 0C97 DJNZ 0C88,SER-OUT-L Loop for all 11 bits.
- 0C99 DI Enable interrupts.
- 0C9A LD A,+01
- 0C9C LD C,+EF
- 0C9E LD B,+EE
- 0CA0 OUT (+F7),A Make RXdata having a high level.
- 0CA2 OUT (C),B Turn off RS232.
- 0CA4 BD-DEL-3 DEC HL Insert a final delay before returning
- 0CA5 LD A,L via the border-restore routine
- 0CA6 OR H below.
- 0CA7 JR NZ,0CA4,BD-DEL-3
- THE 'BORDER COLOUR RESTORE' SUBROUTINE
- This subroutine is used whenever the border colour has been changed to IOBORD during an I/O operation, and needs to be \
- restored to its original state.
- 0CA9 BORD-REST LD A,(BORDCR) Fetch lower screen attribute.
- 0CAC AND +38 Only bits 3,4,5, i.e. BORDER.
- 0CAE RRCA Rotate colour into bits 0,l,2.
- 0CAF RRCA
- 0CB0 RRCA
- 0CB1 OUT (+FE),A Restore colour.
- 0CB3 RET Finished.
- THE 'BREAK INTO I/O OPERATION' ROUTINE
- Whenever BREAK is pressed during an I/O operation, the interrupts have to be enabled, the border colour to be restored \
- and the error "BREAK into program" to be given.
- 0CB4 BRK-INOUT EI Enable interrupts.
- 0CB5 CALL 0CA9,BORD-REST Restore border colour.
- 0CB8 LD (ERR-NR),+l4 Store error code and give the error.
- 0CBC RST 28,ROMERR
- THE 'CALL-INP' ROUTINE
- All inputs from "B", "T", "N" and "M" channels are handled by loading HL with the address of the service 'input' \
- routine for the channel, and then jumping to this routine. The routine handles both INPUT and INKEY$ commands referred \
- to the
- 'new' channels.
- 0CBD CALL-INP RES 3,(TVFLAG) 'The mode is to be considered as being
- unchanged'
- 0CC1 PUSH HL Save address of the service routine.
- 0CC2 LD HL,(ERR-SP) Points to the error address.
- 0CC5 LD E,(HL) Fetch low byte of error addres
- 0CC6 INC HL
- 0CC7 LD D,(HL) Fetch high byte.
- 0CC8 AND A Prepare for a true subtraction.
- 0CC9 LD HL,+107F This is ED-ERROR.
- 0CCC SBC HL,DE Jump forward if not during an INPUT
- 0CCE JR NZ,0CFB,INKEY$ command.
- Now deal with 'INPUT #' command referred to an Interface channel.
- 0CD0 POP HL Restore address of service routine.
- 0CD1 LD SP,(ERR-SP) Clear machine stack.
- 0CD5 POP DE Remove ED-ERROR.
- 0CD6 POP DE The old value of ERR-SP
- 0CD7 LD (ERR-SP),DE is restored.
- 0CDB IN-AGAIN PUSH HL Save address of the service routine.
- 0CDC LD DE,+0CE1 Return address is INPUT-END below.
- 0CDF PUSH DE
- 0CE0 JP (HL) Jump to the service routine.
- When the character has been read from the required channel, a return is made here to add the character to the INPUT \
- line, or to return if the character is ENTER.
- 0CE1 INPUT-END JR C,0CED,ACC-CODE Jump with acceptable codes.
- 0CE3 JR Z,0CEA,NO-READ Jump with no data read.
- 0CE5 OREPORT-8 LD (ERR-NR),+07 Otherwise report the 'End of file'
- 0CE9 RST 28,ROMERR error.
- 0CEA NO-READ POP HL Restore address of service routine
- 0CEB JR 0CDB,IN-AGAIN and try again.
- 0CED ACC-CODE CP +0D Jump if the code is ENTER.
- 0CEF JR Z,0CF7,END-INPUT
- 0CF1 RST 10,CALBAS Otherwise the character is to be added
- 0CF2 DEFW +0F85 to the INPUT line - so enter into the
- main ROM 'ADD-CHAR' subroutine.
- 0CF4 POP HL Restore address of service routine
- 0CF5 JR 0CDB,IN-AGAIN and read the next byte.
- 0CF7 END-INPUT POP HL Remove address of service routine.
- 0CF8 JP 0700,UNPAGE Return to the main ROM calling
- routine.
- Enter here to deal with the INKEY$ function (a single character is returned).
- 0CFB INKEY$ POP HL Address of service routine.
- 0CFC LD DE,+0D01 Return address is INK$-END below.
- 0CFF PUSH DE
- 0D00 JP (HL) Jump to the service routine.
- After having read the byte, a return is made here.
- 0D01 INK$-END RET C Return with acceptable codes, or
- 0D02 RET Z no character read.
- 0D03 BIT 4,(FLAGS3) Give the 'end of file' error if bit
- 0D07 JR Z,0CE5,OREPORT-8 4 of FLAGS3 is reset.
- 0D09 OR +01 Otherwise the MOVE command has been
- 0D0B RET used - so return with carry and zero
- flags both reset.
- The Network routines
- THE '"N" CHANNEL INPUT' ROUTINE
- The actual 'input' is handled via the CALL-INP routine above. The service routine is NCHAN-IN.
- 0D0C N-INPUT LD HL,+0D12 Address of NCHAN-IN routine.
- 0D0F JP 0CBD,CALL-INP Jump to the control routine.
- THE '"N" CHANNEL INPUT' SERVICE ROUTINE
- The actual "n" input involves the reading of the byte from the network buffer. If no other bytes are found in the \
- buffer, a further data block is to be received (provided that the 'current' block is not the 'EOF' one) before reading \
- the byte.
- 0D12 NCHAN-IN LD IX,(CURCHL) Fetch start of "n" channel.
- 0D16 LD A,(NCOBL) This holds 0 while 'receiving'.
- 0D19 AND A Jump if it is a "read" file.
- 0D1A JR Z,0D1E,TEST-BUFF
- 'Reading a 'write' file'
- 0D1C RST 20,SH-ERR Call the error handling
- 0D1D DEFB +0D routine.
- 0D1E TEST-BUFF LD A,(NCIBL) Fetch number of bytes to be read
- from the buffer.
- 0D21 AND A If NCIBL holds zero, then the buffer
- 0D22 JR Z,0D38,TST-N-EOF is empty.
- 0D24 LD E,(NCCUR) Otherwise fetch the current position.
- 0D27 DEC A Decrease number of bytes to be read
- from the buffer.
- 0D28 SUB E Subtract position from the result.
- 0D29 JR C,0D38,TST-N-EOF Jump if all bytes have been read.
- 0D2B LD D,+00 Clear D register.
- 0D2D INC E Update the character position.
- 0D2E LD (NCCUR),E
- 0D31 ADD IX,DE Points to 'byte to be read - 20'.
- 0D33 LD A,(IX+20) Read the byte.
- 0D36 SCF Carry is set to signal 'acceptable
- byte'.
- 0D37 RET Finished.
- If no data is found in the buffer, consider whether this data block is the last one.
- 0D38 TST-N-EOF LD A,(NCTYPE) Fetch packet type.
- 0D3B AND A Jump if packet type = 0.
- 0D3C JR Z,0D3F,GET-N-BUF Indicating a normal packet.
- 0D3E RET Otherwise return with both zero and
- carry flags reset to signal 'end of
- file'.
- A further data block is to be received if the current data block is not the 'EOF' one.
- 0D3F GET-N-BUF LD A,(IOBORD) Fetch new border colour.
- 0D42 OUT (+FE),A Change border colour.
- 0D44 DI Disable interrupts.
- 0D45 TRY-AGAIN CALL 0F1E,WT-SCOUT Wait for a 'scout' leader.
- 0D48 JR NC,0D5F,TIME-OUT Jump if 'time out' occurs.
- 0D4A CALL 0E18,GET-NBLK Wait for header and data block.
- 0D4D JR NZ,0D5F,TIME-OUT Jump with any error.
- 0D4F EI Enable interrupts.
- 0D51 CALL 0CA9,BORD-REST Restore border colour.
- 0D53 LD (NCCUR),+00 The position is 0.
- 0D57 LD A,(NTTYPE) Copy this byte
- 0D5A LD (NCTYPE),A to signal the packet type.
- 0D5D JR 0D1E,TEST-BUFF Try now to fetch the byte.
- 0D5F TIME-OUT LD A,(NCIRIS) Fetch destination station no.
- 0D62 AND A There is no 'time-out' when
- 0D63 JR Z,0D45,TRY-AGAIN broadcasting (NCIRIS=0).
- 0D65 DI Enable interrupts.
- 0D66 CALL 0CA9,BORD-REST Restore border colour.
- 0D69 AND +00 Return with zero flag set and carry
- 0D6B RET reset, signalling that no data has
- been read.
- THE '"N" CHANNEL OUTPUT' ROUTINE
- The routine that handles the "n" channel output is quite straightforward. It involves the storing of the byte held in \
- the A register into the 255-byte buffer; whenever this is filled, the subroutine S-PACK-1 is called, so the data block \
- is sent over the network.
- 0D6C NCHAN-OUT LD IX,(CURCHL) Point to start of channel.
- 0D70 LD B,A Save temporarily into B the byte to
- be sent.
- 0D71 LD A,(NCIBL) This holds 0 for 'write' channel.
- 0D74 AND A Set zero flag as required.
- 0D75 LD A,B Restore the byte to be sent.
- 0D76 JR Z,0D7A,TEST-OUT Continue only if using a 'write'
- channel (NCIBL=0).
- 'Writing to a 'read' file'
- 0D78 RST 20,SH-ERR Call the error handling
- 0D79 DEFB +0C routine.
- 0D7A TEST-OUT LD E,(NCOBL) Fetch length of output buffer.
- 0D7D INC E Include the current byte in the
- length count.
- 0D7E JR NZ,0D88,ST-BF-LEN Jump unless the buffer is filled.
- 0D80 PUSH AF Save the byte to be sent.
- 0DB1 XOR A Signal normal packet type.
- 0D82 CALL 0DAB,S-PACK-1 Send the packet.
- 0D85 POP AF Restore the byte to be sent.
- 0D86 LD E,+01 'Only 1 byte in the buffer'.
- 0D88 ST-BF-LEN LD (NCOBL),E Store new buffer length.
- 0D8B LD D,+00 Make IX point to 'first free byte in
- 0D8D ADD IX,DE the buffer - 20).
- 0D8F LD (IX+20),A Store byte in the buffer.
- 0D92 RET Finished.
- THE 'OUT-BLK-N' SUBROUTINE
- This subroutine calls the OUTPAK subroutine to send over the network the block of bytes starting from (HL), and whose \
- length is held into the E register. Then a 'response byte' is to be received into the NTRESP system variable (provided \
- that you are not using the broadcast). The zero flag is returned reset if no
- response byte has been received. This subroutine is called from SEND-PACK below to send the header and then the data \
- block over the network.
- 0D93 OUT-BLK-N CALL 0FC5,OUTPAK Send the block.
- 0D96 LD A,(NCIRIS) This holds zero when broadcasting.
- 0D99 AND A
- 0D9A RET Z Return if broadcasting.
- 0D93 LD HL,+5CCD Address of NTRESP system variable.
- 0D9E LD (HL),+00 First clear NTRESP.
- 0DA0 LD E,+01 A single byte is to be received
- into NTRESF.
- 0DA2 CALL 0F92,INPAK Get response byte (+01).
- 0DA5 RET NZ Return with zero flag reset if the
- network was inactive.
- 0DA6 LD A,(NTRESP) Now fetch the response byte.
- 0DA9 DEC A It must be +01.
- 0DAA RET Return with zero flag reset if it
- is not +01.
- THE 'S-PACK-1' SUBROUTINE
- This subroutine simply calls SEND-PACK below. If broadcasting, a certain delay is to be inserted after having sent the \
- packet.
- 0DAB S-PACK-1 CALL 0DB2,SEND-PACK Send the packet.
- 0DAE RET NZ Return if not broadcasting.
- 0DAF JP 0E0F,BR-DELAY Otherwise exit through the delay
- routine.
- THE 'SEND-PACK' SUBROUTINE
- This subroutine is also called by using 'hook code' +30. It sends over the network a SCOUT leader, followed by the \
- header and the data block for the "n" channel pointed by the IX register. On entry, the A register may hold +01 or +00 \
- depending upon whether the block is the 'end of file' one or not. NCNUMB is incremented before returning. The zero \
- flag is returned set if the destination station number denotes that the 'broadcasting' is being used.
- 0DB2 SEND-PACK LD (NCTYPE),A Store packet type, i.e. +00 for
- normal, +01 for end of file.
- 0DB5 LD B,(NCOBL) Fetch block length.
- 0DB8 LD A,(IOBORD) Fetch new border colour.
- 0DBB OUT (+FE),A
- 0DBD PUSH IX Make DE point to the start of the
- 0DBF POP DE "n" channel.
- 0DC0 LD HL,+0015 Add this offset to point to
- 0DC3 ADD HL,DE the start of the 255-byte buffer.
- Now the checksum of the data block is calculated.
- 0DC4 XOR A First clear A register.
- 0DC5 CHKS1 ADD A,(HL) Add this byte.
- 0DC6 INC HL Point to next location.
- 0DC7 DJNZ 0DC5,CHKS1 Repeat for all bytes in the block.
- 0DC9 LD (NCDCS),A Store the checksum obtained.
- 0DCC LD HL,+000B Now points to NCIRIS.
- 0DCF ADD HL,DE
- 0DD0 PUSH HL Save the pointer.
- The checksum of the header is calculated.
- 0DD1 LD B,+07 Checksum is for 7 bytes.
- 0DD3 XOR A Clear A register.
- 0DD4 CHKS2 ADD A,(HL) Add this byte.
- 0DD5 INC HL Point to next location.
- 0DD6 DJNZ 0DD4,CHKS2 Repeat for all bytes.
- 0DD8 LD (HL),A Store checksum into NCHCS.
- Now the SCOUT leader, followed by the 8-byte header, is sent, and a response code is received (if not broadcasting).
- 0DD9 DI Disable interrupts.
- 0DDk SENDSCOUT CALL 9Fb1,SEND-SC Send the SCOUT (i.e. a leader
- followed by station number).
- 0DD0 POP HL Restore pointer to NCIEIS,
- 0DD1 PUSH HL i.e. Start of header block.
- 0DD1 LD 1,48 The header Is made by '8' bytes.
- 0DE1 CALL 9II93,OUT-BLK-N The header is sent, and the response
- code received.
- 0DE4 JR NZ,0DDA,SENDSCOUT Repeat until successfully.
- 0DE6 PUSH IX Make HL point to the start of the "n"
- 0DE8 POP HL channel.
- 0DE9 LD DE,+0015 Now points to the start of the data
- 0DEC ADD HL,DE block.
- 0DED LD E,(NCOBL) Get block length.
- 0DF0 LD A,E If NCOBL is zero (i.e. if the buffer
- 0DF1 AND A is empty); no data needs to be sent.
- 0DF2 JR Z,0DFD,INC-BLKN
- 0DF4 LD B,+20 Wait 418 T cycles before proceeding.
- 0DF6 SP-DL-1 DJNZ 0DF6,SP-DL-1
- Now the data block is sent, and NCNUMB updated.
- 0DF8 CALL 0D93,OUT-BLK-N Send the data block and get the
- response code.
- 0DF8 JR NZ,0DDA,SENDSCOUT Repeat until succesfully.
- 0DF0 INC_BLKN INC (NCNUMB-lo) Increment low byte of block number.
- 0E00 JR NZ,0E05,SP-N-END
- 0E02 INC (NCNUMB-hi) Increment also high byte when low
- byte reaches zero.
- 0E05 SP-N-END POP HL Restore pointer to NCIRIS.
- 0E06 CALL 0CA9,BORD-REST Restore border colour.
- 0E09 EI Enable interrupts.
- 0E0k LD A,(NCIRIS) Get destination station number.
- 0E00 AND A Set zero flag if NCIRIS is 0 (i.e.
- broadcasting).
- 0E01 RET Finished.
- THE 'BR-DELAY' SUBROUTINE
- This short subroutine inserts a delay of about 40 msec. when it is called. Its task is that of separating outputs \
- during 'broadcasts' transmissions.
- 0E01 BR-DELAY LD DE,+1500 Set a counter.
- 0E12 DL-LOOP DEC DE Decrease it.
- 0E13 LD A,E Check whether the counter has reached
- 0E14 OR D zero.
- 0E15 JR NZ,0E12,DL-LOOP Repeat if not.
- 0E17 RET Finished.
- THE 'HEADER AND DATA BLOCK RECEIVING' ROUTINES
- The following two subroutines are used to get from the Network an 8-byte header and a data block respectively. Both \
- require that the IX register point to the start of the "n" channel. The zero flag is returned reset with any error.
- 0E18 GET-NBLK LD HL,+5CCE Point to NTDEST, i.e. first byte of
- header block.
- 0E1B LD E,+08 Length of the block.
- 0E1D CALL 0F92,INPAK Receive the header.
- 0E20 RET NZ Return with network inactive (i.e.
- no header has been found).
- 0E21 LD HL,+5CCE Points again to NTDEST.
- Now the header checksum is calculated, and compared with NTCHS checksum.
- 0E24 XOR A First clear A.
- 0E25 LD B,+07 Checksum for next 7 bytes.
- 0E27 CHKS3 ADD A,(HL) Add this byte.
- 0E28 INC HL Point to next location.
- 0E29 DJNZ 0E27,CHKS3 Repeat for all bytes.
- 0E2B CP (HL) Compare with NTCHS checksum.
- 0E2C RET NZ Return if they do not match.
- Some other tests are now made.
- 0E2D LD A,(NTDEST) Fetch destination station number.
- 0E30 AND A Jump if broadcasting.
- 0E31 JR Z,0E40,BRCAST
- 0E33 CP (NCSELF) Otherwise compare with NCSELF.
- 0E36 RET NZ Return if this data block is for
- another Spectrum.
- 0E37 LD A,(NTSRCE) Source station number.
- 0E3A CP (NCIRIS) Compare against NCIRIS.
- 0E3D RET NZ Return if the transmitting Spectrum
- is not the required one.
- 0E3E JR 0E45,TEST-BLKN Jump forward.
- 0E40 BRCAST LD A,(NCIRIS) Make sure that it is broadcasting
- 0E43 OR A (i.e. NTDEST and NCIRIS both 0).
- 0E44 RET NZ Return if you are not waiting for a
- broadcast.
- 0E45 TEST-BLKN LD HL,(NTNUMB) Fetch number of block being
- transmitted.
- 0E48 LD E,(MCNUMB-lo) Fetch number of expected block.
- 0E4B LD D,(NCNUMB-hi)
- 0E4E AND A
- 0E4F SBC HL,DE Jump if the block received is the
- 0E51 JR Z,0E65,GET-NBUFF expected one.
- 0E53 DEC HL Accept also the previous block
- 0E54 LD A,H (already received, but 'response'
- 0E55 OR C lost).
- 0E56 RET NZ But refuse other blocks.
- 0E57 CALL 0E65,GET-NBUFF Receive the block.
- 0E5A DEC (NCNUMB-lo) Decrease NCNUMB, i.e. 'ignore' this
- 0E5D JR NC,0E62,GETNB-END block.
- 0E5F DEC (NCNUMB-hi)
- 0E62 GETNB-END OR +01 Return with zero flag reset, so that
- 0E64 RET the procedure is repeated.
- Now follows the second routine, used to get the data block from the network.
- 0E65 GET-NBUFF LD A,(NTDEST) This holds zero when broadcasting.
- 0E68 AND A
- 0E69 CALL NZ,0FBE,SEND-RESP Send the 'response' code (for the
- header) unless broadcasting.
- 0E6C LD A,(NTLEN) Fetch data block length.
- 0EbF AND A Jump if the data block is empty.
- 0E73 JR Z,0E93,STORE-LEN
- 0E72 PUSH IX Make HL point to the start of the
- 0E74 POP HL channel.
- 0E75 LD DE,+0015 Point to the start of data buffer.
- 0E78 ADD HL,DE
- 0E79 PUSH HL Save start address.
- 0E?A LD E,A Length of the block to be received
- goes into E.
- 0E7B CALL 0F92,INPAK Receive the data block.
- 0E7E POP HL Restore start address.
- 0E7F RET NZ Return if the network was inactive.
- 0E83 LD A,(NTLEN) Pass length of data block to the
- 0E83 LD B,A B register.
- 0E84 LD A,(NTDCS) Start with the data block checksum.
- 0E87 CHKS4 SUB (HL) Subtract current byte.
- 0E88 INC HL Point to next location.
- 0E89 DJNZ 0E87,CHKS4 Repeat for all bytes in the block.
- 0E8B RET NZ Return if the checksum is wrong.
- 0E8C LD A,(NTDEST) This holds 0 when broadcasting.
- 0E8F AND A
- 0E93 CALL NZ,0FBE,SEND-SCOUT Send response code for the data block
- (unless broadcasting).
- 0E93 STORE-LEN LD A,(NTLEN) Fetch data block length.
- 0E96 LD (NCIBL),A Copy it into NCIBL.
- 0E99 INC (NCNUMB-lo) Finally increment block number.
- 0E9C JR NZ,0EA1,GETBF-END
- 0E9E INC (NCNUMB-hi)
- 0EA1 GETBF-END CP A Return with zero flag set to signal
- 0EA2 RET 'block successfully received'.
- THE 'OPEN "N" CHANNEL' COMMAND ROUTINE
- This routine is the actual OPEN command referred to the network. It is called from the 'OPEN' command syntax routine \
- to attach a permanent "n" channel to a stream.
- 0EA3 OPEN-N-ST CALL 0EB5.OP-PERM-N Open a permanent "n" channel.
- 0EA6 JP 0B4A,OP-STREAM Attach it to a stream.
- THE 'OPEN TEMPORARY "N" CHANNEL' SUBROUTINE
- This subroutine is also called by using the 'hook code' +2D. It simply opens a permanent 'n' channel, and then makes \
- it "temporary" by setting bit 7 of the channel specifier. The variables are to be set as for the OP-PERM-N subroutine \
- below. The start of the channel area is returned in the IX index register.
- 0EA9 OP-TEMP-N CALL 0EB5,OP-PERM-N Open a permanent "n" channel.
- 0EAC LD IX,(CURCHL) Fetch start of channel area.
- 0EB1 SET 7,(IX+4) Make the channel temporary.
- 0EB4 RET Finished.
- THE 'OPEN PERMANENT "N" CHANNEL" SUBROUTINE
- On entry, D-STR1 must hold the destination station number to be copied into NCIRIS, while NTSTAT must hold the own \
- station number to be copied into NCSELF. A permanent "n" channel is created into the CHANS area, and it is made, the \
- 'current' channel. The routine returns the channel base address into the DE register pair.
- 0EB5 OP-PERN-N LD HL,(PROG) Fetch start address of the channel
- 0EB8 DEC HL created.
- 0EB9 LD BC,+0114 Length of the channel.
- 0EBC PUSH BC Save it briefly.
- 0EBD RST 10,CALBAS Call main ROM 'MAKE-ROOM' subroutine
- 0EBE DEFW +1655 to make the required space.
- 0EC3 INC HL Point to the first new location.
- 0EC1 POP BC Restore 'length' of space inserted.
- 0EC2 CALL I691,RESThN.,.AD Restore start address of 'filename'
- possibly moved up after the
- insert ion.
- 0EC5 LD (CHURCHL),HL Make the Channel 'current'
- 0EC8 EX DE,HL Pass 'start' to DE.
- 0EC9 LD HL,+0EEA Start of "n" Channel data.
- 0ECC LD BC,+000B Length of data.
- 0ECF LDIR Copy the data into the channel area.
- 0ED1 LD A,(DSTR-1) Fetch destination station number.
- 0ED4 LD (DE),A Copy it into NCIRIS.
- 0ED5 INC DE Points to NCSELF.
- 0ED6 LD A,(NTSTAT) Fetch own station number.
- 0ED9 LD (DE),A Copy it into NCSELF.
- 0EDA INC DE Points to NCNUMB.
- 0EDB XOR A Clear it.
- 0EDC LD (DE),A
- 0EDD LD H,D Fill the remaining bytes with zeros.
- 0EDE LD L,E
- 0EDF INC DE
- 0EE0 LD BC,+0106
- 0EE3 LDIR
- 0EE5 LD DE,(CURCHL) Fetch start address of the channel.
- 0EE9 RET Finished.
- THE '"N" CHANNEL DATA' TABLE
- The '11' bytes that composes the initial part of a "N" channel are as follows:
- 0EEA DEFW +0008 Main ROM 'output' routine.
- 0EEC DEFW +0008 Main ROM 'input' routine.
- 0EEE DEFB +43 "N" (channel specifier)
- 0EEF DEFW +0D6C Shadow ROM 'output' routine.
- 0EF1 DEFW +0D0C Shadow ROM 'input' routine.
- 0EF3 DEFW +0114 Length of "n" channel.
- THE 'SEND EOF BLOCK TO NETWORK' SUBROUTINE
- This subroutine is used whenever the remaining buffer contents of the current "n" channel have to be sent as the "end \
- of file" block.
- 0EF5 SEND-NEOF LD IX,(CURCHL) Fetch start address of channel.
- 0EF9 LD A,(NCOBL) Fetch data block length.
- 0EFC AND A Return if this is a 'read' channel
- 0EFD RET Z (NCOBL=0).
- 0EFE LD A,+01 Signal 'EOF' packet.
- 0F00 JP 0DAB,S-PACK-1 Send packet and exit.
- THE 'NETWORK STATE' SUBROUTINE
- This subroutine returns when the network is considered to be 'resting', i.e. when the network line is inactive for 3-4 \
- ms. The exact time is 'randomised' as to prevent Spectrums from claiming the network at the same time.
- 0F03 NET-STATE LD A,R Get a random value.
- 0F05 CP +C0 Allow only the range 192..255.
- 0F07 LD B,A Pass the value to B.
- 0F08 CALL 0F8E,CHK-REST Check network state.
- 0F0B JR C,0F03,NET-STATE Repeat until the network is resting,
- or BREAK pressed.
- 0F0D RET Return when 'ready to claim'.
- THE 'CHECK-RESTING' SUBROUTINE
- This subroutine checks the state of the network and returns with carry reset if it is inactive for a 'sufficient' time \
- determined by the value passed to the B register ((B * 54) - 22) T cycles).
- 0F0E CHK-REST LD A,+7F First check SPACE key.
- 0F10 IN A,(+FE)
- 0F12 RRCA
- 0F13 JR NC,0F4D,E-READ-N Give an error if it is pressed.
- 0F15 MAKESURE PUSH BC Wait 21 T cycles.
- 0F16 POP BC
- 0Fl7 IN A,(+F7) Check network state.
- 0F19 RRCA Only bit 0.
- 0F1A RET C Return if the network is already
- claimed by another Spectrum.
- 0F1B DJNZ 0F15,MAKESURE Repeat the test.
- 0F1D RET Return with carry reset when network
- is resting.
- THE 'WAIT-SCOUT' SUBROUTINE
- This subroutine is used to identify a SCOUT leader from the network. This is done by checking the network line for \
- about 7000 T cycles, to prove whether it is resting. After this, the network is examined until it is active. At this \
- point, the SCOUT is identified. The subroutine returns the carry flag reset if 'time-out' has occurred and no SCOUT \
- has been identified. Remember that there are no 'time-outs' when broadcasting.
- 0F1E WT-SCOUT LD HL,+01C2 Set a counter.
- 0F21 CLAIMED LD B,+80 This constant allows the network to
- be tested for 6890 T cycles.
- 0F23 CALL 0F9E,CHK-REST Check network state.
- 0F26 JR NC,0F35,WT-SYNC Jump for waiting the SCOUT.
- 0F28 DEC HL Loop again if the network is active,
- 0F29 DEC HL until the counter reaches zero.
- 0F2A LD A,H
- 0F2B OR C
- 0F2C JR NZ,0F21,CLAIMED
- 0F2E LD A,(NCIRIS) There is no 'time-out' when
- 0F31 AND A broadcasting.
- 0F32 JR Z,0F21,CLAIMED
- 0F34 RET Return with carry reset to signal
- 'time-out'.
- Now the SCOUT pulse is waited for.
- 0F35 WT-SYNC IN A,(+F7) Read the network line.
- 0F37 RRCA Only bit 0.
- 0F38 JR C,0F56,SCOUT-END Jump if the SCOUT is identified.
- 0F3A CD A,+7F Check SPACE key.
- 0F3C IN A,(+FE)
- 0F3E RRCA
- 0F3F JR NC,0F4O,E-READ-N Give an error if it is pressed.
- 0F41 DEC HL decrease counter.
- 0F42 LD A,H Repeat until it reaches zero.
- 0F43 OR C
- 0F44 JR NZ,0F35,WT-SYNC
- 0F46 CD A,(NCIRIS) There is no 'time-out' when
- 0F49 AND A broadcasting.
- 0F4A JR Z,0F35,WT-SYNC
- 0F4C RET Carry reset signals 'time-out',
- 0F4D E-READ-N EI Enable interrupts.
- 0F4E CALL 0CA9,BORD-REST Restore border colour.
- 0F51 LD (ERR-NR),+14 Give the error 'BREAK into program'.
- 0F55 RST 28,ROMERR
- NOTE: The above routine is a 'duplicate' of BRK-INOUT at 0CB4.
- When the SCOUT has been identifIed, the routine waits until it is finished.
- 0F56 SCOUT-END LD L,+09 Set a counter.
- 0F58 LP-SCOUT DEC L Decrease it.
- 0F59 SCF Return with carry set (to signal
- 0F5A RET Z 'scout identified') when the counter
- reaches zero.
- 0F5B LD B,+0E Wait a while.
- 0F5D DELAY-SC DJNZ 0F5D,DELAY-SC
- 0F5F JR 0F58,LP-SCOUT Go back into the loop,
- THE 'SEND-SCOUT' SUBROUTINE
- This is the opposite of the preceding routine; the SCOUT leader, followed by an 8-bit station number, is sent over the \
- network. After having sent every bit, a test is made to see if the network has the expected state from the current bit \
- value; if any error is found, then the whole procedure is repeated.
- 0F61 SEND-SC CALL 0F03,NET-STATE Wait until the network Is resting.
- 0F64 LD C,+F7 Output port.
- 0F66 LD HL,+0009 H=0 (leader bit value)
- L=9 (bit counter).
- 0F69 LD A,(NTSTAT) Fetch global station number,
- 0F6C LD E,A Pass it to the E register.
- 0F6D IN A,(+F7) Start again if some data is found
- 0F6F RRCA into the network line.
- 0F70 JR C,0F61,SEND-SC
- 0F72 ALL-BITS OUT (C),H Send a bit.
- 0F74 LD D,H Save the bit into D.
- 0F75 LD H,+00 Clear H.
- 0F77 RLC E Rotate 'station no.' left.
- 0F79 RL H Bit 7 of station no. goes into bit
- 0 of H.
- 0F7B LD B,+08 Wait 196 T cycles.
- 0F7D S-SC-DEL DJNZ 0F7D,S-SC-DEL
- 0F7F IN A,(+F7) Read the network.
- 0F81 AND +01 Only bit 0.
- 0F83 CP D Repeat again the procedure if the
- 0F84 JR Z,0F61,SEND-SC network does not have the right state
- from the current bit value.
- 0F86 DEC L Decrease bit counter.
- 0F87 JR NZ,0F72,ALL-BITS Send all bits.
- 0F89 LD A,+01 Make network inactive.
- 0F8B OUT (+F7),A
- 0F8D LD B,+0E Wait 184 T cycles.
- 0F8F END-S-DEL DJNZ 0F8F,END-S-DEL
- 0F91 RET Finished.
- THE 'INPAK' SUBROUTINE
- This basic subroutine is used to receive from the network a block of bytes. On entry. HL must hold the address from \
- which the bytes will be loaded, while E must hold the length of the block. The subroutine returns with the zero flag \
- reset if the network is found inactive and no data has been read. The bits are read every 40 T cycles.
- 0F92 INPAK LD B,+FF Set a counter.
- 0F94 N-ACTIVE IN A,(+F7) Read the network.
- 0F96 RRA Only bit 3.
- 0F97 JR C,0F9D,INPAK-2 Jump if found active.
- 0F99 BJNZ 0F94,N-ACTIVE Otherwise try again.
- 0F9B INC B Return with zero flag reset to
- 0F9C RET indicate 'network inactive'.
- Now the block is received.
- 0F9D INPAK-2 LD B,E B holds the length of the block.
- 0F9E INPAK-L LD E,+80 Set a marker into bit 7.
- 0FAI LD A,+CE Make Wait and CTS having a low level,
- 0FA2 OUT (+EF),A enable network comm.
- 0FA4 NOP Wait 48 T cycles at the start of each
- 0FA5 NOP byte.
- 0FA6 INC IX
- 0FA8 DEC IX
- 0FAA INC IX
- 0FAC DEC IX
- 0FAE UNTIL-MK LD A,+00 Wait 7 T cycles.
- 0FB0 IN A,(+F7) Get a bit into carry
- 0FB2 RRA flag.
- 0FB3 RR E Shift the bit into E.
- 0FB5 JP NC,0FAE,UNTIL-MK Repeat for 8 bits.
- 0FB8 LD (HL),E Store the received byte.
- 0FB9 INC HL Point to next location.
- 0FBA DJNZ 0F9E,INPAK-L Get next byte.
- 0FBC CP A Return with zero flag set to signal
- 0FBD RET 'successfully read'.
- THE 'SEND RESPONSE BYTE' SUBROUTINE
- A 'response byte' is simply a byte +01 that is sent over the network to confirm that some data has been successfully \
- received.
- 0FBE SEND-RESP LD A,+0l This is the response byte.
- 0FC0 LD HL,+5CCD Store it into NTRESP.
- 0FC3 LD (HL),A
- 0FC4 LD E,A A 'single byte' is to be sent.
- The subroutine continues into OUTPAK below.
- THE 'OUTPAK' SUBROUTINE
- This is the opposite to the INPAK subroutine and thus, is used to send over the network a block of bytes. Again, on \
- entry HL must hold the address fro which the block is stored, and E must hold its length. Initially a leader (length \
- 98 T cycles) is sent, followed by each byte, with an initial 'start' period, and then the 8 bits (each 40 T cycles).
- 0FC5 OUTPAK XOR A Begin with a 'start' leader.
- 0FC6 OUT (+F7),A
- 0FC8 LD B,+04 Insert the required delay.
- 0FCA DEL_O-1 DJNZ 0FCA,DEL_O-1
- 0FCC OUTPAK-L LD A,(HL) Get the byte to be sent,
- 0FCD CPL Send the bits inverted.
- 0FCE SCF The start bit is high.
- 0FCF RLA Rotate bit into A.
- 0FD0 LD B,+0A '10' bits to be sent (start, data,
- stop).
- 0FD2 UNT-MARK OUT (+F7),A Send the bit.
- 0FD4 RRA Next bit.
- 0FD5 AND A But clear carry.
- 0FD6 DEC B becrease bit counter.
- 0FD7 LD D,+00 Wait 7 T cycles.
- 0FD9 JP NZ,0FB2,UNT-MARK Loop for all bits.
- 0FDC INC HL Point to next location in the block.
- 0FDD DEC E Decrease 'block length'.
- 0FDE PUSH HL Wait 22 T cycles.
- 0FDF POP HL
- 0FE0 JP NZ,0FCC,OUTPAK-L Loop until all bytes have been sent.
- 0FE3 LD A,+01
- 0FE5 OUT (+F7),A Finally make the network inactive.
- 0FE7 RET Finished.
- The Microdrive routines
- THE 'SET A TEMPORARY "M" CHANNEL' SUBROUTINE
- This very important subroutine sets a temporary "M" channel in the CHANS area; the Microdrive map is created unless it \
- already exists (if another channel refers to the same drive). The subroutine returns with the IX register pointing to \
- the start of the channel, and with the HL register holding a suitable displacement to be eventually inserted in the \
- STRHS area to attach the channel to a stream. Note that the HL' register is corrupted if you call this routine from \
- your own program.
- 0FE8 SET-T-MCH EXX Swap registers.
- 0FE9 LD HL,+0000 Signal 'map to be created'.
- 0FEC EXX Swap registers again.
- 0FED LD IX,(CHANS) Start of channel area.
- 0FF1 LD DE,+0014 Points to the start of the channels
- 0FF4 ADD IX,DE Other than the 'standard' ones.
- 0FF6 CHK-LOOP LD A,(IX+0) Jump forward it the CHANS area is
- 0FF9 CP +80 finished.
- 0FFB JR Z,1034,CHAN-SPC
- 0FFD LD A,(IX+4) Fetch channel specifier.
- 1000 AND +7F Clear bit 7.
- 1002 CP +4D Jump if this is not an "m" channel.
- 1004 JR NZ,102A,NEXT-CHAN
- 1006 LD A,(D-STR1) Fetch drive number.
- 1009 CP (CHDRIV) Jump if this channel uses a different
- l00C JR NZ,102A,NEXT-CHAN drive.
- 100E EXX Swap registers.
- 100F LD L,(CHMAP-lo) Move address of map area into H'L'
- 1012 LD H,(CHMAP-hi)
- 1015 LXX Swap registers again.
- 1016 LD BC,(N-STR1) Length of filename.
- 101A LD HL.(N-STR1+2) Start address of filename.
- 101D CALL 131E,CHK-NAME Check name against 'CHNAME' of this
- channel.
- 1020 JR NZ,102A,NEXT-CHAN Jump if not the same file.
- 1022 BIT 3,(IX+24) This is set with 'write' files.
- 1026 JR Z,102A,NEXT-CHAN Continue with 'read' files.
- 1028 RST 20,SH-ERR Give the 'Reading a 'write' file'
- 1029 DEFB +0D error if the file is already opened
- for writing.
- 102A NEXT-CHAN LD E,(IX+9) Fetch length of channel into the DE
- 102D LD D,(lX+10) register pair.
- 1030 ADD IX,DE Point to the next channel.
- 1032 JR 0FF6,CHK-LOOP Back again.
- Now the space for the new channel is created at the end of the CHANS area.
- 1034 CHAN-SPC LD HL,(PROG) Fetch the start address of the
- 1037 DEC HL channel,
- 1038 PUSH HL Save it.
- 1039 LD BC,+0253 Length is '595' bytes.
- 103C RST 10,CALBAS Call MAKE-ROOM to create the required
- 103D DEFW +1655 space.
- 103E POP DE Restore start address of the channel.
- 1040 PUSH DE
- 1041 LD HL,+13CC Start of "M" channel data.
- 1044 LD BC,+0019 Length of data.
- 1047 LDIR Store data into the channel.
- 1049 LD A,(D-STR1) Fetch drive number.
- 104C LD (CHDRIV),A Initialise CHDRIV.
- 104F LD BC,+0253 Length of channel.
- 1052 PUSH IX Fetch start of channel into HL.
- 1054 POP HL
- 1055 CALL 1691,REST-N-AD Restore start of 'filename' possibly
- moved after the 'insertion' of the
- channel.
- 1058 EX DE,HL The start address of the filename goes
- to HL.
- 1059 LD BC,(N-STR1) Fetch length of filename.
- 105D BIT 7,B Jump if the name does not exist
- 105F JR NZ,106F,TEST-MAP (N-STR1 = +FFFF).
- The channel name is transferred into CHNAME.
- 1061 T-CH-NAME LD A,B The loop continues until 'length'
- 1062 OR C reaches zero.
- 1063 JR Z,106F,TEST-MAP Fetch character of name.
- 1065 LD A,(HL)
- 1066 LD (IX+14),A Store it into CHNAME.
- 1069 INC HL Point to next locations.
- l06A INC IX
- 106C DEC BC Decrease 'length'.
- 106D JR 106l,T-CH-NAME Continue with next character.
- Now the 'map' is created unless it already exists.
- 106F TEST-MAP POP IX Restore start address of channel.
- 1071 EXX Use alternate registers.
- 1072 LD A,H Address of map, or +0000 if the map
- 1073 OR L does not exist.
- 1074 JR NZ,108A,ST-MAP-AD Jump if the map already exists.
- 1076 LD HL,(CHANS) Otherwise the map is to be created.
- 1079 PUSH HL
- 107A DEC HL
- 107B LD BC,+0020 Length of the map is 32 bytes.
- 107E RST 10,CALBAS Call MAKE-ROOM to make the space.
- 107F DEFW +1655
- 1081 POP HL Restore start of map.
- 1082 LD BC,+0020 Restore 'start' of channel.
- 1085 ADD IX,BC
- 1087 CALL 1691,REST-N-AD Restore 'start' of filename.
- 108A ST-MAP-AD LD (CHMAP-lo),L Lastly store the start address
- 108E LD (CHMAP-hi),H of the Microdrive map.
- All bits in the map are made high; then the 'preambles' are collected from the table at +13E5 and stored in the channel.
- 1090 LD A,+FF All bits high.
- 1092 LD B,+20 Length of map.
- l094 FILL-MAP LD (HL),A Store +FF into this location.
- 1095 INC HL Advance the pointer.
- 1096 DJNZ 1094,FILL-MAP Continue for 32 bytes.
- 1098 PUSH IX Pass start of channel to HL.
- 109A POP HL
- 109B LD DE,+001C Make DE register pair point to the
- 109E ADD HL,DE header block preamble area.
- 109F EX DE,HL
- 10A0 LD HL,+13E5 Start of 'preamble' data.
- l0A3 LD BC,+000C Preamble is 12 bytes in length.
- 10A6 LDIR Set-up header preamble.
- 10A8 PUSH IX Pass again 'start' to HL.
- 10AA POP HL
- 10AB LD DE,+0037 Offset for data block preamble.
- 10AE LD BC,+000C Preamble is again 12 bytes.
- 10B1 ADD HL,DE Make DE register pair point to the
- 10B2 EX DE,HL data block preamble.
- 10B3 LD HL,+13E5 Start of 'preamble data'.
- 10B6 LDIR Set-up the data block preamble.
- 10B8 PUSH IX Move 'start' of channel into HL
- 10BA POP HL register pair.
- 10BB LD DE,(CHANS) Calculate the required 'stream
- 10BF OR A offset' into HL.
- 10C0 SBC HL,DE
- 10C2 INC HL
- 10C3 RET Finished.
- THE 'RECLAIM "M" CHANNEL' SUBROUTINE
- This subroutine (also called by using 'hook code' +2C) is used to reclaim the "m" channel pointed by the IX index \
- register. Any stream attached to this channel will be closed, and other 'dynamic' areas updated. The map is also \
- reclaimed, unless it is used by another channel.
- 10C4 DEL-M-BUF LD L,(CHMAP-lo) Fetch address of map into HL.
- 10C7 LD H,(CHMAP-hi)
- 10CA PUSH HL Save it for later.
- 10CB LD A,(CHDRIV) Fetch drive number.
- 10CE PUSH AF Save it for later.
- 10CD PUSH IX Make HL point to the start of
- 10D1 POP HL the channel.
- 10D2 LD BC,+0253 Length of the channel.
- 10D5 RST 10,CALBAS RECLAIM-2 is called to delete
- 10D6 DEFW +19E8 the channel area.
- 10D8 PUSH IX Make HL point again to the start of
- 10DA POP HL the (reclaimed) channel.
- 10DB LD DE,(CHANS) Calculate 'offset' used into STRMS
- 10DF OR A area for the deleted channel,
- 10E0 SBC HL,DE possibly attached to a stream.
- 10E2 INC HL
- l0E3 LD BC,+0253 Amount of bytes moved down.
- 10E6 CALL l35F,REST-STRM Close required streams and update
- data for other streams.
- Look for any channel that uses the same map as that of the channel deleted.
- 10E9 POP AF Restore drive number, and start
- 10EA POP HL address of map.
- 10EB LD B,A Drive number goes into B.
- 10EC LD IX,(CHANS) Start of channel area.
- 10F0 LD DE,+0014 Skip initial 'standard' channels.
- 10F3 ADD IX,DE
- 10F5 TEST-MCHL LD A,(IX+0) Jump if the channel area is finished.
- 10F8 CP +80
- 10FA JR Z,1114,RCLM-MAP
- 10FC LD A,(IX+4) Fetch channel specifier.
- 10FF AND +7F Clear bit 7 (no distinction is made
- between 'temporary' and 'permanent'
- channels).
- 1101 CP +4D Jump if this is not an "m" channel.
- 1103 JR NZ,113A,NXTCHAN
- 1105 LD A,(CHDRIV) Fetch drive number of this channel.
- 1108 CP B If it is the same as that of the
- 1109 RET Z deleted channel, the map is not to
- be reclaimed.
- 110A NXTCHAN LD E,(IX+9) Fetch length of this channel.
- 110D LD B,(IX+10)
- 1110 ADD IX,DE Points to next channel.
- 1112 JR 10F5,TEST-MCHL Back again for next channel.
- If no channel uses the map used by the deleted one, it is to be deleted too.
- 1114 RCLM-HAP LD BC,+0020 Length of the map.
- 1117 PUSH HL Save start of map.
- 1118 PUSH BC Save length of map. Note: this is
- not necessary.
- 1119 RST 10,CALBAS Call RECLAIM-2 to delete the map.
- 111A DEFW +19E8
- 111C POP BC Restore length and start of the
- 111D POP HL deleted map.
- 111E CALL 1391,REST-MAP Update addresses of other maps.
- 1121 RET Finished.
- THE '"M" CHANNEL INPUT' ROUTINE
- The actual 'input' is handled via CALL-INP. The service routine is MCHAN-IN below.
- 1122 M-INPUT LD IX,(CURCHL) First make IX point to start of
- channel.
- 1126 LD HL,+112C Address of MCHAN-IN routine.
- 1129 JP 0CBD,CALL-INP Jump to the control routine.
- THE '"M" CHANNEL INPUT' SERVICE ROUTINE
- Similarly to the "n" input, the "m" input involves the reading of a byte from the data block. When it is empty, a \
- further block is to be received from Microdrive (Provided that the 'current' data block is not the 'end of file' one) \
- before reading the byte.
- 112C MCHAN-IN BIT 0,(CHFLAG) This is reset to indicate a 'read'
- file.
- 1130 JR Z,1134,TEST-M-BF Jump with 'read' file.
- 'Reading a write file'
- 1132 RWF-ERR RST 20,SH-ERR Call the error handling routine.
- 1133 DEFB +0D
- 1134 TEST-M-BF LD E,(CHBYTE-lo) Fetch current byte counter.
- 1137 LD D,(CHBYTE-hi)
- 113A LD L,(RECLEN-lo) Fetch record length.
- 113D LD H,(RECLEN-hi)
- 1140 SCF Include byte to be read.
- 1141 SEC HL,DE Jump if all bytes have been read.
- 1143 JR C,1158,CHK-M-EOF
- 1145 INC DE Include byte to be read in the
- byte counter.
- 1146 LD (CHBYTE-lo),E Store pew byte Counter.
- 1149 LD (CHBYTE-hi),D
- 114C DEC DE Position of character to be read.
- 114D PUSH IX Save start address of channel.
- 114F Abb IX,DE IX now points to 'byte to be
- read - 82'.
- 1151 LD A,(IX+82) Fetch the byte.
- 1154 POP IX Restore start of channel.
- 1156 SCF Signal 'acceptable code'.
- 1157 RET Finished.
- If all bytes in the data block have been read, a check is made to see if it is the 'end of file' block, i.e. the last \
- one.
- 1158 CHK-M-EOF BIT 1,(RECFLG) This is set to signal 'EOF'.
- 115C JR Z,1162,NEW-BUFF Jump if not the last block.
- 115E XOR A Otherwise zero and carry flags are
- returned reset to signal EOF.
- 115F ADD A,+0D Returned byte is +0D.
- 1161 RET Finished.
- A new data block is now read from the Microdrive unit.
- 1162 NEW-BUFF LD DE,+0000 The byte counter is cleared.
- 1165 LD (CHBYTE-lo),E
- 1168 LD (CHBYTE-hi),D
- 116B INC (CHREC) Increment record number.
- 116E CALL 1177,GET-RECD Fetch a new data block.
- 1171 XOR A Turn off drive motor.
- 1172 CALL 17F7,SEL-DRIVE
- 1175 JR 1134,TEST-M-BF Now read the byte.
- THE 'GET A RECORD' SUBROUTINE
- This subroutine is used to load a record of a 'PRINT-type file. The number of the wanted record must be stored into \
- CHREC, the drive number into CHDRIV and the filename into CHNAME. If after five passes of the tape the record is not \
- found, or if a checksum error occurs, the error 'File not found' is given.
- 1177 GET-RECD LD A,(CHDRIV) Fetch drive number.
- 117A CALL 17F7,SEL-DRIVE Start drive motor.
- 117D GET-R-2 LD BC,+04FB Initialise SECTOR to 1275 (i.e., at
- 1180 LD (SECTOR),BC least five passes of the tape).
- 1184 GET-R-LP CALL 11A5,G-HD-RC Get header and data block.
- 1187 JR C,119E,NXT-SCT Consider next sector with errors, or
- 1189 JR Z,119E,NXT-SCT if it is unused.
- 118B CD A,(RECNUM) Fetch record number.
- 118E CP (CHREC) Test against CHREC.
- 1191 JR NZ,119E,NXT-SCT Next sector also if this record is
- not the expected one.
- 1193 PUSH IX Fetch base of "m" channel into HL.
- 1195 POP HL
- 1196 LD DE,+0052 Points to the start of the buffer.
- 1199 ADD HL,DE
- 119A CALL 1346,CHKS-BUFF Return if the checksum is correct.
- 119D RET Z
- 119E NXT-SCT CALL 1312,DEC-SECT Decrease SECTOR.
- 11A1 JR NZ,1184,GET-R-LP Continue until five passes of the
- tape have been made.
- 'File not found'
- 11A3 RS-SH2 RST 20,SH-ERE Call the error handling routine.
- 11A4 DEFB +11
- THE 'GET HEADER AND DATA BLOCK' SUBROUTINE
- This subroutine is used to collect from the selected Hicrodrive unit a header followed by its data block. Note that \
- the drive motor is to be turned on before calling G-HD-RC. The flags returned denote the following states:
- - zero set, carry reset The sector is unused.
- - zero reset, carry reset Successful loading.
- - carry set With any error.
- The 'errors' include wrong checksums, and no matching between the wanted filename (CHNAME) and the loaded one (RECNAM).
- 11A5 G-HD-RC CALL 12C4,GET-M-HD2 Fetch the header.
- 11A8 LD DE,+001B Make HL point to RECLCG, i.e.,
- 11AB ADD HL,DE start of record area.
- 11AC CALL 18A9,GET-M-BF Fetch the record.
- 11AF CALL 1341,CHKS-HD-R Calculate record checksum.
- 11B2 JR NZ,11D6,G-REC-ERR Exit if the checksum is wrong.
- 11B4 BIT 0,(RECFLG) This is set to signal a header block.
- 11B8 JR NZ,11D6,G-REC-ERR Exit if a header instead of a data
- block has been fetched.
- 11BA LD A,(RECFLG) Bit 1 of RECFLG and of REGLEN-hi
- 11BD OR (RECLEN-hi) are both reset with 'unused sector'.
- 11C0 AND +02 Take only bit 1.
- 11C2 RET Z Return with unused sectors.
- 11C3 PUSH IX Make HL point to the start of the
- 11C5 POP HL channel.
- 11C6 LD DE,+0047 Points to RECNAM.
- 11C9 ADD HL,DE
- 11CA LD BC,+000A Name is ten characters in length.
- 11CD CALL 131E,CHK-NAME Compare it against CHNAME.
- 11D0 JR NZ,11D6,G-REC-ERR Exit if they do not match.
- 11D2 LD A,+FF Exit with zero and carry flags reset
- 11D4 OR A when successful.
- 11D5 RET
- 11D6 G-REC-ERR SCF Exit with carry set if any error has
- 11D7 RET been detected.
- THE '"M" CHANNEL OUTPUT' ROUTINE
- The routine is very similar to that for the "N" channel output. The byte passed to the accumulator is stored into the \
- 512-byte buffer. When it is filled, the record is written onto the Microdrive cartridge.
- 11D8 MCHAN-OUT LD IX,+FFFA Point to the start of the channel
- 11DC ADD IX,DE (i.e. DE-6, see 00BA).
- 11E1 BIT 0,(CHFLAG) Continue only if this is a 'write'
- 11E2 JR NZ,11E6,NOREAD file.
- 'Writing to a 'read' file'
- 11E4 RST 20,SH-ERR Call the error handling routine.
- 11E5 DEFB +0C
- 11E6 NOREAD LD E,(CHBYTE-lo) Fetch byte counter.
- 11E9 LD D,(CHBYTE-hi)
- 11EC PUSH IX Save start address of channel.
- 11EE ADD IX,DE Now IX points to 'first free byte
- in the buffer'-82.
- 11F0 LD (IX+82),A Store a byte in the buffer.
- 11F3 POP IX Restore start address of channel.
- 11F5 INC DE Points to first 'free byte' in the
- buffer.
- 11F6 LD (CHBYTE-lo),E Update byte counter,
- 11F9 LD (CHBYTE-hi),D
- 11FC BIT 1,D Return if the buffer is not filled
- 11FE RET Z (position 512 has not been reached).
- If the buffer is filled, the routine continues into WR-RECD below.
- THE 'WRITE A RECORD ONTO MICRODRIVE' SUBROUTINE
- This subroutine is also called by using hook code +26. The record held in the "m" channel pointed by the IX register \
- (with name CHNAME and number CHREC), is written into the first unused sector in the cartridge inserted in the drive \
- CHDRIV. Then the appropriate map bit is set and CHREC is automatically incremented. An error is produced if no more \
- space is available on the cartridge to write the record.
- 11FF WR-RECD LD A,(CHDRIV) Fetch drive number.
- 1202 CALL 17F7,SEL-DRIVE Turn on the motor.
- 1205 CALL 120D,WRITE-PRC Write the record.
- 1208 XOR A Turn off the motor.
- 1209 CALL 17F7,SEL-DRIVE
- 120C RET Finished.
- 120D WRITE-PRC CALL 1264,CHK-FULL Check if the cartridge is full,
- 1210 JR NZ,121B,NOFULL and jump if it is not.
- 1212 CALL 10C4,DEL-M-BUF Otherwise reclaim the channel.
- 1215 XOR A Turn off drive motors.
- 1216 CALL 17F7,SEL_DRIVE
- 'Microdrive full'
- 1219 RST 20,SH-ERR Call the error handling routine.
- 121A DEFB +0F
- 121B NOFULL PUSH IX Save base address of channel.
- 121D LD B,+0A Counts ten characters.
- 121F CP-NAME LD A,(IX+14) Copy CHNAME into RECNAM.
- 1222 LD (IX+71),A
- 1225 INC IX
- 1227 DJNZ 121F,CP-NAME
- 1229 POP IX Restore start of channel.
- 122B LD C,(CHBYTE-lo) Copy CHBYTE into RECLEN.
- 122E CD (RECLEN-lo),C
- 1231 LD A,(CHBYTE-hi)
- 1234 LD (RECLEN-hi),A
- 1237 LD A,(CHREC) Copy CHREC into RECNUM.
- l23A LD (RECNUM),A
- 123D PUSH IX Make HL point to the start of the data
- 123F POP HL block workspace, i.e. RECFLG.
- 1240 LD DE,+0043
- 1243 ADD HL,DE
- 1244 CALL 1341,CHKS-HD-R Calculate DESCHK checksum.
- 1247 LD DE,+000F Hake HL point to the start of the
- 124A ADD HL,DE 512-byte buffer.
- 124B CALL 1346,CHKS-BUFF Calculate DCHK checksum.
- 124E PUSH IX Three useless instructions.
- 1250 POP HL
- 1251 LD DE,+0047
- 1254 CALL 1275,SEND-BLK Send the record to Microdrive.
- 1257 LD DE,+0000 Clear CHBYTE.
- 125A LD (CHBYTE-lo),E
- 125D LD (CHBYTE-hi),D
- 1260 INC (CHREC) Finally increment record number.
- 1263 RET Finished.
- THE 'CHK-FULL' SUBROUTINE
- This subroutine is used to check whether the currently used Microdrive unit contains a full cartridge, with no 'free \
- tot use' sectors. The zero flag is returned set if the cartridge is full (i.e. if all map bits are set).
- 1264 CHK-FULL LD L,(CHMAP-lo) Fetch address of the map.
- 1267 LD H,(CHMAP-hi)
- i26A LD B,+20 Length of the map.
- 126C NXT-B-MAP LD A,(HL) Fetch a byte.
- 126D CP +FF Exit with zero flag reset if not all
- 126F RET NZ bits are set.
- 1273 INC HL Point to the next byte,
- 1271 DJNZ 126C,NXT-B-MAP Loop for all bytes.
- 1273 XOR A Return with zero flag set to signal
- 1274 RET that the cartridge is full.
- TIlE 'SEND-BLK' SUBROUTINE
- The following subroutine fetches the first 'free' header and then writes the
- buffer into the sector, provided that the cartridge is not write-protected. Finally the map bit is set.
- 1275 SEND-BLK PUSH IX Make HL point to the data block
- 1277 POP HL preamble.
- 1278 LD DE,+0037
- 127B ADD HL,BE
- l27C PUSH HL Save this address.
- 127D FAILED CALL 12C4,GET-M-HD2 Fetch the first header.
- 1280 CALL 12DF,CHECK-MAP Check map bit for this header.
- 1283 JR NZ,127D,FAILED Continue if the sector is not 'free
- for use'.
- 1285 EX (SP),HL Now (SP) holds the map bit address;
- and HL the start of the data block
- preamble.
- 1286 PUSH BC Save map bit position.
- 1287 IN A,(+EF) Jump if the write-protect tab is
- 1289 AND +01 present.
- 128B JR NZ,128F,NO-PRT
- 'Drive 'write' protected'
- 128D RST 20,SH-ERR Call the error handling routine.
- 128E DEFB +0E
- 128F NO-PRT LD A,+E6 Start the writing process.
- 1291 OUT (+EF),A
- 1293 LD BC,+0168 Wait until the first gap is finished.
- 1296 CALL 18FA,DELAY-BC
- 1299 CALL 1878,OUT-M-BUF Write preamble and data block.
- 129C LD A,+EE Send a signal when finished.
- 129E OUT (+EF),A
- 12A0 POP BC Restore map bit position.
- 12A1 POP HL Restore map bit address.
- 12A2 LD A,B Set the required map bit.
- 12A3 OR (HL)
- 12A4 LD (HL),A
- 12A5 RET Finished.
- THE 'CLOSE FILE' SUBROUTINE
- This subroutine CLOSEs a 'PRINT-type' "m" channel. If the channel is used for reading, then it is reclaimed; but if it \
- is used for writing, any unsent data in the buffer is written onto the Microdrive cartridge before reclaiming the \
- channel. The entry point CLOSE-M is used when the start address of the channel is held in the HL register pair, while \
- CLOSE-M2 (also used by 'hook code' +23) is used when that address is held in the IX index register.
- 12A6 CLOSE-M PUSH HL Make IX register point to the start
- 12A7 POP IX of the channel.
- 12A9 CLOSE-M2 BIT 0,(CHFLAG) Jump forward when 'reading'.
- 12AD JR Z,12B6,NOEMP
- 12AF SET 1,(RECFLG) Otherwise signal 'EOF' record,
- 12B3 CALL 11FF,WR-RECD and write it onto drive.
- 1236 NOEMP XOR A Switch off motor.
- 1237 CALL 17F7,SEL-DRIVE
- 12BA CALL 10C4,DEL-M-BUF Reclaim the channel.
- 12BD RET Finished.
- THE 'MAIN ERROR RESTART' EMULATION ROUTINE
- This routine, called in the format 'CALL ERR-RS / DEFB nn' emulates the sequence 'RST 8 / DEFB nn' that is used (when \
- the main ROM is paged in) to give an error report. ERR-RS is never called from the shadow ROM code.
- 12BE ERR-RS POP HL Fetch return address (points to the
- error code).
- 12BF LD A,(HL) Fetch error code.
- 12C0 LD (ERR-NR),A Store it.
- 12C3 RST 28,ROMERR Give the error report.
- THE 'FETCH HEADER FROM HICRODRIVE' SUBROUTINE
- This subroutine is used to fetch a header from the current Microdrive unit (whose motor must be turned on). The header \
- is loaded into HDFLG...HDCHK. The procedure is repeated unless the checksum is correct.
- 12C4 GET-M-HD2 PUSH IX Make HL point to MDFLAG, i.e. location
- 12C6 POP HL from which the header will be loaded.
- 12C7 LD DE,+0028
- 12CA ADD HL,DE
- 12CB CALL 18A3,GET-M-HD Fetch the header.
- 12CE CALL 1341,CHKS-HD-R Calculate checksum.
- 12D1 JR NZ,12C4,GET-M-HD2 Repeat if it does not match with the
- 'old' checksum.
- 12D3 BIT 0,(HDFLAG) Repeat if a record descriptor has
- 12D7 JR Z,12C4,GET-M-HD2 been loaded instead of a header.
- 12D9 RET Finished.
- THE 'CHECK MAP BIT STATE' SUBROUTINE
- The bit correspondent to a given sector in the microdrive map is checked. The zero flag is returned set if the bit was \
- reset, and vice-versa. Also the B register will hold, on return, a bit set in the position of the map bit; HL will \
- hold the address of that map bit. The entry point is CHK-MAP-2 when the sector number has to be collected from RECNUM, \
- or CHECK-MAP if from HDNUMB.
- 12DA CHK-KAP-2 CD E,(RECNUM) Fetch sector number.
- 12DD JR 12E2,ENTRY Jump forward.
- 12E1 CHECK-MAP LD E,(HDNUMB) Fetch sector number.
- 12E2 ENTRY LD L,(CHMAP-lo) Fetch map start address.
- 12E5 LD H,(CHMAP-hi)
- 12E8 ENTRY-2 XOR A Clear D register.
- 12E9 LD D,A
- 12EA LD A,E Move sector number to A.
- 12EB AND +07 Only 3 less significant bits,
- (i.e. 'bit position').
- 12ED SRL E Shift out the 'position' from E.
- 12EF SRL E
- 12F1 SRL E
- 12F3 ADD HL,DE Calculate map bit address.
- 12F4 LD B,A Pass 'position' to B.
- 12F5 INC B Range is now 1..8.
- 12F6 XOR A Clear A register.
- 12F7 SCF Set carry flag.
- 12F8 ROTATE RLA Set a bit in the correct position.
- 12F9 DJNZ 12F8,ROTATE
- 12FB LD B,A Exit with B holding that bit.
- 12FC AND (HL) Set zero flag as required.
- 12FD RET Finished.
- THE 'RESET BIT IN MAP AREA' SUBROUTINE
- This subroutine is used to reset the bit in the map area corresponding to the sector HDNUMB.
- 12FE RES-B-MAP CALL 12DF,CHECK-MAP Set B and HL registers with position
- and map address.
- 1301 LD A,B Pass bit to be reset to A.
- 1302 CPL Reset only that bit and
- 1303 AND (HL) leave other bits unchanged.
- 1304 LD (HL),A Store new map byte.
- 1305 RET Finished.
- THE 'CHECK "PSEUDO-MAP" BIT STATE' SUBROUTINE
- This subroutine is apparently equal to the CHECK-MAP subroutine at 12DA, however it does not refer to the standard \
- map, but to a 'pseudo-map' set up in the 512-byte buffer of the "m" channel. This map is used from the ERASE command \
- to mark the sectors to be erased,
- 1306 TEST-PMAP PUSH IX Make HL point to the start of the
- 1308 POP HL buffer. I.e. to the start of
- 1309 LD DE,+0052 the 'pseudo-map' area.
- 130C ADD HL,DE
- 130D LD E,(HDNUMB) Fetch sector number.
- 1310 JR 12E8,ENTRY-2 Continue into CHECK-MAP.
- THE 'DECREASE SECTOR NUMBER' SUBROUTINE
- This short subroutine is frequently called to decrease the content of the system variable SECTOR, used to count a \
- given number of sectors during microdrive operations. The zero flag is returned set when SECTOR reaches zero.
- 1312 DEC-SECT LD BC,(SECTOR) Decrease (SECTOR).
- 1316 DEC BC
- 1317 LD (SECTOR),BC
- 131B LD A,B Set zero flag if SECTOR has reached
- 131C OR C zero.
- 131D RET Finished.
- THE 'CHECK-NAME' SUBROUTINE
- Whenever a 'filename' is to be compared against the channel name CHNAME, this subroutine is called. On entry, HL must \
- point to the filename to be compared, while C must contain its length. If the comparison is successful, the zero flag \
- is returned set.
- 131E CHK-NAME PUSH IX Save start of channel.
- 1320 LD B,+0A Length of CHNAME.
- 1322 ALL-CHARS LD A,(HL) Fetch a byte from name.
- 1323 CP (IX+14) Compare it against CHNAME.
- 1326 JR NZ,133E,CKNAM-END Jump if it does not match.
- 1328 INC HL Point to next character.
- 1329 INC IX
- 132B DEC B Decrease 'lengths'.
- 132C DEC C
- 132D JR NZ,1322,ALL-CHARS Continue until the length of the name
- reaches zero.
- 132F LD A,B CHNAME remaining length.
- 1330 OR A Exit if successful (CHNAME length has
- 1331 JR Z,133E,CKNAM-END reached zero).
- 1333 ALLCHR-2 LD A,(IX+14) Otherwise check that the following
- 1336 CP +20 characters of CHNAME are spaces.
- 1338 JR NZ,133E,CKNAM-END Signal 'unsuccessful' if not spaces.
- 133A INC IX Continue until the whole CHNAME has
- 133C DJNZ 1333,ALCCHR-2 been examined.
- 133E CKNAM-END POP IX Restore channel start address.
- 1340 RET Finished.
- THE 'CALCULATE/COMPARE CHECKSUMS' ROUTINE
- This routine is used to calculate HDCHK, DESCHK and DCHK checksums, or to compare the previous checksum against the \
- current one; the zero flag is returned set if the checksums match. The entry point is CHKS-HD-R for HDCHK or DESCHK, \
- or CHKS-BUFF for DCHK checksum. In both cases HL must contain on entry the start address of the block for which the \
- checksum is to be obtained.
- 1341 CHKS-HD-R LD BC,+000E The block length.
- 1344 JR 1349,CHKS-ALL Skip next instruction.
- 1346 CHKS-BUFF LD BC,+0200 The block length.
- 1349 CHKS-ALL PUSH HL Save the start address.
- 134A LD E,+00 Start with E cleared.
- 134C NXT-BYTE LD A,E Add the current byte to the
- 134D ADD A,(HL) previous sum.
- 134E INC HL Point to next location.
- 134F ADC A,+01 Include also the carry.
- 1351 JR Z,1354,STCHK Jump when A reaches zero.
- 1353 DEC A Otherwise balance the ADD above.
- 1354 STCHK LD E,A Update sum.
- 1355 DEC BC Decrement counter.
- 1356 LD A,B Repeat until the counter reaches 0.
- 1357 OR C
- 1358 JR NZ,134C,NXT-BYTE
- 135A LD A,E Move checksum into A.
- 135B CP (HL) Compare with previous checksum.
- 135C LD (HL),A Store new checksum.
- 135D POP HL Restore start address.
- 135E RET Finished.
- THE 'RESTORE STREAM DATA' SUBROUTINE
- This subroutine is entered with BC holding the length of a reclaimed channel, and HL holding the 'stream displacement' \
- for that channel, The stream that refers to this displacement (i.e. the stream attached to the reclaimed channel) is \
- closed. The other stream displacements are updated if they refer to channels moved down after the reclaiming.
- 135F REST-STRM PUSH HL Save stream displacement.
- 1360 LD A,+10 Counts 16 streams.
- 1362 LD HL,+5C16 Start with STRMS-0 address.
- 1365 NXT-STRM LD (X-PTR),HL Save current address into X-PTR.
- 1368 LD E,(HL) Fetch stream displacement for the
- 1369 INC HL current stream.
- 136A LD D,(HL)
- 136B POP HL Restore displacement of stream to be
- 136C PUSH HL closed.
- 136D OR A Clear carry.
- 136E SBC HL,DE Jump if this is not the stream to be
- 1370 JR NZ,1377,NOTRIGHT closed.
- 1372 LD DE,+0000 Close the stream by storing a
- 1375 JR 137E,STO-DISP displacement = 0.
- 1377 NOTRIGHT JR NC,1384,UPD-POINT Jump if the stream data does not need
- to be updated.
- 1379 EX DE,HL HL holds the current displacement.
- 137A OR A Clear carry.
- 137B SBC HL,BC Obtain new displacement.
- 137D EX DE,HL Move it into DE.
- 137E STO-DISP LD HL,(X-PTR) Store the new displacement for
- 1381 LD (HL),E the current stream.
- 1382 INC HL
- 1383 LD (HL),D
- 1384 UPD-POINT LD HL,(X-PTR) Fetch pointer of current stream data.
- 1387 INC HL Advance to data for next stream.
- 1388 INC HL
- 1389 DEC A Jump back until all 16 streams have
- 138A JR NZ,1365,NXT-STRM been examined.
- 138C LD (X-PTR-lo),A Clear X-PTR.
- 138F POP HL Restore displacement.
- 1390 RET Finished.
- THE 'RESTORE MAP ADDRESSES' SUBROUTINE
- When a map has been deleted, the addresses of the other 'higher' maps have to be updated. The 'REST-MAP' subroutine \
- does this. HL should hold on entry the address of the deleted map.
- 1391 REST-MAP LD BC,+0020 Length of map.
- 1394 LD IX,(CHANS) Point to the first channel other than
- 1398 LD DE,+0014 'standard' one.
- 139B ADD IX,DE
- 139D LCHAN LD A,(IX+0) Return if the CHANS area is finished.
- 13A0 CP +80
- 13A2 RET Z
- 13A3 PUSH HL Save 'start' of map.
- 13A4 LD A,(IX+4) Fetch channel specifier.
- 13A7 AND +7F No distinction between 'temporary'
- and 'permanent' channels is made.
- 13A9 CP +4D Jump if this is not an "m" channel.
- 13AB JR NZ,13C1,LPEND
- 13AD LD E,(CHMAP-lo) Fetch address of map.
- 13B0 LD D,(CHMAP-hi)
- 13B3 SBC HL,DE Jump if this map has not been moved.
- 13B5 JR NC,13C1,LPEND
- 13B7 EX DE,HL HL = old map address.
- 13B8 OR A Clear carry.
- 13B9 SBC HL,BC Calculate actual start address and
- 13BB LD (CHMAP-lo),L store it.
- 13BE LD (CMMAP-hi),H
- 13C1 LPEND POP HL Restore 'start' of deleted map.
- 13C2 LD E,(IX+9) Fetch channel length.
- 13C5 LD D,(IX+10)
- 13C8 ADD IX,DE Point to next channel.
- 13CA JR 139D,LCHAN Loop again.
- THE '"M" CHANNEL DATA' TABLE
- The '25' bytes that compose the initial part of an "M" channel are as follows:
- 13CC DEFW +0008 Main ROM 'output' routine.
- 13CE DEFW +0008 Main ROM 'input' routine.
- 13D0 DEFB +CD "M"+80H (channel specifier).
- 13D1 DEFW +11D8 Shadow ROM 'output' routine.
- 13D3 DEFW +1122 Shadow ROM 'input' routine.
- 13D5 DEFW +0253 Channel length.
- 13D7 DEFW +0000 Default for CHBYTE.
- 13D9 DEFB +00 Default for CHREC.
- 13DA DEFM " (10 spc) " Default for CHNAME.
- 13E4 DEFB +FF Default for CHFLAG ('write' channel).
- THE 'PREAMBLE DATA' TABLE
- The header and the data block preambles are made by the following bytes:
- 13E5 DEFB +00,+00,+00
- 13E8 DEFB +00,+00,+00
- 13EB DEFB +00,+00,+00
- 13EE DEFB +00,+FF,+FF
- Each preamble is used to fetch the start of a block of data when reading from the Microdrive unit.
- THE 'MOVE' COMMAND SUBROUTINE
- The actual MOVE command involves the 'reading' of a byte from the required stream or channel, and then the 'writing' \
- of that byte onto the 2nd stream or channel. The operation is repeated until the 'end of file' condition occurs. Note \
- that bit 4 of FLAGS3 is set to signal to the CALL-INP subroutine (see 0D03) that the 'end of file' error is not to be \
- reported.
- 13F1 MOVE SET 4,(FLAGS3) See comment above.
- 13F5 CALL 1455,OP-STRM Open the first channel.
- 13F8 LD HL,(CHANS) Store current value 0f CHANS.
- 13FB PUSH BC
- 13FC CALL 14C7,EX-DSTR2 Exchange D-STR areas.
- 13FF CALL 1455,OP-STRM Open second channel.
- 1402 CALL 14C7,EX-DSTR2 Exchange D-STR areas again.
- 1405 POP DE Initial start of CHANS.
- 1406 LD HL,(CHANS) Current start of CHANS.
- 1409 OR A Clear carry for a true subtraction.
- 140A SBC HL,DE HL holds the length of the space
- inserted after the 2nd opening
- (possible maps inserted).
- 140C LD DE,(N-STR1) Fetch start of first channel.
- 1410 ADD HL,DE Calculate 'current' start.
- 1411 LD (N-STR1),HL Store it.
- 1414 M-AGAIN LD HL,(N-STR1) Make 'current' the 1st channel
- 1417 LD (CURCHL),HL
- 141A I-AGAIN RST 10,CAL8AS Call INPUT-A in the main ROM to
- 141B DEFW +15E6 read a byte.
- 141D JR C,1423,MOVE-OUT Jump with acceptable codes.
- 141F JR Z,141A,I-AGAIN Repeat if no data has been read.
- 1421 JR 142E,MOVE-EOF Jump when EOF has been reached.
- 1423 MOVE-OUT LD HL,(N-STR2) Make 'current' the 2nd channel.
- 1426 LD (CURCHL),HL
- 1429 RST 10,CALBAS Use main ROM 'PRINT-A' restart to
- 142A DEFW +0010 send the byte through the 2nd channel
- 142C JR 1414,M-AGAIN Repeat the whole procedure.
- 142E MOVE-EOF RES 4,(FLAGS3) Signal that the MOVE command is
- finished.
- 1432 LD HL,(CHANS) Store current CHANS address.
- 1435 PUSH HL
- 1436 CALL 14C7,EX-DSTR2 Exchange D-STR areas,
- 1439 CALL 14A4,CL-CHAN Close the second channel.
- 143C CALL 14C7,EX-DSTR2 Exchange D-STR areas again.
- 143F POP DE Restore initial address of CHANS.
- 1440 LD HL,(CHANS) Fetch current CHANS address.
- 1443 OR A Calculate the amount of bytes
- 1444 SBC HL,DE reclaimed after the deletion of the
- second channel.
- 1446 LD DE,(N-STR1) Calculate the new start address of
- 144A ADD HL,DE first channel.
- 144B LD (N-STR1),HL
- 144E CALL 14A4,CL-CHAN Close the first channel.
- 1451 CALL 17B9,RCL-T-CH Reclaim temporary channels and switch
- off drive motors.
- 1454 RET Finished.
- THE 'USE STREAM OR TEMPORARY CHANNEL' SUBROUTINE
- This subroutine is used from the MOVE command routine above to fetch the start address of the channel attached to a \
- stream (if the command is of the type 'MOVE #N TO ...' ), or to open a temporary channel and fetch its start address \
- if the
- command is in the form 'MOVE "S";N (;"NAME") TO ...'. In both cases the start address of the channel is returned into \
- N-STR1.
- 1455 OP-STRM LD A,(S-STR1) Fetch stream number.
- 1458 INC A If stream no. is +FF (i.e.
- 1459 JR Z,1466,OP-CHAN nonexistent), jump to open a
- temporary channel.
- 145B DEC A A holds the stream number.
- 145C RST 10,CAL8AS Call 'CHAN-OPEN' to select the stream.
- 145D DEFW +1601
- 145F LD HL,(CURCHL) Fetch channel start address.
- 1462 LD (N-STR1),HL Store it.
- 1465 RET Finished.
- 1466 OP-CHAN LB A,(L-STR1) Fetch channel specifier
- 1469 CP +4D Jump if not "m".
- 146B JR NZ,147F,CHECK-N
- 146D CALL 1B29,OP-TEMP-M Open a temporary "m" channel.
- 1470 XOR A Switch off drive motor.
- 1471 CALL 17F7,SEL-DRIVE
- 1474 LD (N-STR1),IX Store channel start address.
- 1478 BIT 2,(RECFLG) Allow only PRINT-type files with the
- 147C RET Z MOVE command.
- 'Wrong file type'
- 147D RST 28,SH-ERR Call the error handling routine.
- 147E DEFB +16
- 147F CHECK-N CP +4E Jump if not an "n" channel.
- 1481 JR NZ,148B,CHECK-R
- 1483 CALL 0EA9,OP-TEMP-N Open a temporary "n" channel.
- 1486 LD (N-STR1),IX Store channel start address,
- 148A RET Finished.
- 148B CHECK-R CP +54 Jump with "t" channel.
- 148D JR Z,1495,USE-R
- 148F CP +42 Jump with "b" channel.
- 1491 JR Z,1495,USE-R
- 'Nonsense in BASIC'
- 1493 RST 28,SH-ERR Call the error handling routine.
- 1494 DEFB +00
- 1495 USE-R CALL 0B13,OP-RS-CH Open a permanent "b" or "t" channel.
- 1498 LD (N-STR1),DE Store channel start address.
- 149C PUSH DE Make IX point to start of channel.
- 149D POP IX
- 149F SET 7,(IX+4) Make the channel 'temporary'.
- 14A3 RET Finished.
- THE 'CLOSE "MOVE" CHANNEL' SUBROUTINE
- This is the opposite subroutine of the preceding one, and is used to CLOSE the channel used by the MOVE command \
- routine. If S-STR1 denotes that a stream was used, no action is made.
- 14A4 CL-CHAN LD A,(S-STR1) Fetch stream number.
- 14A7 INC A Return if a stream has been used
- (i.e. S-STR1<>+FF).
- 14A8 RET NZ
- 14A9 LD A,(L-STR1) Fetch channel specifier.
- 14AC CP +4D Jump if not "m" channel.
- 14AE JR NZ,14B8,CL-CHK-N
- 14B0 LD IX,(N-STR1) Fetch channel start address.
- 14B4 CALL 12A9,CLOSE-M2 Close the "m" channel.
- 14B7 RET Finished.
- 14B8 CL-CHK-N CP +4E Return with "b" and "t" channels.
- 14BA RET NZ
- 14BB LD IX,(N-STR1) Fetch channel start addreus.
- 14BF LD (CURCHL),IX Make the "n" channel the 'current' one
- 14C3 CALL 0EF5,SEND-NEOF Close the "n" channel.
- 14C6 RET Finished.
- THE 'EXCHANGE DSTR1 AND DSTR2 CONTENTS' SUBROUTINE
- This subroutine performs exactly the same task as the EX-D-STR subroutine at 059F, even if it is slightly different. \
- The D-STR1 area is copied into the
- D-STR2 one, and vice-versa.
- 14C7 EX-DSTR2 LD DE,+5CD6 Start of 1st area.
- 14CA LD HL,+5CDE Start of 2nd area.
- 14CD LD B,+08 Length of both areas.
- 14CF ALL-BYT-2 LD A,(DE) Fetch byte from D-STR1.
- 14D0 LD C,(HL) Fetch byte from D-STR2.
- 14D1 EX DE,HL Exchange pointers.
- 14D2 LD (HL),C Store into D-STR1.
- 14D3 LD (DE),A Store into D-STR2.
- 14D4 EX DE,HL Exchange pointers again.
- 14D5 INC HL Advance pointers.
- 14D6 INC DE
- 14D7 DJNZ 14CE,ALL-BYT-2 Continue for all bytes in the
- D-STR areas.
- 14D9 RET Finished.
- THE 'SAVE DATA BLOCK INTO MICRODRIVE' SUBROUTINE
- This is the actual SAVE command referred to the Microdrive (see 082F). The '9' bytes that form the 'header \
- information' are collected from the HD variables and passed to the channel data block; then the memory block, whose \
- 'start' and 'length' are held in the system variables HD-0D and HD-0B, is written onto the Microdrive (provided that \
- there is sufficient space available on cartridge).
- 14DA SA-DRIVE LD A,(D-STR1) Fetch drive number.
- 14DD CALL 17F7,SEL-DRIVE Turn on drive motor.
- 14E0 IN A,(+EF) Continue only if the write-protect
- 14E2 AND +01 tab was not removed.
- 14E4 JR NZ,14E8,START-SA
- 'Drive 'write' protected'
- 14E6 RST 20,SH-ERR Call the error handling
- 14E7 DEFB +0E routine.
- 14E8 START-SA LD HL,(HD-0D) Fetch 'start' of data.
- 14EB LD (5CE4),HL Store it into (N-STR2+2).
- 14EE CALL 1B29,OP-TEMP-M Open a temporary "m" channel.
- 14F1 BIT 0,(CHFLAG) Continue only if this file does
- 14F5 JR NZ,14FC,NEW-NAME not already exist in the cartridge.
- l4F7 CALL 12A9,CLOSE-M2 Close the channel and report the error
- 'Writing to a 'read' file'
- 14FA RST 20,SH-ERR Call the error handling routine.
- 14FB DEFB +0C
- 14FC NEW-NAME SET 2,(RECFLG) Signal 'not a PRINT file'.
- 1500 LD A,(CHDRIV) Fetch drive number.
- 1503 CALL 17E7,SEL-DRIVE Start motor.
- 1506 PUSH IX Make HL point to the buffer.
- 1508 POP HL
- 1509 LD DE,+0052
- 150C ADD HL,DE
- 150D EX DE,HL
- 150E LD HL,+5CE6 Address of HD-00.
- 1511 LD BC,+0009 Length of HD variables.
- 1514 LD (CHBYTE-lo),C Current position is '9'.
- 1517 LDIR Store header informations.
- 1519 PUSH DbE Save address of 'first free byte'.
- 151A LD HL,+0009 Add 9 to 'data length'.
- 151D LD BC,(HD-0B)
- 1521 ADD HL,BC
- 1522 SRL H H holds INT(length/5l2), i.e. number
- of sectors required.
- 1524 INC H Allow for a further EOF sector.
- 1525 PUSH HL Save H register.
- 1526 CALL 1D38,FREESECT Calculate into E the number of 'free'
- sectors.
- 1529 POP HL Restore H.
- 152A LD A,E Jump if there are sufficient
- 152B CP H 'free' sectors.
- 152D JR NC,1530,SA-DRI-2
- 'Microdrive full'
- 152E RST 20,SH-ERR Call the error handling routine.
- 152F DEFB +0F
- 1530 SA-BRI-2 POP DE Restore address of 'first free byte'
- in the buffer.
- 1531 LD HL,(5CE4) Fetch 'start' of block from
- (N-STR2+2) (see 14EB).
- 1534 LD BC,(HD-0B) Fetch 'length' of data.
- 1538 SA-DRI-3 LD A,B Jump when it reaches zero.
- 1539 OR C
- 153A JR Z,155E,SA-DRI-4
- 153D LD A,(CHBYTE-hi) Jump until the buffer space has been
- 151E CP +02 filled.
- 1541 JR NZ,1552,SA-DRI-WR
- 1543 PUSH HL Save registers.
- 1544 PUSH BC
- 1545 CALL 123D,WRITE-PRC Write this data block onto cartridge.
- 1548 POP BC Restore counter.
- 1549 PUSH IX Make DE point to the start of the
- 154B POP HL buffer.
- 154C LD DE,+0052
- 154E ADD HL,DE
- 1550 EX DE,HL
- 1551 POP HL Restore pointer.
- 1552 SA-DRI-WR LDI Move a byte to the buffer.
- 1554 INC (CHBYTE-lo) Increment CHBYTE and go back into the
- 1557 JR NZ,SA-DRI-3 loop.
- 1559 INC (CHBYTE-hi)
- 155C JR 1538,SA-DRI-3
- 155E SA-DRI-4 SET 1,(RECFLG) Mark as 'EOF' record.
- 1562 CALL 120D,WRITE-PRC Write the last data block.
- 1565 LD A,(COPIES) Decrease COPIES and exit if it has
- 1568 DEC A reached zero.
- 1569 JR Z,1579,END-SA-DR
- 156B LD (COPIES),A Store new value.
- 156E RES 1,(RECFLG) Signal 'not EOF'.
- 1572 LD A,+00 Clear CHREC.
- 1574 LD (CHREC),A
- 1577 JR 14FC,NEW-NAME Make another copy.
- 1579 END-SA-DR XOR A Turn off Microdrive motor.
- 157A CALL 17F7,SEL-DRIVE
- 157D JP 10C4,DEL-M-BUF Exit via the delete-channel
- subroutine.
- THE 'GET HEADER INFORMATION FROM MICRODRIVE' SUBROUTINE
- This subroutine is used to collect the first nine bytes of the file into the "m" channel buffer, i.e. the 'header \
- information' when handling files which have been written using the SAVE command (see 08C8). These bytes are copied \
- into the HD system variables.
- 1580 F-M-HEAD LD HL,(5CE1) Move 'start' of data into +5CE4.
- 1583 LD (5CE4),HL
- 1586 CALL 1B29,OP-TEMP-M Open a temporary "m" channel.
- 1589 BIT 0,(CHFLAG) Continue only if the file is found.
- 158D JR Z,1591,F-HD-2
- 'File not found'
- 158F RST 20,SH-ERR Call the error handling routine.
- 1590 DEFB +11
- 1591 F-HD-2 BIT 2,(RECFLG) Continue only if it is not a
- 1595 JR NZ,1599,F-HD-3 'PRINT-type' tile.
- 'Wrong file type'
- 1597 RST 20,SH-ERR Call the error handling routine.
- 1598 DEFB +16
- 1599 F-HD-3 PUSH IX Point to the start of the 512-byte
- 159B POP HL buffer.
- 159C LD DE,+0052
- 159F ADD HL,DE
- 15A0 LD DE,+5CE6 Address of HD-00 variable.
- 15A3 LD BC,+0009 Length of 'header information'.
- 15A6 LDIR Copy header into HD variables.
- 15A8 RET Finished.
- THE 'LOAD OR VERIFY BLOCK FROM MICRODRIVE' SUBROUTINE
- This subroutine is called from the 'LOAD OR VERIFY' subroutine (see 0A66) to load or verify (depending upon the state \
- of bit 7 of FLAGS3) a block of bytes in memory, starting from the address held in the HL register pair. The subroutine
- initially calculates the number of records that composes the file; then starts to collect records and to LOAD or \
- VERIFY the data coming in the 512-Byte buffer. When each record has been loaded or verified, the relevant map bit is \
- set, so as to prevent the record to be used again. The map contents are restored to their initial values before \
- returning. Note that the records may be collected from the Microdrive in a random order.
- 15A9 LV-MCH LD (HD-0D),HL Store 'start'.
- 15AC LD E,(IX+83) Get 'new' length directly from the
- 15AF LD D,(IX+84) 'header information' held in the
- buffer.
- 15B2 LD HL,+0008 Increase 'length' by 8.
- 15B5 ADD HL,DE
- 15B6 SRL H The number of records that composes
- the file is computed (INT(length/5l2))
- 15B8 INC H Include the 'EOF' record.
- 15B9 LD A,H Save this value into HD-0B.
- 15BA LD (HD-0B),A
- 15BD CALL 1613,SA-MAP Save the map into the stack.
- 15C0 LD DE,+0009 Subtract the 'header length' from
- 15C3 LD L,(RECLEN-lo) the 'block length'.
- 15C6 LD H,(RECLEN-hi)
- 15C9 OR A
- 15CA SBC HL,DE
- 15CC LD (RECLEN-lo),L Store actual data block length.
- 15CF LD (RECLEN-hi),H
- 15D2 PUSH IX Make HL point after the nine bytes of
- 15D4 POP HL 'header information'.
- 15D5 LD DE,+005B
- 15D8 ADD HL,DE
- 15D9 LD DE,(HD-0D) Fetch 'start' saved at 15A9.
- 15DD JR 15F9,LOOK-MAP Jump forward.
- 15DF USE-REC CALL 166C,F-REC2 Fetch a record.
- 15E2 LD A,(RECNUM) Repeat if RECNUM is still zero.
- 15E5 OR A
- 15E6 JR Z,15DF,USE-REC
- Now some calculation is performed to obtain into DE the address from which the data coming from the current record, \
- will be loaded or verified. HL will point to the 512-byte buffer.
- 15E8 RLA Now A = RECNUM*2.
- 15E9 DEC A A=RECNUM*2-1.
- 15EA LD D,A Use it as high byte.
- 15EB LD E,+F7 Exclude nine bytes of initial header.
- 15ED LD HL,(HD-0D) Fetch 'start'.
- 15F0 ADD HL,DE Calculate 'start' to use with this
- record.
- 15F1 EX DE,HL Move it to DE.
- 15F2 PUSH IX Make HL point to the start
- 15F4 POP HL of the 512-byte buffer.
- 15F5 LD BC,+0052
- 15F8 ADD HL,BC
- 15F9 LOOK-MAP EXX Use alternate registers.
- 15FA CALL 12DA,CHK-MAP-2 Check bit state for the current
- record.
- 15FD JR NZ,15DF,USE-REC Repeat if this record has already
- been fetched.
- 15FF LD A,(HL) Set map bit to prevent the record
- 1600 OR B from being fetched again.
- 1601 LD (HL),A
- 1602 EXX Restore initial register values.
- 1603 CALL 1648,LD-VE-M Load or verify this record.
- 1606 LD A,(HD-0B) Fetch number of records stored at
- 15BA above.
- 1609 DEC A Decrease it and repeat until all
- 160A LD (ED-0B),A records have been collected.
- 160D JR NZ,15DF,USE-REC
- 160F CALL 162D,RE-MAP Restore map contents.
- 1612 RET Finished.
- THE 'SAVE MICRODRIVE MAP CONTENTS' SUBROUTINE
- This subroutine, called from LV-MCH above, simply copies the '32' bytes that form the Microdrive map into the machine \
- stack.
- 1613 SA-MAP POP HL Store return address in a currently
- 1614 LD (SECTOR),HL unused variable.
- 1617 LD L,(CHMAP-lo) Fetch map start address.
- 161A LD H,(CHMAP-hi)
- 161D LD BC,+1000 B counts 16 passes (map length/2)
- 1620 SA-MAP-LP LD E,(HL) Fetch a byte from the map.
- 1621 LD (HL),C Then clear map byte.
- 1622 INC HL Point to next location.
- 1623 LD D,(HL) Fetch another map byte.
- 1624 LD (HL),C Then clear map byte.
- 1625 INC HL Point to next location.
- 1626 PUSH DE Save the two collected bytes into
- the stack.
- 1627 DJNZ 1620,SA-MAP-LP Continue the loop.
- 1629 LD HL,(SECTOR) Fetch return address.
- 162C JP (HL) Make an indirect return.
- THE 'RESTORE MICRODRIVE MAP CONTENTS' SUBROUTINE
- Exactly the opposite of the subroutine above: the 32 bytes at the top of the
- stack are collected and copied into the Microdrive map.
- 162D RE-MAP POP HL Fetch return address.
- 162E LD (SECTOR),HL Store it in a currently unused
- variable.
- 1631 LD L,(CHMAP-lo) Fetch map address.
- 1634 LD H,(CHMAP-hi)
- 1637 LD DE,+001F Advance to the last map location.
- l63A ADD HL,DE
- 163B LD B,+10 Counts 'map/2' bytes.
- 163D RE-MAP-LP POP DE Fetch two bytes.
- 163E LD (HL),D Store first byte in the map.
- 163F DEC HL Previous location.
- 1640 LD (HL),E Store second byte.
- 1641 DEC HL Previous location.
- 1642 DJNZ 163D,RE-MAP-LP Continue the loop.
- 1644 LD HL,(SECTOR) Fetch return address.
- 1647 JP (HL) Make an indirect return.
- THE 'LD-VE-M' SUBROUTINE
- This subroutine performs the actual LOAD or VERIFY operation. It is entered with HL holding the data start address, \
- and with DE holding the address from which the data have to be loaded or verified.
- 1648 LD-VE-M LD C,(RECLEN-lo) Fetch record length.
- 164B LD B,(RECLEN-hi)
- 164E LD A,(FLAGS3) Jump if VERIFYing.
- 1651 BIT 7,A
- 1653 JR NZ,1658,VE-M-E
- 1655 LDIR LOAD the data.
- 1657 RET Finished.
- 1658 VE-M-E LD A,(DE) Fetch an existing byte.
- 1659 CP (HL) Compare against loaded one.
- 165A JR NZ,1664,VE-FAIL Jump if they do not match.
- 165C INC HL Point to next locations.
- 165D INC DE
- 165E DEC BC Repeat until the block has been
- 165F LD A,B verified.
- 1660 OR C
- 1661 JR NZ,1658,VE-M-E
- 1663 RET Finished.
- 'Verification has failed'
- 1664 VE-FAIL RST 20,SH-ERR Call the error handling routine.
- 1665 DEFB +15
- THE 'FETCH A RECORD FROM MICRODRIVE' SUBROUTINE
- This subroutine is used to read from the Microdrive unit, a record of the current file (saved with a SAVE command). An \
- error occurs if no record is found after five passes of the cartridge tape. The entry point is F-REC2 when the \
- Microdrive motor is already turned on.
- 1666 F-REC1 LD A,(CHDRIV) Fetch drive number.
- 1669 CALL 17E7,SEL-DRIVE Start drive motor.
- 166C E-REC2 LD BC,+04FB Count five passes of the tape.
- 166F LD (SECTOR),BC
- 1673 UNTILFIVE CALL 11A5,G-HD-RC Fetch header and record.
- 1676 JR C,168A,F-ERROR Jump with any error, or with
- 1678 JR Z,168A,F-ERROR unused sectors.
- 167A CALL 12DA,CHK-MAP-2 Check map bit.
- 167D JR NZ,168A,F-ERROR Jump also with already fetched
- records.
- 167F PUSH IX Make HL point to the start of the
- 1681 POP HL 512-byte buffer.
- 1682 LD DE,+0052
- 1685 ADD HL,DE
- 1686 CALL 1346,CHKS-BUFF Return only with correct checksum.
- 1689 RET Z
- 168A F-ERROR CALL 1312,DEC-SECT Decrease SECTOR.
- 168D JR NZ,1673,UNTILFIVE And continue until five passes of the
- tape have been made.
- 'File not found'
- 168F RST 20,SH-ERR Call the error handling routine.
- 1690 DEER +11
- THE 'RESTORE ADDRESS OF "FILENAME"' ROUTINE
- After the 'insertion' of some space, the 'filenames' whose start addresses are held into (N-STR1+2) and (N-STR2+2) \
- have been moved up in the workspace area. This routine is entered with HL holding the channel start address, and with \
- BC
- holding the number of 'inserted' bytes. The addresses held into (N-STR1+2) and (N-STR2+2) are then updated, unless the \
- filenames are stored into 'no-dynamic' areas (i.e. before the channel or after STKEND).
- 1691 REST-N-AD PUSH HL Save 'start of channel' twice.
- 1692 PUSH HL
- 1693 LD DE,(N-STR2+2) Restore start address of the second
- 1697 CALL 16AC,TST-PLACE filename.
- 169A LD (N-STR2+2),DE
- 169E POP HL Restore channel start address.
- 169F LD DE,(N-STR1+2) Restore start address of the first
- 16A3 CALL 16AC,TST-PLACE filename.
- 16A6 LD (N-STR1+2),DE
- l6AA POP HL Restore channel start address.
- 16AB RET Finished.
- The subroutine which calculates the new filename address is the following:
- 16AC TST-PLACE SCF Allow for a further byte.
- 16AD SBC HL,DE No action is made if the filename is
- 16AF RET NC before the channel,
- 16B0 LD HL,(STKEND) or if it is after STKEND.
- 16B3 SBC HL,DE
- 16B5 RET C
- 16B6 EX DE,HL Add to DE the number of 'inserted'
- 16B7 ADD HL,BC bytes, so returning the new filename
- 16B8 EX DE,HL address.
- 16B9 RET Finished.
- 16BA...1707 Unused locations (all set to +FF).
- THE 'CLOSE-STREAM' ROUTINE
- The main ROM 'CLOSE' routine at +16E5 is rather inadequate to deal with Interface's channels:
- First, it has a bug that may crash the system when attempting to CLOSE an unopened stream. This is because the CLOSE-2 \
- routine at +1701 does not check whether the displacement data (found by STR-DATA, +171E) is +0000 (signalling a
- CLOSEd stream). Thus a channel specifier is loaded from a wrong location (CHANS+3), and finally a call to the INDEXER \
- routine is made to search for the (wrong) specifier into the 'stream look-up table', this will result in a system \
- crash.
- Secondly, that routine will only clear the stream data in STRMS area and is not able to manipulate and reclaim the \
- interface's channels as required. So the shadow ROM is paged-in by an instruction fetch at the address +1708 (i.e., \
- the middle of the CLOSE-2 routine in the main ROM). The following routine is then used.
- 1708 CLOSE-CL INC HL The 'INC HL' at +1708 in main ROM.
- 1709 RST 30,NEWVARS Create new variables if required.
- 170A SRL A Range of stream number is +03..+12.
- 170C SUB +03 And now +00..+0F.
- 170E RES 1,(FLAGS3) Signal 'unsent bytes in the buffer
- have to be sent'.
- 1712 CALL 1718,CLOSE Close the stream.
- 1715 JP 05C1,END1 Finished.
- THE 'CLOSE' COMMAND SUBROUTINE
- Any stream +00 to +0F may be CLOSEd by loading the stream number into A and then calling this subroutine. The unsent \
- bytes in 'write'-type files are sent or lost depending upon whether bit 1 of FLAGS3 is reset or set. First a call to
- STR-DATA1 in the main ROM is made to fetch into BC the 'stream data' for the given stream, and to make HL point to the \
- first of the two data bytes.
- 1718 CLOSE RST 10,CALBAS Call STR-DATA1.
- 1719 DEFW +1727
- 171B LD A,C Return if the stream is already
- 171C OR B CLOSEd (i.e. stream data = 0).
- 171D RET Z
- 171E PUSH BC
- 171F PUSH HL
- 1720 LD HL,(CHANS) Make HL point to the start of the
- 1723 DEC HL channel attached to the stream to
- 1724 ADD HL,BC be closed.
- 1725 EX (SP),HL HL now holds the address of the
- stream data.
- 1726 RST 20,CALBAS A call in the middle of the main ROM
- 1727 DEFW +16EB 'CLOSE' routine is made to update
- STRMS contents.
- 1729 LD HL,(CHANS) Make HL point to the first of the
- l72C LD DE,+0014 'new' channels,
- 172F ADD HL,DE
- 1730 POP DE Restore channel start address.
- 1731 SCF Return if the channel is not
- 1732 SBC HL,DE a 'new' one.
- 1734 POP BC
- 1735 RET NC
- 1736 PUSH BC Save stream data, and
- 1737 PUSH DE channel start address.
- 1738 EX DE,HL Move start of channel to HL.
- 1739 LD (CURCHL),HL Make the channel 'current'.
- 173C INC HL Advance HL to the channel specifier.
- 173D INC HL
- 173E INC HL
- 173F INC HL
- 1740 LD A,(HL) Fetch channel specifier.
- 1741 LD DE,+0005 Points to channel length.
- 1744 ADD HL,DE
- 1745 LD E,(HL) Fetch channel length.
- 1746 INC HL
- 1747 LD D,(HL)
- 1748 PUSH DE Save the 'length'.
- 1749 CP +42 Jump with "b" channel.
- 174B JR Z,1751,CL-RS-CH
- 174D CP +54 Jump with "n" and "m" channels.
- 174F JR NZ,175E,CL-N-CH
- Now follows the CLOSE routine for the "t" and "b" channels.
- 1751 CL-RS-CH BIT 1,(FLAGS3) Jump if doing a CLEAR#.
- 1755 JR NZ,177F,RCLM-CH (i.e. do not send any data).
- 1757 LD A,+0D Send a carriage return over RS232.
- 1759 CALL 0C5A,BCHAN-OUT
- 175C JR 177F,RCLM-CH Jump to reclaim the channel.
- 175E CL-N-CH CP +4E Jump with "m" channel.
- 1760 JR NZ,176D,CL-M-CH
- This is the CLOSE routine for the "n" channel,
- 1762 BIT 1,(FLAGS3) Jump if doing a CLEAR#.
- 1766 JR NZ,177F,RCLM-CH
- 1768 CALL 0EF5,SEND-NEOF Send remaining contents of "n"
- buffer.
- 176B JR 177F,RCLM-CH
- Finally the CLOSE routine for the "m" channel.
- 176D CL-M-CH CP +4D Jump if not "m" channel.
- 176F JR NZ,177F,RCLM-CH
- 1771 POP DE Remove 'channel length'.
- 1772 POP IX Start of channel.
- 1774 POP DE Stream data.
- 1775 BIT 1,(FLAGS3) Send the EOF record on microdrive if
- 1779 JP Z,12A9,CLOSE-M2 not using CLEAR#.
- l77C JP 10C4,DEL-M-BUF Reclaim "m" channel.
- 177F RCLM-CH POP BC Channel length.
- 1780 POP HL Channel start address.
- 1781 PUSH BC Save 'length' again.
- 1782 RST 10,CALBAS Call RECLAIM-2 to delete the channel.
- 1783 DEFW +19E8
- NOTE: If the BREAK key is pressed while the buffer is sent as EOF block, the routine does not reach RCLM-CH or \
- DEL-M-BUF, and it is impossible to delete the channel from BASIC unless using the NEW command. The bug should be \
- eliminated by making the channel 'temporary', by setting bit 7 of channel specifier (at 1740..1741), so the channel \
- will be deleted when any error occurs.
- Now all data referring to the stream attached to the channels moved down are updated.
- 1785 XOR A Start with stream 0.
- 1786 LD HL,+5C16 Address of data for stream 0.
- 1789 UPD-STRM LD E,(HL) Fetch stream data.
- 178A INC HL
- 178B LD D,(HL)
- 178C DEC HL Point to the first byte.
- 178D LD (X-PTR),HL Store address into X-PTR.
- 1790 POP BC Length of channel.
- 1791 POP HL Stream data for closed channel.
- 1792 PUSH HL
- 1793 PUSH BC
- 1794 AND A Jump if the stream data found is
- 1795 SBC HL,DE lower than that of the closed stream
- 1797 JR NC,17A4,UPD-NXT-S (i.e. channel has not been moved).
- 1799 EX DE,HL HL holds the fetched Stream data.
- 179A AND A Calculate into DE the new stream data
- 179B SBC HL,BC to be stored.
- 179D EX DE,HL
- 179E LD HL,(X-PTR) Restore stream data address.
- 17A1 LD (HL),E Store new stream data.
- 17A2 INC HL
- 17A3 LD (HL),D
- 17A4 UPD-NXT-S LD HL,(X-PTR) Make HL point to next stream data.
- 17A7 INC HL
- 17A8 INC HL
- 17A9 INC A Increment stream number.
- 17AA CP +10 Loop for all 16 streams.
- 17AC JR C,1789,UPD-STRM
- 17AE LD (X-PTR-hi),+00 Clear X-PTR.
- 17B2 POP HL Remove 'channel length' and
- 17B3 POP HL 'stream data'.
- 17B4 RES 1,(FLAGS3) Clear 'CLEAR/CLOSE' flag.
- 17B8 RET Finished.
- THE 'RECLAIM TEMPORARY CHANNELS' SUBROUTINE
- This subroutine is called to reclaim from the CHANS area all 'temporary' channels (i.e. with bit 7 of channel \
- specifier set). Also the drive motors are turned off. The routine is always called when any error report occurs, and \
- on some other occasions.
- 17B9 RCL-T-CH LD IX,(CHANS) Make IX point to first 'non-standard'
- 17BD LD DE,+0014 channel.
- 17C0 ADD IX,DE
- 17C2 EX-CHANS LD A,(IX+3) Jump if the CHANS area is not
- 17C5 CP +80 finished.
- 17C7 JR NZ,17D2,CHK-TEMPM
- 17C9 LD A,+EE Send a signal to the interface.
- 17CB OUT (+EF),A
- 17CD XOR A Return via SEL_DRIVE to turn off
- 17CE JP 17F7,SEL-DRIVE drive motors.
- 17D1 RET Never executed.
- 17D2 CHK-TEMPM LD A,(IX+4) Fetch channel specifier.
- 17D5 CP +CD Jump if not a temporary "m" channel.
- 17D7 JR NZ,17DE,CHK-TEMPN
- 17D9 CALL 10C4,DEL-M-BUF Reclaim "m" channel.
- 17DC JR 17B9,RCL-T-CH Loop again.
- 17DE CHK-TEMPN CP +CE Jump if not a temporary "n" channel.
- 17E0 JR NZ,17ED,PT-N-CHAN
- 17E2 LD BC,+0114 Length of "n" channel.
- 17E5 PUSH IX Make HL point to start of channel.
- 17E7 POP HL
- 17E8 RST 10,CALBAS Call RECLAIM-2 to reclaim channel.
- 17E9 DEFW +19E8
- 17EB JR 17B9,RCL-T-CH Loop again.
- 17ED PT-N-CHAN LD E,(IX+9) Fetch channel length.
- l7F0 LD D,(IX+10)
- 17F3 ADD IX,DE Point to next channel.
- 17F5 JR 17C2,EX-CHANS Loop for the whole CHANS area.
- THE 'SELECT DRIVE MOTOR' SUBROUTINE
- This subroutine is also called by using 'hook code' +21. On entry, A must hold a drive number in the range 1. .8; the \
- appropriate drive motor is turned on, and an error occurs if the specified drive is not present (or if it contains no \
- cartridge, or
- contains an unformatted cartridge). If A holds zero, all motors are turned off. Note that this subroutine returns with \
- interrupts disabled if a motor has been switched on.
- 17F7 SEL-DRIVE PUSH HL Save HL register pair.
- 17F8 CP +00 Jump if a drive motor is to be turned
- 17FA JR NZ,1802,TURN-ON on.
- 17FC CALL 182A,SW-MOTOR Otherwise switch off all motors.
- 17FF EI Enable interrupts.
- 1800 POP HL Restore HL.
- 1801 RET Finished.
- 1802 TURN-ON DI Disable interrupts.
- 1803 CALL 182A,SW-MOTOR Switch motors as required.
- 1806 LD HL,+1388 First wait about 40 ms.
- 1809 TON-DELAY DEC HL Decrease counter.
- 180A LD A,H Has the counter reached zero?
- 180B OR L
- 180C JR NZ,1809,TON-DELAY Repeat if not.
- 180E LD HL,+1388 Repeat 5000 times the following test:
- 1811 REPTEST LD B,+06 Set a counter.
- 1813 CMK-PRES CALL 18E9,TEST-BRK Give an error if BREAK is pressed.
- 1816 IN A,(+EF) Repeat until 'GAP' signal is found low
- 1818 AND +04
- 181A JR NZ,1820,NOPRES
- 181C DJNZ 1813,CHK-PRES Repeat 6 times.
- 181E POP HL Restore HL.
- 181F RET Finished.
- 1820 NOPRES DEC HL Becrease counter.
- 1821 LD A,H Has the counter reached zero?
- 1822 OR L
- 1823 JR NZ,1811,REPTEST Repeat if not.
- 1825 CALL 17F7,SEL-DRIVE Send 'switch off' signals and enable
- interrupts.
- 'Microdrive not present'
- 1828 RST 20,SH-ERR Call the error handling routine.
- 1829 DEFB +10
- The following subroutine does the actual switching' of the motors, and the selection of the required drive. It is \
- entered with drive number 1...8 (or 0 to switch all motors off) in the A register. The required drive motor is \
- selected, its motor started, while others are disabled.
- 182A SW-MOTOR PUSH DE Save DE register pair.
- 182B LB DE,+0100
- 182E NEG A = 0 - drive number.
- 1830 ADD A,+09 A = 9 - drive number.
- 1832 LD C,A Move counter to C.
- 1833 LD B,+08 Loop for 8 microdrives.
- 1835 ALL-NOTRS DEC C Switch off this microdrive if it is
- 1836 JR NZ,184B,OFF-MOTOR not the required one.
- 1838 LD A,D Otherwise switch on the motor.
- 1839 OUT (+F7),A
- 183B LD A,+EE
- 183D OUT (+EF),A
- 183F CALL 1867,DEL-S-1 Wait about 1 ms.
- 1842 LD A,+EC
- 1844 OUT (+EF),A
- 1846 CALL 1867,DEL-S-1 Wait about 1 ms.
- 1849 JR 185C,NXT-MOTOR Continue with next microdrive.
- 184B OFF-MOTOR LD A,+EF The drive motor Is turned off.
- 184D OUT (+EF),A
- 184F LD A,E
- 1850 OUT (+F7),A
- 1852 CALL 1867,DEL-S-1 Wait about 1 ms.
- 1855 LD A,+ED
- 1857 OUT (+EF),A
- 1859 CALL 1867,DEL-S-1 Wait about 1 ms,
- 185C NXT-NOTOR DJNZ 1835,ALL-MOTRS Loop for 8 microdrives.
- 185E LD A,D End of drive selection.
- 185F OUT (+F7),A
- 1861 LD A,+EE
- 1863 OUT (+EF),A
- 1865 POP DE Restore DE register pair.
- 1866 RET Finished.
- THE '1 MILLISECOND DELAY' SUBROUTINE
- This subroutine inserts a delay of about 3600 T cycles. It is called from
- SW-MOTOR above.
- 1867 DEL-S-1 PUSH BC Save BC register pair.
- 1868 PUSH AF Save accumulator.
- 1869 LD BG,+0087 Inserts a delay of 3553 T cycles.
- 186C CALL 18FA,DELAY-BC
- 186F POP AF Restore registers.
- 1870 POP BC
- 1871 RET Finished.
- THE 'SEND DATA BLOCK TO MICRODRIVE HEAD' SUBROUTINE
- This subroutine is used for writing a block of bytes onto a Microdrive cartridge. On entry, HL must hold the start of \
- the block to be written. The block is then sent to the Interface (provided that the write-protect tab is present) in a \
- parallel form (the bytes are converted in a serial form by the hardware). The entry points OUT-M-HD and OUT-M-BUF are \
- used respectively to write headers or data blocks (including preambles).
- 1872 OUT-M-HD PUSH HL Save block start address.
- 1873 LD DE,+001E Block length.
- 1876 JR 187C,0UT-M-BLK Jump forward.
- 1878 OUT-M-BUF PUSH HL Save block start address.
- 1879 LD DE,+021F Block length.
- 187C OUT-N-ELK IN A,(+EF) Check write-protect tab.
- 187E AND +01 Only bit 0.
- 1880 JR NZ,1884,NOT-PROT Jump if tab is present.
- 'Drive 'write' protected'
- 1882 RST 20,SH-ERR Call the error handling routine.
- 1883 DEFB +0E
- 1884 NOT-PROT LD A,(IOBORD) Fetch border colour.
- 1887 OUT (+FE),A Change border colour.
- 1889 LD A,+E2 Start writing.
- 188B OUT (+EF),A
- 188D INC D Increment high counter and copy it
- 188E LD A,D into A.
- 188F LD B,E Low counter.
- 1890 LD C,+E7 Output port.
- 1892 NOP Wait 12 T cycles.
- 1893 NOP
- 1894 NOP
- 1895 OUT-M-BYT OTIR Write first block.
- 1897 DEC A Repeat until the whole block has been
- 1898 JR NZ,1895,OUT-M-BYT written.
- 189A LD A,+E6 Stop writing.
- 189C OUT (+EF),A
- 189E CALL 0CA9,BORD-REST Restore border colour.
- 18A1 POP HL Restore block start address.
- 18A2 RET Finished.
- THE 'RECEIVE BLOCK FROM MICRODRIVE HEAD' SUBROUTINE
- This is the opposite routine to the preceding one. On entry, HL must hold the start address of the header block or of \
- the data block (AFTER the preamble). The bytes are collected from Microdrive head and stored In the appropriate block. \
- The entry points are GET-M-HD or GET-M-BUF, depending upon whether the block to be received is a header or a data \
- block.
- 18A3 GET-M-HD PUSH HL Save start address.
- 18A4 LD DE,+000F Block length.
- 18A7 JR 18AD,GET-M-BLK Jump forward.
- 18A9 GET-M-BUF PUSH HL Save start address.
- 18AA LD DE,+0210 Block length.
- 18AD GET-M-BLK LD B,E Copy 'length' into BC in
- 18AE LD C,D a reversed form.
- 18AF INC C Increment high byte of 'length'.
- 18B0 PUSH BC
- 18B1 CHK-AGAIN LD B,+08 Loop 8 times.
- 18B3 CHKLOOP CALL 18E9,TEST-BRK Give an error if BREAK pressed.
- 18B6 IN A,(+EF) The GAP line is read repeatedly;
- 18B8 AND +04 it must be found 'low' after a 'high'
- 18BA JR Z,18B1,CHK-AGAIN period.
- 18BC DJNZ 18B3,CHKLOOP
- 18BE CHK-AG-2 LD B,+06
- 18C0 CHK-LP-2 CALL 18E9,TEST-BRK
- 18C3 IN A,(+EF)
- 18C5 AND +04
- 18C7 JR NZ,18BE,CHK-AG-2
- 18C9 DJNZ 18C0,CHK-LP-2
- 18CB POP BC Restore BC.
- 18CC LD A,+EE Start reading.
- 18CE OUT (+EF),A
- 18D0 POP HL Restore 'start address'.
- 18D1 PUSH HL
- 18D2 DR-READY IN A,(+EF) Read SYNC line to synchronize the
- 18D4 AND +02 reading with the start of the block.
- 18D6 JR NZ,18D2,DR-READY Repeat until SYNC is found low.
- 18D8 CALL 18E9,TEST-BRK Give an error if BREAK pressed.
- 18DB LD A,C A holds the high counter.
- 18DC LD C,+E7 Input port.
- 18DE IN-M-BLK INIR Read first block.
- 18E0 DEC A Repeat until the whole block has
- 18E1 JR NZ,18DE,IN-M-BLK been read.
- 18E3 LD A,+EE Finished.
- 18E5 OUT (+EF),A
- 18E7 POP HL Restore block start address.
- 18E8 RET
- TIlE 'TEST-BRK' SUBROUTINE
- The BREAK key is checked and the error 'BREAK into program' is made if it is pressed.
- 18E9 TEST-BRK LD A,+7F Read port +7FFE.
- 18EB IN A,(+FE)
- 18ED RRA Only bit 0.
- 18EE RET C Return if SPACE not being pressed.
- 18EF LD A,+FE Read port +FEFE.
- 18F1 IN A,(+FE)
- 18F3 RRA Only bit 0.
- 18F4 RET C Return if CAPS SHIFT not being pressed
- 18F5 LD (ERR-NR),+14 Store error code.
- 18F9 RST 28,ROMERR Report the error.
- THE 'DELAY-BC' SUBROUTINE
- This subroutine is called to insert delays in the program execution, depending upon the value of BC. The exact delay \
- is (BC * 26 - 43) T cycles.
- 18FA DELAY-BC PUSH AF Save accumulator.
- 18FB DELAY-BC1 DEC BC Decrease counter.
- 1BFC LD A,B Repeat until the counter reaches 0.
- 18FD OR C
- 18FE JR NZ,18FB,DELAY-BC1
- 1900 POP AF Restore accumulator.
- 1901 RET Finished.
- The following are two subroutines that are never called from the Shadow ROM code. These subroutines operate evidently \
- on the buffer's contents of a Microdrive channel.
- 1902 UNKN-1 PUSH HL
- 1903 PUSH IX
- 1905 POP HL
- 1906 LD BC,+0052
- 1909 ADD HL,BC
- 190A LD B,H
- 190B LD C,L
- 190C LD HL,+0000
- 190F LD DE,+0000
- 1912 EXX
- 1913 LD BC,+0200
- 1916 LD HL,+0000
- 1919 LD DE,+0000
- 191C UNKN-2 EXX
- 191D LD A,(BC)
- 191E INC BC
- 191F ADD A,E
- 1920 LD E,A
- 1921 JR NC,1929,UNKN-3
- 1923 INC D
- 1924 JR NZ,1929,UNKN-3
- 1928 EXX
- 1929 UNKN-3 ADD HL,DE
- 192A EXX
- 192B ADC HL,DE
- 192D DEC BC
- 192E LD A,B
- 192F OR C
- 1930 JR NZ,191C,UNKN-2
- 1932 LD D,E
- 1933 EXX
- 1934 LD A,D
- 1935 LD E,+00
- 1937 SLA D
- 1939 EXX
- 193A LD E,A
- 193B RL E
- 193D RL D
- 193F EXX
- 1940 ADD HL,DE
- 1941 EXX
- 1942 ADC HL,DE
- 1944 PUSH HL
- 1945 EXX
- 1946 PUSH HL
- 1947 PUSH BC
- 1948 POP HL
- 1949 POP BC
- 194A LD E,+00
- 194C LD A,C
- 194D CP (HL)
- 194E JR Z,1952,UNKN-4
- 1950 INC E
- 1951 LD (HL),A
- 1952 UNKN-4 INC HL
- 1953 LD A,B
- 1954 CP (HL)
- 1955 JR Z,1959,UNKN-5
- 1957 INC E
- 1958 LD (HL),A
- 1959 UNKN-5 INC HL
- 195A POP BC
- 195B LD A,C
- 195C CP (HL)
- 195D JR Z,1961,UNKN-6
- 195F INC E
- 1960 LD (HL),A
- 1961 UNKN-6 INC HL
- 1962 LD A,B
- 1963 CP (HL)
- 1964 JR Z,1968,UNKN-7
- 1966 INC E
- 1967 LD (HL),A
- 1968 UNKN-7 LD A,E
- 1969 OR A
- 196A POP HL
- 196B RET
- l96C UNKN-8 PUSH IX
- 196E POP HL
- 196F LD DE,+0052
- 1972 ADD HL,DE
- 1973 LD BC,+0200
- 1976 UNKN-9 LD A,(HL)
- 1977 XOR +55
- 1979 LD (HL),A
- 197A INC HL
- 197B DEC BC
- 197C LD A,B
- 197D OR C
- 197E JR NZ,1976,UNKN-9
- 1980 RET
- The 'Hook code' routines
- THE 'HOOK-CODE' ROUTINE
- This routine is entered from 00EB with the A register holding a 'hook code', or an invalid error code. The routine \
- calls a set of subroutines in the shadow ROM, and is intended to help the machine-code user. Only the value held in \
- the accumulator may be passed to the called subroutine.
- 1981 HOOK-CODE CP +18 Continue with 'hook' codes.
- 1983 JR C,1987,CLR-ERR
- 'Hook code error'
- 1985 RST 20,SH-ERR Call the error handling routine.
- 1986 DEFB +12
- 1987 CLR-ERR LD (ERR-NR),+FF The 'error' is cleared.
- 198B SET 2,(FLAGS)
- 198F INC HL Advance return address past the
- error code.
- 1990 EX (SP),HL Store new return address; the initial
- value of A goes into H.
- 1991 PUSH HL Save this value.
- 1992 ADD A,A Multiply code by two.
- 1993 LD D,+00 Pass offset into DE.
- 1995 LD E,A
- 1996 LD HL,+19A9 Start of 'hook code addresses' table.
- 1999 ADD HL,DE Index into this table.
- 199A LD E,(HL) Fetch low byte of the address.
- 199B INC HL
- 199C LD D,(HL) Fetch high byte.
- 199D POP AF Restore initial value of A.
- 199E LD HL,+0700 Return address is UNPAGE.
- 19Al PUSH HL
- 19A2 EX DE,HL Move address to HL.
- l9A3 JP (HL) Jump to the 'hook code' routine.
- THE 'HOOK CODE +32' ROUTINE
- This 'hook code' is designed to call (when the main ROM is paged in) any subroutine held in the shadow ROM. The \
- address of the subroutine to be called is taken from HD-11.
- 19A4 HOOK-32 LD HL,(HD-11) Fetch address of the routine.
- 19A7 JP (HL) Jump to the routine.
- THE 'HOOK CODE +31' ROUTINE
- This 'hook code' has the task of creating the new system variables if nonexistent. Note that the routine is made by a \
- single RET instruction, because the variables have been created on entry to the shadow RON.
- 19A8 HOOK-3l RET Jump indirectly to UNPAGE.
- THE 'HOOK CODE ADDRESSES' TABLE
- This jump table is made by the 24 addresses of the routines called by using the various 'hook codes'. Note that hook \
- code +2B jumps incorrectly to the same routine as hook code +22. The correct address seems to be +1AF0.
- 19A9 DEFW +19D9,CONS-IN Hook code +1B.
- 19AB DEFW +19EC,CONS-OUT Hook code +1C.
- 19AD DEFW +0B81,BCHAN-IN Hook code +1D.
- 19AF DEFW +0C5A,BCHAN-OUT Hook code +1E.
- 1981 DEFW +19FC,PRT-OUT Hook code +1F.
- 1983 DEFW +1A01,KBD-TEST Hook code +20.
- 1985 DEFW +17F7,SEL-DRIVE Hook code +21.
- 1987 DEFW +1B29,OP-TEMP-M Hook code +22.
- 1989 DEFW +12A9,CLOSE-M2 Hook code +23.
- 198B DEFW +1D6E,ERASE Hook code +24.
- 198D DEFW +1A09,READ-SEQ Hook code +25.
- 198F DEFW +11FF,WR-RECD Hook code +26.
- 19C1 DEFW +1A17,RD-RANDOM Hook code +27.
- 19C3 DEFW +1A4B,RD-SECTOR Hook code +28.
- 19C5 DEFW +1A86,RD-NEXT Hook code +29.
- 19C7 DEFW +1A91,WR-SECTOR Hook code +2A.
- 19C9 DEFW +1B29,OP-TEMP-M Hook code +2B.
- 19CB DEFW +10C4,DEL-M-BUF Hook code +2C.
- 19CD DEFW +0EA9,OP-TEMP-N Hook code +2D.
- 19CF DEFW +1A24,CLOSE-NET Hook code +2E.
- 19D1 DEFW +1A31,GET-PACK Hook code +2F.
- 19D3 DEFW +0DB2,SEND-PACK Hook code +30.
- 19D5 DEFW +19A8,HOOK-31 Hook code +31.
- 19D7 DEFW +19A4,HOOK-32 Hook code +32.
- THE 'CONSOLE INPUT' SUBROUTINE
- This subroutine is called by using 'hook code' +1B. It simply waits until a key is pressed and returns the character \
- code in the A register. This 'hook code' has been included because the keyboard is not scanned when the main ROM is \
- paged-in.
- 19D9 CONS-IN EI Enable interrupts.
- 19DA RES 5,(FLAGS) Signal 'ready for a new key'.
- 19DE WTKEY HALT Wait 1/50th of second.
- 19DF RST 10,CALBAS Call the keboard scan routine
- 19E0 DEFW +02BF in the main ROM.
- 19E2 BIT 5,(FLAGS) Repeat the scan if no key has been
- 19E6 JR Z,19DE,WTKEY pressed.
- 19E8 LD A,(LAST-K) Fetch character code.
- 19EB RET Finished.
- THE 'CONSOLE OUTPUT' SUBROUTINE
- This subroutine is called by using 'hook code' +1C. The character held in the A register is printed on the screen, \
- with scroll suppressed.
- 19EC CONS-OUT PUSH AF Save character to be printed.
- 19ED LD A,+FE Use stream '-2' (Screen).
- 19EF OUT-CODE LU HL,+5C8C This is SCR-CT.
- 19F2 LD (HL),+FF Set scroll counter.
- 19F4 RST 10,CALBAS Call CHAN-OPEN in the main ROM to
- 19F5 DEFW +1601 select the stream.
- 1SF7 POP AF Restore character.
- 19F8 RST 10,CALBAS Call 'PRINT-A' restart to print the
- 19F9 DEFW +0010 character.
- 19FB RET Finished.
- THE 'PRINTER OUTPUT' SUBROUTINE
- This subroutine is called by using hook code +1F. This is identical to the preceding one, but the output is directed \
- to the stream +03 (normally the ZX
- Printer).
- 19FC PRT-OUT PUSH AF Save character to be printed.
- 19FD LD A,+03 Select stream 3.
- 19FF JR 196F,OUT-CODE Jump back.
- THE 'KEYBOARD TEST' SUBROUTINE
- This is called by using 'hook code' +20. The keyboard is scanned and the zero flag returned reset if any key has been \
- pressed.
- 1A01 KBD-TEST XOR A Clear A, allowing for the whole
- keyboard to be examined.
- 1A02 IN A,(+FE) Read the keyboard.
- 1A04 AND +1F Only 5 less significant bits.
- 1A06 SUB +1F Return with sign negative and zero
- 1A08 RET flag reset if any key has been
- pressed.
- THE 'READ SEQUENTIAL' SUBROUTINE
- This is called by using 'hook code' +25. The subroutine reads into the datablock of the current "m" channel, the next \
- record of a named PRINT-type file. On entry IX must hold the "m" channel start address, and CHREC the number of the \
- current record. CHREC will be automatically incremented. CHDRIV must hold the drive number and CHNAME must hold the \
- file name.
- 1A09 READ-SEQ BIT 1,(RECFLG) Jump if the current record is not
- 1A0D JR Z,1A14,INCREC the EOF one.
- 1A0F LD (ERR-NR),+07 Otherwise signal 'end of file'.
- 1A13 RST 28,ROMERR Report the error.
- 1A14 INCREC INC (CHREC) Increment record number and continue
- into RD-RANDOM.
- THE 'READ RANDOM' SUBROUTINE
- This subroutine is called by using 'hook code' +27. The record number CHREC of a PRINT-type file is loaded into the \
- data block. The other variables are to be set as for READ-SEQ above.
- 1A17 RD-RANDOM CALL 1177,GET-RECD Load CHREC record.
- 1A1A BIT 2,(RECFLG) Return only if this is a PRINT-type
- 1A1E RET Z file.
- 1A1F CALL 10C4,DEL-M-BUF Otherwise reclaim the channel, and
- report the error.
- 'Wrong file type'
- 1A22 RST 20,SH-ERR Call the error handling routine.
- 1A23 DEFB +16
- THE 'CLOSE NETWORK CHANNEL' SUBROUTINE
- This is called by using 'hook code' +2E. First, the remaining bytes in the "n" channel buffer whose base address is \
- held in the CURCHL system variable, are sent as EOF block (if the channel is opened for writing). The channel is then \
- reclaimed.
- 1A24 CLOSE-NET CALL 0EF5,SEND-NEOF Send the EOF block if required.
- 1A27 PUSH IX Move channel start address to HL.
- 1A29 POP HL
- 1A2A LD BC,+0114 Length of "n" channel.
- 1A2D RST 10,CALBAS Call RECLAIM-2 to delete the channel.
- 1A2E DEFW +19E8
- 1A30 RET Finished.
- THE 'GET PACKET FROM NETWORK' SUBROUTINE
- This is called by using 'hook code' +2F. Unfortunately the subroutine is unusable, because the carry flag (that \
- signals if an error has occurred) is corrupted by exit via the BORD-REST subroutine. You may use GET-N-BUF at 03DF to \
- read a packet.
- 1A31 GET-PACK LD A,(IOBORD) Fetch border colour.
- 1A34 OUT (+FE),A Change border colour.
- 1A36 DI Disable interrupts.
- 1A37 CALL 0F1E,WT-SCOUT Wait for a 'scout' leader.
- 1A3A JR NC,1A46,GP-ERROR Jump if 'time-out' occurs.
- 1A3C CALL 0E18,GET-NBLK Wait for header and data block.
- 1A3F JR NZ,1A46,GP-ERROR Jump with any error.
- 1A41 EI Enable interrupts.
- 1A42 AND A Reset carry to signal 'successful'.
- 1A43 JP 0CA9,BORD-REST But it is corrupted into BORD-REST.
- 1A46 CF-ERROR SCF Signal 'error'
- 1A47 EI Enable interrupts.
- 1A48 JP 0CA9,BORD-REST Again the carry flag will be
- corrupted.
- THE 'READ SECTOR' SUBROUTINE
- This is called by using 'hook code' +28. Before using this, you must start the required drive motor, and store a \
- sector number into CHREC. The data block stored into the given sector is then read in the channel area (pointed by \
- IX), and used if it is a PRINT-type record. The carry flag is returned reset if the reading is successful.
- 1A4B RD-SECTOR LD HL,+00F0 Counts through 240 sectors.
- 1A4E LD (SECTOR),HL
- 1A51 NO-GOOD CALL 12C4,GET-M-HD2 Get a header.
- 1A54 LD A,(HDNUM) Fetch current sector number.
- 1A57 CP (CHREC) Compare with given sector number.
- 1A5A JR Z,1A63,USE-C-RC Jump if found the required sector.
- 1A5C CALL 1312,DEC-SECT Otherwise decrease SECTOR.
- 1A5E JR NZ,1A51,NO-G00D Jump until 240 sectors have been
- examined.
- 'File not found'
- 1A61 RST 20,SH-ERR Call the error handling routine.
- 1A62 DEFB +11
- 1A63 USE-C-RC PUSH IX Make HL point to RECFLG (i.e. sTart
- 1A65 POP HL of data block.
- 1A66 LD DE,+0043
- 1A69 ADD HL,DE
- 1A6A CALL 18A9,GET-M-BUF Read data block.
- 1A6D CALL 1341,CHKS-HD-R Calculate current checksum.
- 1A70 JR NZ,1A81,DEL-B-CT Jump if it does not match with old
- checksum.
- 1A72 LD DE,+000F Make HL point to start of buffer.
- 1A75 ADD HL,DE
- 1A76 CALL 1346,CHKS-BUFF Calculate checksum of buffer.
- 1A79 JR NZ,1A81,DEL-B-CT Jump if it does not match with old
- checksum.
- 1A7B OR A Return with carry flag reset if
- 1A7C BIT 2,(RECFLG) this is a PRINT-type file.
- 1A80 RET Z
- 1A81 DEL-B-CT CALL 1AE0,CLR-BUFF Otherwise clear buffer contents.
- 1A84 SCF Return with carry flag set to signal
- 1A85 RET the error.
- THE 'READ NEXT SECTOR' SUBROUTINE
- This is used by using 'hook code' +29. The first header and data block that pass through the Microdrive head are \
- copied into the channel area pointed by IX. As with the previous subroutine, the drive motor is to be started before \
- calling it.
- 1A86 RD-NEXT LD HL,+00F0 Initialise SECTOR to 240.
- 1A89 LD (SECTOR),HL
- 1A8C CALL 12C4,GET-M-HD2 Fetch the first header.
- 1A8F JR 1A63,USE-C-RC Continue back.
- THE 'WRITE SECTOR' SUBROUTINE
- This is used by using 'hook code' +2A. It is the opposite routine of 'RD-SECTOR' above. The Microdrive unit is to be \
- started before calling the routine. The current data block in the "m" channel pointed by the IX register is written \
- onto the sector whose number is specified by CHREC. Other channel variables, such as CHNAME, are to be set as required.
- 1A91 WR-SECTOR LD HL,+00F0 Pass through 240 sectors.
- 1A94 CD (SECTOR),HL
- 1A97 PUSH IX Make HL point to the data block
- 1A99 POP HL preamble.
- 1A9A LD DE,+0037
- 1A9D ADD HL,DE
- 1A9E PUSH HL Save this address.
- 1A9F LD DE,+000C Now point to RECFLG.
- 1AA2 ADD HL,DE
- 1AA3 CALL 1341,CHKS-HD-R Calculate DESCHK checksum.
- 1AA6 LD DE,+000F Now point to the buffer.
- 1AAA CALL 1346,CHKS-BUFF Calculate DCHK checksum.
- 1AAD WR-S-l CALL 12C4,GET-M-HD2 Get a header.
- 1AB0 LD A,(HDNUMB) Fetch current sector number.
- 1AB3 CP (CHREC) See whether it is the expected one.
- 1AB6 JR Z,1ABF,WR-S-2 Jump if so.
- 1AB8 CALL 1312,DEC-SECT Otherwise decrease SECTOR.
- 1ABB JR NZ,1AAD,WR-S-l Loop until 240 sectors have been
- examined.
- 'File not found'
- 1ABD RST 20,SH-ERR Call the error handling routine.
- 1ABE DEFB +11
- 1ABF WR-S-2 IN A,(+EF) Continue if the write-protect tab
- 1AC1 AND +01 is present.
- 1AC3 JR NZ,1AC7,WR-S-3
- 'Drive write protected'
- 1AC5 RS-SH RST 20,SH-ERR Call the error handling routine.
- 1AC6 DEFB +0E
- 1AC7 WR-S-3 LD A,+E6 Start writing.
- 1AC9 OUT (+EF),A
- 1ACB LD BC,+0168 Wait until the first gap is finished.
- 1ACE CALL 18FA,DELAY-BC
- 1AD1 POP HL Restore address of data block preamble
- 1AD2 CALL 1878,OUT-M-BUF Write data block onto cartridge.
- 1AD5 LD A,+EE Stop writing.
- 1AD7 OUT (+EF),A
- 1AD9 CALL 12DF,CHECK-MAP Finally set the appropriate map bit.
- 1ADC LD A,B
- 1ADD OR (HL)
- 1ADE LD (HL),A
- 1ADF RET Finished.
- THE 'CLEAR BUFFER CONTENTS' SUBROUTINE
- This subroutine is called from RD-SECTOR and RD-NEXT subroutines to clear the data received into the "m" buffer, if \
- they are not part of a PRINT-type file.
- 1AE0 CLR-BUFF PUSH IX Make HL point to the start of the
- 1AE2 POP HL "m" buffer.
- 1AE3 LD DE,+0052
- 1AE6 ADD HL,DE
- 1AE7 LD D,H Copy this address into DE.
- 1AE8 LD E,L
- 1AE9 INC DE 'Destination' is next byte.
- 1AEA LD BC,+01FF Buffer length - 1.
- 1AED LDIR Clear the buffer.
- 1AEF RET Finished.
- THE 'OPEN A PERMANENT "M" CHANNEL' SUBROUTINE
- This is the actual OPEN corinnand referred to the "m" channel. A permanent "m" channel is opened, and it is attached \
- to the stream held into S-STR1 (provided that the file is a PRINT-type file).
- 1AF0 OP-M-STRM LD A,(S-STR1) Fetch stream number.
- 1AF3 ADD A,A Multiply by two.
- 1AF4 LD HL,+5Cl6 Address of data for stream 0.
- 1AF7 LD E,A Use (stream*2) as offset.
- 1AF8 LD D,+00
- 1AFA ADD HL,DE Index into STRMS area.
- 1AFB PUSH HL Save address of data for the required
- stream.
- 1AFC CALL 1B29,OP-TEMP-M Open a temporary "m" channel.
- 1AFF BIT 0,(CHFLAG) Jump if this is a 'read' file.
- 1B03 JR Z,1B0D,MAKE-PERM
- 1B05 IN A,(+EF) Jump if the write-protect tab is
- 1B07 AND +01 present.
- 1B09 JR NZ,1B0D,MAKE-PERM
- 'Drive 'write' protected'
- 1B0B RST 20,SH-ERR Call the error handling routine.
- 1B0C DEFB +0E
- 1B0D MAKE-PERN RES 7,(IX+4) Make the channel permanent.
- 1B11 XOR A Switch off drive motors.
- 1B12 CALL 17F7,SEL-DRIVE
- 1B15 BIT 0,(CHFLAG) Jump with 'write' files.
- 1B19 JR NZ,1B23,STORE-DSP
- 1B1B BIT 2,(RECFLG) Jump with PRINT-type 'read' files.
- 1B1F JR Z,1B23,STORE-DSP
- 'Wrong file type'
- 1B21 RST 20,SH-ERR Call the error handling routine.
- 1B22 DEFB +16
- 1B23 STORE-DSP EX DE,HL DE holds new stream data.
- 1B24 POP HL Restore stream address.
- 1B25 LD (HL),E Store stream data into STRMS area.
- 1B26 INC HL
- 1B27 LD (HL),D
- 1B28 RET Finished.
- THE 'OPEN TEMPORARY "M" CHANNEL' SUBROUTINE
- This fundamental subroutine is used to open a temporary "m" channel in the CHANS area. First a temporary "m" channel \
- is created. Then the drive whose number is held into D-STR1 is started, and searched for a file whose name is held into
- N-STR1. A map area is created (unless it already exists), and its contents are setup according to the cartridge \
- contents (the bits reset indicate 'free for use' sectors). Various flags are returned as follows:
- - bit 0 of CHFLAG set with 'write' files.
- - bit 1 of RECFLG set with EOF block.
- - bit 2 of RECFLG set with PRINT-type files.
- On exit, HL holds a 'stream data' displacement that may be used to attach the channel to a stream. The drive motor \
- will not be switched off. Note that H'L' is corrupted and the user must preserve its value when using this routine \
- from BASIC.
- 1B29 OP-TEMP-M CALL 0FE8,SET-T-MCH Create a temporary "m" channel.
- 1B2C PUSH HL Save 'stream displacement'
- 1B2D LD A,(CHDRIV) Fetch drive number.
- 1B30 CALL 17F7,SEL-DRIVE Turn on drive motor.
- 1B33 LD BC,+00FF Count 255 sectors.
- 1B36 LD (SECTOR),BC
- 1B3A OP-F-1 CALL 11A5,G-HD-RC Get header and data block.
- 1B3D JR C,1B5F,OP-F-4 Jump with any error.
- 1B3F JR Z,1B5C,OP-F-3 Jump with 'free' sectors.
- 1B41 RES 0,(CHFLAG) Signal 'read file' if the file is
- already present on cartridge.
- 1B45 LD A,(RECNUM) Jump if this is not the 1st record.
- 1B48 OR A
- 1B49 JR NZ,1B57,OP-F-2
- 1B4B PUSH IX Make HL point to the data buffer.
- 1B4D POP HL
- 1B4E LD DE,+0052
- 1B51 ADD HL,DE
- 1B52 CALL 1346,CHKS-BUFF Calculate new DCHK checksum.
- 1B55 JR Z,1B6C,OF-F-5 Jump it it is equal to the old one.
- 1B57 OP-F-2 CALL 117D,GET-R-2 Fetch first record of file.
- 1B5A JR 1B6C,OP-F-5 Jump forward.
- 1B5C OP-F-3 CALL 12FE,RES-B-MAP Reset map bit to signal 'free sector'
- 1B5F OP-F-4 CALL 1312,DEC-SECT Decrease SECTOR.
- 1B62 JR NZ,1B3A,OP-F-1 Consider all 255 sectors.
- 1B64 RES 1,(RECFLG) 'No EOF'.
- 1B68 RES 2,(RECFLG) 'PRINT-type file' (opened for writing)
- 1B6C OP-F-5 POP HL Restore stream 'stream data'.
- 1B6D RET Finished.
- The Microdrive command routines
- THE 'FORMAT' COMMAND ROUTINE
- The action of FORMATting a new cartridge is performed by this subroutine. It is entered with the drive number into \
- D-STR1, the cartridge name address and length into N-STR1.
- 1B6E FORMAT CALL 0FE8,SET-T-MCH Create channel and map.
- 1B71 LD A,(CHDRIV) Fetch drive number.
- 1B74 CALL 182A,SW-MOTOR Turn on the motor.
- 1B77 LD BC,+32C8 Wait before checking the write-
- 1B7A CALL 18FA,DELAY-BC protect tab.
- 1B7D DI Disable interrupts.
- 1B7E IN A,(+EF) Continue only if the tab is
- 1B80 AND +01 present.
- 1B82 JR NZ,1B86,FORMAT-1
- 'Drive 'write' protected'
- 1B84 RST 20,SH-ERR Call the error handling routine.
- 1B85 DEFB +0E
- 1B86 FORMAT-1 LD A,+E6 Start writing.
- 1B88 OUT (+EF),A
- 1B8A LD BC,+00FF Pass through 255 sectors.
- 1B8D LD (SECTOR),BC
- 1B91 PUSH IX Make DE point to HDNAHE.
- 1B93 POP HL
- 1B94 LD DE,+002C
- 1B97 ADD HL,DE
- 1B98 EX DE,HL
- 1B99 LD HL,+FFE2 Now make HL point to CHNAME
- 1B9C ADD HL,DE (i.e. cartridge name).
- 1B9D LD BC,+000A Name length.
- 1BA0 LDIR Copy cartridge name into HDNAME.
- 1BA2 XOR A Use 'invisible' name by storing zero
- 1BA3 LD (RECNAM),A as first character of the record name.
- 1BA6 SET 0,(HDFLAG) Mark the header block.
- 1BAA RES 0,(RECFLG) Mark the data block.
- 1BAE SET 1,(RECFLG) Mark as 'EOF' block.
- 1BB2 PUSH IX Make HL point to the start of the
- 1BB4 POP HL data buffer.
- 1BB5 LD DE,+0052
- 1BB8 ADD HL,DE
- Now the data buffer is filled with bytes +FC; and the checksums are calculated.
- 1BB9 LD B,+00 Counts 256 bytes.
- 1BBB LD A,+FC The byte to be stored.
- 1BBD FILL-B-F LD (HL),A Fill 256 bytes.
- 1BBE INC HL
- 1BBF BJNZ 1BBD,FILL-B-F
- 1BC1 FILL-B-F2 LD (HL),A Fill next 256 bytes.
- 1BC2 INC HL
- 1BC3 DJNZ 1BC1,FILL-B-F2
- 1BC5 PUSH IX Point to start of data block
- 1BC7 POP DE workspace (i.e. RECFLG).
- 1BC8 LD HL,+0043
- 1BCB ADD HL,DE
- 1BCC CALL 1341,CHKS-HD-R Calculate DESCHK checksum.
- 1BCF LD DE,+000F Make HL point to the data buffer.
- 1BD2 ADD HL,DE
- 1BD3 CALL 1346,CHKS-BUFF
- Now this data block is written in all sectors with HDNUMB numbered from 254 to 1
- 1BD6 WR-F-TEST CALL 1312,DEC-SECT Decrease SECTOR.
- 1BD9 JR Z,1C0A,TEST-SCT Jump when SECTOR has reached zero.
- 1BDB LD (HDNUMB),C Take HDNUMB from SECTOR.
- 1BDE PUSH IX Make HL point to the start of the
- 1BE0 POP HL header workspace, i.e. HDFLAG.
- 1BE1 LD DE,+0028
- 1BE4 ADD HL,DE
- 1BE5 CALL 1341,CHKS-HD-R Calculate HDCHK checksum.
- 1BE8 LD DE,+FFF4 Make HL point to the header block
- 1BEB ADD HL,DE preamble.
- 1BEC CALL 1872,OUT-M-HD Write the header onto the cartridge.
- 1BEF LD BC,+01B2 Wait to create part of the first gap.
- 1BF2 CALL 18FA,DELAY-BC
- 1BF5 PUSH IX Make HL point to data block preamble.
- 1BF7 POP HL
- 1BF8 LD DE,+0037
- 1BFB ADD HL,DE
- 1BFC CALL 1878,OUT-M-BUF Write the data block.
- 1BFF LD BC,+033F Part of the second gap is created.
- 1C02 CALL 1BFA,DELAY-BC
- 1C05 CALL 18E9,TEST-BRK Give an error if BREAK has been
- pressed.
- 1C08 JR 18D6,WR-F-TEST Continue with next sector.
- 1C0A TEST-SCT LD A,+EE Stop writing.
- 1C0C OUT (+EF),A
- 1C0E LD A,(CHDRIV) Fetch drive number.
- 1C11 CALL 17F7,SEL-DRIVE Start motor.
- Now the sectors contain 'test data', and are to be read back to see if they are usable. If the checksums are correct, \
- the appropriate map bit is reset to signal 'free for use' sectors.
- 1C14 LD BC,+00FF Pass through 255 sectors,
- 1C17 LD (SECTOR),BC
- 1C1B CHK-SCT CALL 12C4,GET-H-HD2 Fetch a header.
- 1C1E CALL 12DF,CHECK-MAP Check map bit and jump with
- 1C21 JR Z,1C3E,CHK-NSECT examined sectors.
- 1C23 PUSH IX Make HL point to start of data block
- 1C25 POP HL workspace (i.e. RECFLG).
- 1C26 LD DE,+0043
- 1C29 ADD HL,DE
- 1C2A CALL 18A9,GET-M-BF Fetch data block.
- 1C2D CALL 1341,CHKS-HD-R Calculate DESCHK checksum.
- 1C30 JR NZ,1C3E,CHK-NSECT Jump with faulty sectors.
- 1C32 LD DE,+000F Make HL point to the data buffer.
- 1C35 ADD HL,DE Start of data buffer.
- 1C36 CALL 1346,CHKS-BUFF Calculate DCHK checksum.
- 1C39 JR NZ,1C3E,CHK-NSECT Jump with faulty sectors.
- 1C3B CALL 12FE,RES-B-MAP Reset map bit with usable sectorS.
- 1C3E CHK-NSECT CALL 1312,DEC-SECT Decrease SECTOR.
- 1C41 JR NZ,1C1B,CHK-SCT Check all sectors.
- 1C43 CALL 1E3E,IN-CHK Initialise RECFLG, BECLEN, and DESCHK.
- At this point all sectors that have been found 'usable' (marked with a reset bit in the map) are written with RECFLG \
- and RECLEN zeroed, as to mark them 'working' for future use.
- 1C46 MARK-FREE CALL 1264,CHK-FULL Jump until all bits in the map
- 1C49 JR NZ,1C53,MK-BLK are made set.
- 1C48 XOR A Turn off drive motors.
- 1C4C CALL 17F7,SEL-DRIVE
- 1C4F CALL 10C4,DEL-M-BUF Reclaim "m" channel and map.
- 1C52 RET Finished.
- 1C53 MK-BLK CALL 1275,SEND-BLK Write data block in the next 'free'
- sector.
- 1C56 JR 1C46,MARK-FREE Jump back.
- THE 'CAT' COMMAND ROUTINE
- This subroutine makes a CATalogue of the cartridge inserted in the drive whose number must be specified by D-STR1. \
- S-STR1 must hold the stream to which the catalogue is to be directed.
- 1C58 CAT LD A,(S-STR1) Fetch stream number.
- 1C5B RST 10,CALBAS Call CHAN-OPEN to select the
- 1C5C DEFW +1601 specified stream.
- 1C5E CALL 0FE8,SET-T-MCH Set a temporary "m" channel.
- 1C61 LD A,(CHDRIV) Fetch drive number.
- 1C64 CALL 17F7,SEL-DRIVE Turn on drive motor.
- 1C67 LD BC,+00FF Pass through 255 sectors.
- 1C6A LD (SECTOR),BC
- 1C6E CAT-LP CALL 12C4,GET-M-HD2 Fetch a header.
- 1C71 CALL 1E53,G-RDES Fetch record descriptor.
- 1C74 JR NZ,1C6E,CAT-LP Repeat until data is correct.
- 1C76 LD A,(RECFLG) The sector is 'free for use' when
- 1C79 OR (RECLEN-hi) bit 1 of both RECFLG and RECLEN-hi
- 1C7C AND +02 are reset (see comment after 1C43).
- 1C7E JR NZ,1C85,IN-NAME Jump if not a 'free' sector.
- 1C80 CALL 12FE,RES-B-MAP Reset map bit if it is a 'free'
- sector.
- 1C83 JR 1CEE,F-N-SCT Continue with next sector.
- If the current sector is not 'free', then the name of the file held in it is to be collected and inserted in \
- alphabetical order into the data buffer of the "m" channel. Names starting with CHR$ 0 are refused.
- 1C85 IN-NAME LD A,(RECNAM) Fetch first character of file name.
- 1C88 OR A Continue with next sector if this is
- 1C89 JR Z,1CEE,F-N-SCT CHR$ 0.
- 1C8B PUSH IX Make HL point to the data buffer.
- 1C8D POP HL
- 1C8E LD DE,+0052
- 1C91 ADD HL,DE
- 1C92 LD DE,+000A Length of filename.
- 1C95 LD B,+00 B is initiallly cleared.
- 1C97 LD C,(CHREC) Start with 'file count' cleared.
- The following loop tests to make sure that the name of the current record is not already stored in the buffer.
- 1C9A SE-NAME LD A,C Jump forward when all existing names
- 1C9B OR A have been examined.
- 1C9C JR Z,1CD4,INS-NAME
- 1C9E PUSH HL Save registers.
- 1C9F PUSH IX
- 1CA1 PUSH BC
- 1CA2 LD B,+0A Counts characters in a name.
- 1CA4 T-NA-1 LD A,(HL) Fetch a character from buffer.
- 1CA5 CF (RECNAM) Compare against RECNAM.
- 1CA8 JR NZ,1CAF,T-NA-2 Jump if they do not match.
- 1CAA INC HL Point to next character,
- 1CAB INC IX
- 1CAD DJNZ 1CA4,T-NA-1 Loop until all the names have been
- compared.
- 1CAF T-NA-2 POP BC Restore registers.
- 1CB1 POP IX
- 1CB2 POP HL
- 1CB3 JR Z,1CEE,F-N-SCT Continue with next sector if the name
- is already stored.
- 1CB5 JR NC,1CBB,ORD-NAM Jump if the name is surely not in the
- buffer (i.e. 'lower' than the current
- one).
- 1CB7 ADD HL,DE Otherwise point to next name.
- 1CB8 DEC C Decrease number of names to be
- examined.
- 1CB9 JR 1C9A,SE-NAME Loop back.
- The address at which the name is to be inserted has been calculated; the following names are moved down to create the \
- space for storing the new name.
- 1CBB ORD-NAM PUSH HL Save registers.
- 1CBC PUSH DE
- 1CBD PUSH BC
- 1CBE PUSH HL
- 1CBF SLA C Multiply by two the number of names
- to be moved down.
- 1CC1 LD H,B Move result into HL (B holds 0).
- 1CC2 LD L,C
- 1CC3 ADD HL,BC Multiply this by 5, to get in HL the
- 1CC4 ADD HL,BC number of bytes to be moved down
- 1CC5 ADD HL,BC (i.e. number of names * 10).
- 1CC6 ADD HL,BC
- 1CC7 LD B,H Move into BC the length of the block
- 1CC8 LD C,L to be moved.
- 1CC9 POP HL Restore address where the current
- name is to be inserted.
- 1CCA DEC HL Make HL point to the last character
- 1CCB ADD HL,BC of the last name.
- 1CCC EX DE,HL Calculate into DE the address 'HL+10'.
- 1CCD ADD HL,DE
- 1CCE EX DE,HL
- 1CCF LDIR Move down the required names (leaving
- 10 bytes for the current name).
- 1CD1 POP BC Restore registers.
- 1CD2 POP DE
- 1CD3 POP HL
- 1CD4 INS-NAME PUSH IX Save channel start address.
- 1CD6 LD B,+0A Ten characters in a name.
- 1CD8 MOVE-NA LD A,(IX+RECNAM) Fetch a character from the name.
- 1CDB LD (HL),A Store in the buffer.
- 1CDC INC IX Point to next location.
- 1CDE INC HL
- 1CDF DJNZ 1CB8,MOVE-NA Loop until the whole name has been
- transferred.
- 1CE1 POP IX Restore channel start address.
- 1CE3 LD A,(CHREC) Fetch number of names in the buffer.
- 1CE6 INC A Include current name in the count.
- 1CE7 LD (CHREC),A Store new number.
- 1CEA CP +32 Jump if 50 names have been collected
- 1CEC JR Z,1CF4,BF-FILLED
- 1CEE F-N-SCT CALL 1312,BEC-SECT Decrease SECTOR.
- 1CF1 JP NZ,1C6E,CAT-LP Repeat for all 255 sectors.
- Now the file names are in the data buffer. CHREC holds the number of names stored. First the cartridge name is printed \
- onto the selected stream.
- 1CF4 BF-FILLED PUSH IX Save channel base address.
- 1CF6 XOR A Switch off drive motor.
- 1CF7 CALL 17F7,SEL-DRIVE
- 1CFA PUSH IX Make HL point to HDNAME.
- 1CFC POP HL
- 1CFD LD DE,+002C
- 1D00 ADD HL,DE
- 1D01 CALL 1D50,PRNAME Print cartridge name.
- 1D04 LD A,+0D Print a carriage return.
- 1D06 CALL 1D66,PRCHAR
- 1D09 PUSH IX Make HL point to the data buffer.
- 1D0B POP HL
- 1D0C LD DE,+0052
- 1D0F ADD HL,DE
- 1D11 LD B,(CHREC) Fetch number of stored names.
- 1D13 LD A,B Jump forward if no names have been
- 1D14 OR A stored.
- 1D15 JR Z,1D1C,NONAMES
- 1D17 OT-NAMS CALL 1D53,PRNAME Print all filenames.
- 1D1A DJNZ 1D17,OT-NAMS
- 1D1C NONAMES CALL 1D38,FREESECT Calculate number of 'free' sectors
- 1D1F LD A,E into A.
- 1D20 SRL A Divide by two, giving the kilobytes
- left.
- 1D22 RST 10,CALBAS Call STACK-A to store this value on
- 1D23 DEFW +2D28 the calculator stack.
- 1D25 LD A,+0D Print a carriage return.
- 1D27 CALL 1D66,PRCHAR
- 1D2A RST 10,CALBAS Call PRINT-FP to print the number of
- 1D2B DEFW +2DE3 kilobytes left.
- 1D2D LD A,+0D Print the final carriage return.
- 1D2F CALL 1D66,PRCHAR
- 1D32 POP IX Restore channel start address.
- 1D34 CALL 10C4,DEL-M-BUF Reclaim the channel.
- 1D37 RET Finished.
- THE 'FREESECT' SUBROUTINE
- This subroutine is called to calculate the number of 'free sectors' (I...> bits reset in the map). The number is \
- returned in the I register.
- 1D38 FREESECT LD L,(CHMAP-lo) Fetch address of map.
- 1D3B LD H,(CHMAP-hi)
- 1D3E LD E,+00 Start with E cleared.
- 1D40 LD C,+20 Length of map.
- 1D42 FR-SC-LP LD A,(HL) Fetch a byte from the map.
- 1D43 INC HL Advance the pointer.
- 1D44 LD B,+08 Loop for 8 bits.
- 1D46 FR-S-LPB RRA Jump if this bit is set,
- 1D47 JR C,14DA,FR-S-RES
- 1D49 INC E Otherwise increment counter.
- 1D4A FR-S-RES DJNZ 1D46,FR-S-LPB Repeat for all 8 bits.
- 1D4C DEC C Repeat for all bytes in the map.
- 1D4D JR NZ,1D42,FR-SC-LP
- 1D4F RET Finished.
- THE 'PRNAME' SUBROUTINE
- This is used from the CAT command routine to print a file-name starting from the address held into the HL register.
- 1D50 PRNAME PUSH BC Save BC register.
- 1D51 LD B,+0A Counts 10 characters.
- 1D53 PRNM-LP LD A,(HL) Fetch a character.
- 1D54 CALL 1D66,PRCHAR Print it.
- 1D57 INC HL Increment pointer.
- 1D58 DJNZ 1D53,PRNM-LP Loop until the whole name has been
- printed.
- 1D5A LD A,+0D Print a carriage return.
- 1D5C CALL 1D66,PRCHAR
- 1D5F PUSH HL Save the pointer.
- lD60 RST 10,CALBAS Call main ROM 'TEMPS' subroutine.
- 1D61 DEFW +0D4D
- 1D63 POP HL Restore registers.
- 1D64 POP BC
- 1D65 RET
- THE 'PRCHAR' SUBROUTINE
- The character whose code is held in the A register is sent over the currently selected stream.
- 1D66 PRCHAR PUSH IX Save channel base address.
- 1D68 RST 10,CALBAS Call restart 'PRINT-A' to print the
- 1D69 DEFW +0010 character.
- 1D6B POP IX Restore channel base address.
- 1D6D RET Finished.
- THE 'ERASE' COMMAND SUBROUTINE
- This is also called by using 'hook code' +24. The subroutine is entered with
- D-STR1 holding the drive number and N-STR1 holding the length and the start of the filename, Note that H'L' is \
- corrupted.
- 1D6E ERASE CALL 0FE8,SET-T-MCH Set a temporary "m" channel.
- 1D71 LD A,(CHDRIV) Fetch drive number.
- 1D74 CALL 17F7,SEL-DRIVE Turn on drive motor.
- 1D77 IN A,(+EF) Continue only if the write-nrotect
- 1D79 AND +01 tab is present.
- 1D7B JR NZ,107F,ERASE-1
- 'Drive write protected'
- 1D7D RST 20,SH-ERR Call the error handling routine.
- 1D7E DEFB +0E
- 1D7F ERASE-1 PUSH IX Point to the data buffer.
- 1D81 POP HL
- 1D82 LD DE,+0052
- 1D85 ADD HL,DE
- 1D86 PUSH HL Copy this address into DE.
- 1D87 POP DE
- Now the first 32 locations in the data buffer are cleared. These locations act as a 'pseudo-map', used to mark the \
- sectors to be erased,
- 1D88 INC DE Point to next location.
- 1D89 LD BC,+001F Gap length - 1.
- 1D8C XOR A Clear the first location.
- 1D8D LD (HL),A
- 1D8E LDIR Clear all locations.
- lD90 LD A,+FF CHREC is made holding 255.
- 1D92 CD (CHREC),A
- 1D95 LD BC,+04FB SECTOR is initialised to 'five passes
- 1D98 LD (SECTOR),BC of the tape'.
- The cartridge is searched for the sectors to be erased, and when any such sector is found, the relevant 'pseudo-map' \
- bit is set. A 'normal' map is also set-up.
- 1D9C ERASE-LP CALL 1312,DEC-SECT Decrease SECTOR.
- 1D9F JR Z,1DF8,ERASE-MK Make the ERASE when it reaches 0.
- 1DA1 CALL 12C4,GET-M-HD2 Fetch a header.
- 1DA4 CALL 1E53,G-RDES Fetch record descriptor.
- 1DA7 JR NZ,1DDA,TST-NUM Jump with any error.
- 1DA9 LD A,(RECFLG) Jump it this record is not 'tree'.
- 1DAC OR (RECLEN-hi)
- lDAF AND +02
- 1DB1 JR NZ,1DB8,ERASE-2
- 1DB3 CALL 12FE,RES-B-MAP Otherwise reset map bit to indicate
- 'free sector'.
- 1DB6 JR 1DDA,TST-NUM Jump forward.
- The name of the current record is compared against that of the file to be erased. If the comparison is successful, the \
- 'pseudo-map' bit is set to mark the sector.
- 1DB8 ERASE-2 PUSH IX MAke HL point to RECNAM.
- 1DBA POP HL
- 1DBB LD DE,+0047
- 1DBE ADD HL,DE
- 1DBF LD BC,+000A Counts ten characters in a name.
- 1DC2 CALL 131E,CHK-NAME Compare against CHNAME.
- 1DC5 JR NZ,1DDA,TST-NUM Jump if it does not equal.
- 1DC7 CALL 1306,TEST-PMAP Get position of pseudo-map bit.
- 1DCA LD A,B Fetch bit position.
- 1DCB OR (HL) Set the pseudo-map bit.
- 1DCC LD (HL),A
- 1DCD BIT 1,(RECFLG) Jump if this is not the EOF block.
- 1DD1 JR Z,1DDA,TST-NUN
- 1DD3 LD A,(RECNUM) Otherwise increment record number
- 1DD6 INC A and store it into CHMREC, giving the
- 1DD7 LD (CHREC),A number of sectors that composes the
- file.
- 1DDA TST-NUM PUSH IX Make HL point to the 'pseudo-map'.
- 1DDC POP HL
- 1DDD LD DE,+0052
- 1DE0 ADD HL,DE
- 1DE1 LD E,+00 Clear E register.
- 1DE3 LD C,+20 Length of the pseudo-map.
- IDE5 LP-P-MAP LD A,(HL) Fetch pseudo-map byte.
- 1DE6 INC HL Advance the pointer.
- 1DE7 LD B,+08 Counts 8 bits.
- 1DE9 LP-B-MAP RRA Jump if this bit is reset.
- 1DEA JR NC,1DED,NOINC-C
- 1DEC INC E Otherwise increment counter.
- 1DED NOINC-C DJNZ 1DE9,LP-B-MAP Loop for all 8 bits.
- 1DEF DEC C Decrement map length.
- 1DF0 JR NZ,1DE5,LP-P-MAP Loop until the whole map has been
- examined.
- 1DF2 LD A,(CHREC) Fetch number of records that composes
- the file.
- 1DF5 CP E Compare with number of records found.
- 1DF6 JR NZ,1D9C,ERASE-LP Continue until all records have been
- found (or five passes of the tape
- have been made).
- A 'free' sector descriptor is written in all records of the file to be erased.
- 1DF8 ERASE-MK CALL 1E3E,IN-CHK Set 'free record' attributes.
- 1DFB ERASE-MK2 CALL 12C4,GET-M-HD2 Fetch a header.
- 1DFE CALL 1306,TEST-PMAP Jump if this is not the header of a
- 1E01 JR Z,1E26,T-OTHER record to be erased.
- 1E03 PUSH HL Save map bit address and position.
- 1E04 PUSH BC
- 1E05 LD A,+E6 Start writing.
- 1E07 OUT (+EF),A
- 1E09 LD BC,0168 Wait to insert part of the first gap.
- 1E0C CALL 18FA,DELAY-BC
- 1E0F PUSH IX Make HL point to the data block
- 1E11 POP HL preamble.
- 1E12 LD DE,+0037
- 1E15 ADD HL,DE
- 1E16 CALL 1878,OUT-M-BUF Write the 'free record' descriptor.
- 1E19 LD A,+EE Stop writing.
- 1E1B OUT (+EF),A
- 1E1D CALL 12FE,RES-B-MAP Reset map bit.
- 1E20 POP BC Restore pseudo-map bit position and
- 1E21 POP HL address.
- 1E22 LD A,B Reset the appropriate bit.
- 1E23 CPL
- 1E24 AND (HL)
- 1E25 LD (HL),A
- If the pseudo-map contains at least one bit set, there are other records to be erased.
- 1E26 T-OTHER PUSH IX Make HL point to the pseudo-map.
- 1E28 POP HL
- 1E29 LD DE,+0052
- 1E2C ADD HL,DE
- 1E2D LD B,+20 Length of pseudo-map.
- 1E2F CHK-W-MAP LD A,(HL) Fetch a byte.
- 1E30 OR A Jump back if the byte is not zero
- 1E31 JR NZ,1DFB,ERASE-MK2 (i.e. there are other records to be
- erased).
- 1E33 INC HL Next location.
- 1E34 DJNZ 1E2F,CHK-W-MAP Loop for the whole map.
- 1E36 XOR A Switch off drive motor.
- 1E37 CALL 17F7,SEL-DRIVE
- 1E3A CALL 10C4,DEL-M-BUF Reclaim channel and map.
- 1E3D RET Finished.
- THE 'SIGNAL "FREE SECTOR"' SUBROUTINE
- This subroutine is called from the FORMAT and ERASE command routines to mark the current record descriptor as 'free \
- sector' identifier.
- 1E3E IN-CHK XOR A Clear RECFLG and RECLEN.
- 1E3F LD (RECFLG),A
- 1E42 LD (RECLEN-lo),A
- 1E45 LD (RECLEN-hi),A
- 1E48 PUSH IX Make HL point to RECFLG.
- 1E4A POP HL
- 1E4B LD DE,+0043
- 1E4E ADD HL,DE
- 1E4F CALL 1341,CMKS-HD-R Restore DESCHK checksum.
- 1E52 RET Finished.
- THE 'OBTAIN A RECORD DESCRIPTOR' SUBROUTINE
- This subroutine is used from the FORMAT and ERASE coamnand routines to fetch from the current Microdrive unit the \
- record descriptor held in the current sector (i.e. RECFLG...DESCHK). The zero flag is returned reset with any error.
- 1E53 G-RDES PUSH IX Make HL point to RECFLG.
- 1E55 POP HL
- 1E56 LD DE,+0043
- 1E59 ADD HL,DE
- 1E5A CALL 18A3,GET-M-HD Fetch record descriptor.
- 1E5D CALL 1341,CHKS-MD-R Calculate new checksum.
- 1E60 RET NZ Return if it is wrong.
- 1E61 BIT 0,(RECFLG) Return with zero flag reset if this
- 1E65 RET is a header.
- THE 'CALLS TO THE COMMAND ROUTINES'
- The six following calls are entered from the appropriate command syntax routine; on return from the command routine, \
- the control returns to END1.
- 1E66 ERASE-RUN CALL 1D6E,ERASE
- 1E69 JR 1E84,ENDC
- 1E6B MOVE-RUN CALL 13F1,MOVE
- 1E6E JR 1E84,ENDC
- 1E70 CAT-RUN CALL 1C58,CAT
- 1E73 JR 1E84,ENDC
- 1E75 FOR-RUN CALL 1B6E,FORMAT
- 1E78 JR 1E84,ENDC
- 1E7A OP-RUN CALL 1AF0,OP-M-STRM
- 1E7D JR 1E84,ENDC
- 1E7F SAVE-RUN CALL 14DA,SA-DRIVE
- 1E82 JR 1E84,ENDC
- 1E84 ENDC JP 05Cl,END1
- The 'not used' routines
- The following are four subroutines that are never called from the shadow ROM code; these routines are however \
- described below as they may be useful to the programmer.
- THE 'DISP-HEX' SUBROUTINE
- The contents of the A register are displayed on the screen in hexadecimal. All registers are preserved, excluding A.
- 1E87 DISP-HEX PUSH AF Save A register.
- 1E88 RRA Shift left nibble to right.
- 1E89 RRA
- 1E8A RRA
- 1E8B RRA
- 1E8C CALL 1E90,DISP-NIB Print the first digit.
- 1E8F POP AF Restore value.
- 1E90 DISP-NIB AND +0F Clear left nibble.
- 1E92 CP +0A Jump if the value is lower than 9.
- 1E94 JR C,1E98,CONV-1
- 1E96 ADD A,+07 Otherwise add +07 to reach the code of
- A..F.
- 1E98 CONV-1 ADD A,+30 Add offset for ASCII code.
- 1E9A CALL 1EA9,DISP-CH Print the digit.
- 1E9D RET Finished.
- THE 'DISP-HEX2' SUBROUTINE
- This performs the same task as the preceding one, but the hex number is followed by a space. All registers are \
- preserved.
- 1E9E DISP-HEX2 PUSH AF Save A register.
- 1E9F CALL 1E87,DISP-HEX Print the hex number.
- 1EA2 LD A,+20 Follow with a space.
- 1EA4 CALL 1EA9,DISP-CH
- 1EA7 POP AF Restore A.
- 1EA8 RET Finished.
- THE 'DISP-CH' SUBROUTINE
- This subroutine prints on the screen the character held in the accumulator. All registers are preserved.
- 1EA9 DISP-CH PUSH HL Save registers.
- 1EAA PUSH DE
- 1EAB PUSH BC
- 1EAC PUSH AF
- 1EAD EXX Save alternate registers.
- 1EAE PUSH HL
- 1EAF PUSH DE
- 1EB0 PUSH BC
- 1EB1 PUSH AF
- 1EB2 LD HL,(CURCHL) Save also current channel address.
- 1EB5 PUSH HL
- 1EB6 PUSH AF Save character to be printed.
- 1EB7 LD A,+02 Select stream 2 (screen).
- 1EB9 RST 10,CALBAS Call CHAN-OPEN to select the stream.
- 1EBA DEFW +1601
- 1EBC POP AF Restore character.
- 1EBD RST 10,CALBAS Call PRINT-A restart to print the
- 1EBE DEFW +0010 character.
- 1EC0 POP HL Restore old channel address.
- 1EC1 LD (CURCHL),A
- 1EC4 POP AF Restore alternate registers.
- 1EC5 POP BC
- 1EC6 POP DE
- 1EC7 POP HL
- 1EC8 EXX Restore normal registers.
- 1EC9 POP AF
- 1ECA POP BC
- 1ECB POP DE
- 1ECC POP HL
- 1ECD RET
- THE 'HEX-LINE' SUBROUTINE
- This subroutine displays the values of the ten bytes from the location passed in the HL register. Again all registers \
- are preserved.
- 1ECE HEX-LINE PUSH HL Save registers.
- 1ECF PUSH BC
- 1ED0 PUSH AF
- 1ED1 LD B,+0A Counts 10 bytes.
- 1ED3 HEX-LINE2 LD A,(HL) Fetch a byte.
- 1ED4 CALL 1E9E,DISP-HEX2 Display it in hex and follow with a
- space.
- 1ED7 INC HL Point to next byte.
- 1ED8 DJNZ 1ED3,HEX-LINE2 Loop for all l0 bytes.
- 1EDA LD A,+0D Finally print a carriage return.
- 1EDC CALL 1EA9,DISP-CH
- 1EDF POP AF Restore registers.
- 1EE0 POP BC
- 1EEl POP HL
- 1EE2 RET Finished.
- 1EE3...1FFF Unused locations (all set to +FF).
- APPENDIX 1
- Labels sorted by address value
- (For edition 1 Shadow ROM)
- 0000 MAIN-ROM 0008 ST-SHADOW 0010 CALBAS 0018 CHKSYNTAX
- 0020 SH-ERR 0028 ROMERR 0030 NEWVARS 0038 INT-SERV
- 003A TEST-SP 0040 RMERR-2 0066 NMINT-SRV 0068 ST-ERROR
- 0077 CHECK-SP 0081 CALBAS-2 009A START-2 00A5 START-3
- 00BC START-4 00E7 NREPORT-0 00E9 TEST-CODE 00FB COPYCHADD
- 011B RUNTIME 0130 PROG-LINE 0133 SC-L-LOOP 0139 NREPORT-1
- 013B TEST-LOW 0144 LINE-LEN 014E SKIP-NUN 0152 EACH-ST
- 015D CHKEND 0165 CHKEVEN 0169 CHKEND-L 016F S-STAT
- 0182 RCLM-NUM 01A3 NXT-1 01A5 NEXTNUM 01AA CL-WORK
- 01EC ERR-V 01F0 ERR-6 01F7 CRT-VARS 0224 DEFAULT
- 0235 VAR-EXIST 024D RES-VARS 0252 EACH-VAR 0258 REP-MSG
- 026E FETCH-ERR 029F PR-REP-LP 02AC END-PR-MS 0486 CAT-SYN
- 0494 MISSING-D 04A6 CAT-SCRN 04B2 OREPORT-1 04B4 FRTM-SYN
- 04BF NO-FOR-M 04CD FOR-B-T 04D3 NOT-FOR-B 04E7 FOR-M
- 04ED OPEN-SYN 0500 NOT-OP-M 051C OPEN-RS 051F NOT-OP-B
- 0529 OP-M-C 052F NREPORT-C 0531 ERASE-SYN 053D MOVE-SYN
- 0559 CLS#-SYN 057F CLR#-SYN 0584 NONSENSE 058E ALL-STRMS
- 059F EX-D-STR 05A7 ALL-BYTES 05B1 SEPARATOR 05B7 ST-END
- 05BF TEST-RET 05C1 END1 05DD RETAD-RUN 05E0 RETAD-SYN
- 05E2 BREAK-PGM 05E7 EXPT-STR 05F2 EXPT-SPEC 05F5 EXP-SPEC2
- 060C TEST-NEXT 061E EXPT-NUM 062D NREPORT-3 062F EXPT-NAME
- 064C NREPORT-4 064E EXPT-STRM 0663 NREPORT-2 0665 CHECK-H
- 066D CHECK-M-2 0681 NREPORT-5 0683 NREPORT-9 0685 TEST-MNAM
- 068F TEST-STAT 06A1 NREPORT-8 06A3 EXPT-EXPR 06B0 TEST-BAUD
- 06B9 EXPT-EXP1 06CC ENDHERE 0700 UNPAGE 0701 EXPT-PRMS
- 0716 NO-NAME 0722 NOT-NET 073C OREP-1-2 073E LINE
- 0750 END-EXPT 0753 PROC 0771 SCREEN$ 0789 CODE
- 079A DEFLT-0 079F PAR-1 07A7 TEST-SAVE 07B2 PAR-2
- 07B8 END-CODE 07D2 DATA 07DA NO-M-ARR 07F2 EXISTING
- 07F4 NONS-BSC 07F6 G-TYPE 0803 VR-DATA 080E LD-DATA
- 0819 NUM-ARR 081C END-DATA 082F SAVE-SYN 0849 SAVE-M
- 084F SA-HEADER 0854 HD-LOOP 086E SA-BLOCK 0872 SA-BLK-LP
- 087D S-BLK-END 0880 SA-BYTE 088E SA-NET 0891 SA-B-END
- 0894 LOAD-SYN 089E VERIF-SYN 08A8 MRG-SYN 08AF LD-VF-MR
- 08CD TS-L-NET 08D3 TS-L-RS 08D8 LD-HEADER 08E0 LD-HD-NET
- 08E7 LD-HD-RS 08EC LD-HDR-2 08F2 TEST-TYPE 0902 NREPORT-H
- 0904 TST-MERGE 0911 T-M-CODE 0919 LD-BLOCK 0930 NREPORT-L
- 0932 LD-BLK-2 0941 LD-BLK-3 0952 LD-BLK-4 0959 LD-BLK-5
- 0962 LD-NO-PGM 0967 MERGE-BLK 0973 NO-AUTOST 0988 TST-MR-M
- 0994 TST-MR-N 09A0 MERGE-END 09A3 LD-PR-AR 09B5 LD-PROG
- 09BE TST-SPACE 09C7 TST-TYPE 09DE T-LD-NET 09E8 RCLM-OLD
- 09F3 CRT-NEW 0A0F END-LD-PR 0A15 SET-PROG 0A4E NO-AUTO
- 0A5C LV-ANY 0A6A LV-BN 0A72 LV-N 0A79 LV-B
- 0A7E LV-BN-E 0A8A VR-BN 0A8F LVBN-END 0A95 LOAD-RUN
- 0AC9 SET-BAUD 0AD0 NXT-ENTRY 0AE4 END-SET 0813 OP-RS-CH
- 0B47 OP-RSCHAN 0B4A OP-STREAM 0B6F T-INPUT 0B75 B-INPUT
- 0B7B TCHAN-IN 0B81 BCHAN-IN 0B8E REC-BYTE 0B9A REC-PROC
- 0BB1 READ-RS 0BC5 TST-AGAIN 0BD1 START-BIT 0BD8 SERIAL-IN
- 0BDA BD-DELAY 0BF0 WAIT-1 0BF1 WAIT-2 0BF9 T-FURTHER
- 0C1D SER-IN-2 0C1F BD-DELAY2 0C36 END-RS-IN 0C3C TCHAN-OUT
- 0C46 NOT-TOKEN 0C4C NOT-GRAPH 0C57 NOT-CR 0C5A BCHAN-OUT
- 0C6F BD-DEL-1 0C74 TEST-DTR 0C88 SER-OUT-L 0C8E BD-DEL-2
- 0CA4 BD-DEL-3 0CA9 BORD-REST 0CB4 BRK-INOUT 0CBD CALL-INP
- 0CDB IN-AGAIN 0CE1 INPUT-END 0CE5 OREPORT-8 0CEA NO-READ
- 0CED ACC-CODE 0CF7 END-INPUT 0CFB INKEY$ 0D01 INK$-END
- 0D0C N-INPUT 0D12 NCHAN-IN 0D1E TEST-BUFF 0D38 TST-N-EOF
- 0D3F GET-N-BUF 0D45 TRY-AGAIN 0D5F TIME-OUT 0D6C NCHAN-OUT
- 0D7A TEST-OUT 0D88 ST-BF-LEN 0D93 OUT-BLK-N 0DAB S-PACK-1
- 0DB2 SEND-PACK 0DC5 CHKS1 0DD4 CHKS2 0DDA SENDSCOUT
- 0DF6 SP-DL-1 0DFD INC-BLKN 0E05 SP-N-END 0E0F BR-DELAY
- 0E12 DL-LOOP 0E18 GET-NBLK 0E27 CHKS3 0E40 BRCAST
- 0E45 TEST-BLKN 0E62 GETNB-END 0E65 GET-NBUFF 0E87 CHKS4
- 0E93 STORE-LEN 0EA1 GETNBF-END 0EA3 OPEN-N-ST 0EA9 OP-TEMP-N
- 0EB5 OP-PERN-N 0EF5 SEND-NEOF 0F03 NET-STATE 0F0E CHK-REST
- 0F15 MAKESURE 0F1E WT-SCOUT 0F21 CLAIMED 0F35 WT-SYNC
- 0F4D E-READ-N 0F56 SCOUT-END 0F58 LP-SCOUT 0F5D DELAY-SC
- 0F61 SEND-SC 0F72 ALL-BITS 0F7D S-SC-DEL 0F8F END-S-DEL
- 0F92 INPAK 0F94 N-ACTIVE 0F9D INPAK-2 0F9E INPAK-L
- 0FAE UNTIL-MK 0FBE SEND-RESP 0FC5 OUTPAK 0FCA DEL-D-1
- 0FCC OUTPAK-L 0FD2 UNT-MARK 0FE8 SET-T-MCH 0FF6 CHK-LOOP
- 102A NEXT-CHAN 1034 CHAN-SPC 1061 T-CH-NAME 106F TEST-MAP
- 108A ST-MAP-AD 1094 FILL-MAP 10C4 DEL-M-BUF 10F5 TEST-MCHL
- 110A NXTCHAN 1114 RCLM-MAP 1122 M-INPUT 112C MCHAN-IN
- 1132 RWF-ERR 1134 TEST-M-BF 1158 CHK-M-EOF 1162 NEW-BUFF
- 1177 GET-RECD 117D GET-R-2 1184 GET-R-LP 119E NXT-SCT
- 11A3 RS-SH2 11A5 G-HD-RC 11D6 G-REC-ERR 11D8 MCHAN-OUT
- 11E6 NOREAD 11FF WR-RECD 120D WRITE-PRC 121B NOFULL
- 121F CP-NAME 1264 CHK-FULL 126C NXT-B-MAP 1275 SEND-BLK
- 127D FAILED 128F NO-PRT 12A6 CLOSE-M 12A9 CLOSE-M2
- 12B6 NOEMP 12BE ERR-RS 12C4 GET-M-HD2 12DA CHK-MAP-2
- 12DF CHECK-MAP 12E2 ENTRY 12E8 ENTRY-2 12F8 ROTATE
- 12FE RES-B-MAP 1306 TEST-PMAP 1312 DEC-SECT 131E CHK-NAME
- 1322 ALL-CHARS 1333 ALLCHR-2 133E CHKNAM-END 1341 CHKS-HD-R
- 1346 CHKS-BUFF 1349 CHKS-ALL 134C NXT-BYTE 1354 STCHK
- 135F REST-STRM 1365 NXT-STRM 1377 NOTRIGHT 137E STO-DISP
- 1384 UPD-POINT 1391 REST-MAP 139D LCHAN 13C1 LPEND
- 13F1 MOVE 1414 M-AGAIN 141A I-AGAIN 1423 MOVE-OUT
- 142E MOVE-EOF 1455 OP-STRM 1466 OP-CHAN 147F CHECK-N
- 148B CHECK-R 1495 USE-R 14A4 CL-CHAN 14B8 CL-CHK-N
- 14C7 EX-DSTR2 14CF ALL-BYT-2 14DA SA-DRIVE 14E8 START-SA
- 14FC NEW-NAME 1530 SA-DRI-2 1538 SA-DRI-3 1552 SA-DRI-WR
- 155E SA-DRI-4 1579 END-SA-DR 1580 F-M-HEAD 1591 F-HD-2
- 1599 F-HD-3 15A9 LV-MCH 15DF USE-REC 15F9 LOOK-MAP
- 1613 SA-MAP 1620 SA-MAP-LP 162D RE-MAP 163D RE-MAP-LP
- 1648 LD-VE-M 1658 VE-M-E 1664 VE-FAIL 1666 F-REC1
- 166C F-REC2 1673 UNTILFIVE 168A F-ERROR 1691 REST-N-AD
- 16AC TST-PLACE 1708 CLOSE-CH 1718 CLOSE 1751 CL-RS-CH
- 175E CL-N-CH 176D CL-M-CN 177F RCLM-CH 1789 UPD-STRM
- 17A4 UPD-NXT-S 17B9 RCL-T-CH 17C2 EX-CHANS 17D2 CHK-TEMPM
- 17DE CHK-TEMPN 17ED PT-N-CHAN 17F7 SEL-DRIVE 1802 TURN-ON
- 1809 TON-DELAY 1811 REPTEST 1813 CHK-PRES 1820 NOPRES
- 182A SW-MOTOR 1835 ALL-MOTRS 184B OFF-MOTOR 185C NXT-MOTOR
- 1867 DEL-S-1 1872 OUT-M-HD 1878 OUT-M-BUF 187C OUT-M-BLK
- 1884 NOT-PROT 1895 OUT-M-BYT 18A3 GET-M-HD 18A9 GET-M-BUF
- 18AD GET-M-BLK 18B1 CHK-AGAIN 18B3 CHKLOOP 18BE CHK-AG-2
- 18C0 CHK-LP-2 18D2 DR-READY 18DE IN-M-BLK 18E9 TEST-ERR
- 1BFA DELAY-BC 18FB DELAY-BC1 1902 UNKN-1 191C UNKN-2
- 1929 UNKN-3 1952 UNKN-4 1959 UNKN-5 1961 UNKN-6
- 1968 UNKN-7 196C UNKN-8 1976 UNKN-9 1981 HOOK-CODE
- 1987 CLR-ERR 19A4 HOOK-32 19A8 HOOK-31 19D9 CONS-IN
- 19DE WTKEY 19EC CONS-OUT 19EF OUT-CODE 19FC PRT-OUT
- 1A01 KBD-TEST 1A09 READ-SEQ 1A14 INCREC 1A17 RD-RANDOM
- 1A24 CLOSE-NET 1A31 GET-PACK 1A46 GP-ERROR 1A4B RD-SECTOR
- 1A51 NO-GOOD 1A63 USE-C-RC 1A81 DEL-B-CT 1A86 RD-NEXT
- 1A91 WR-SECTOR 1AAD WR-S-1 1ABF WR-S-2 1AC5 RS-SH
- 1AC7 WR-S-3 1AE0 CLR-BUFF 1AF0 OP-M-STRM 1B0D MAKE-PERM
- 1B23 STORE-DSP 1B29 OP-TEMP-M 1B3A OP-F-1 1B57 OP-F-2
- 1B5C OP-F-3 1B5F OP-F-4 1B6C OP-F-5 1B6E FORMAT
- 1B86 FORMAT-1 1BBD FILL-B-F 1BC1 FILL-B-F2 1BD6 WR-F-TEST
- 1C0A TEST-SCT 1C1B CHK-SCT 1C3E CHK-NSECT 1C46 MARK-FREE
- 1C53 MK-BLK 1C58 CAT 1C6E CAT-LP 1C85 IN-NAME
- 1C9A SE-NAME 1CA4 T-NA-1 1CAF T-NA-2 1CBB ORD-NAM
- 1CD4 INS-NAME 1CD8 MOVE-NA 1CEE F-N-SCT 1CF4 BF-FILLED
- 1D17 OT-NAMS 1D1C NONAMES 1D38 FREESECT 1D42 FR-SC-LP
- 1D46 FR-S-LPB 1D4A FR-S-RES 1D50 PRNAME 1D53 PRNM-LP
- 1D66 PRCHAR 1D6E ERASE 1D7F ERASE-1 1D9C ERASE-LP
- 1DB8 ERASE-2 1DDA TST-NUM 1DE5 LP-P-MAP 1DE9 LP-B-MAP
- 1DED NOINC-C 1DF8 ERASE-MK 1DFB ERASE-MK2 1E26 T-OTHER
- 1E2F CHK-W-MAP 1E3E IN-CHK 1E53 G-RDES 1E66 ERASE-RUN
- 1E6B MOVE-RUN 1E70 CAT-RUN 1E75 FOR-RUN 1E7A OP-RUN
- 1E7F SAVE-RUN 1E84 ENDC 1E87 DISP-HEX 1E90 DISP-NIB
- 1E98 CONV-1 1E9E DISP-HEX2 1EA9 DISP-CH 1ECE HEX-LINE
- 1ED3 HEX-LINE2
- APPENDIX 2
- Labels sorted alphabetically
- (For edition 1 Shadow ROM)
- ACC-CODE 0CED ALL-BITS 0F72 ALL-BYT-2 14CF ALL-BYTES 05A7
- ALL-CHARS 1322 ALL-MOTRS 1835 ALL-STRMS 058E ALLCHR-2 1333
- B-INPUT 0B75 BCHAN-IN 0B81 BCHAN-OUT 0C5A BD-DEL-1 0C6F
- BD-DEL-2 0C8E BD-DEL-3 0CA4 BD-DELAY 0BDA BD-DELAY2 0C1F
- BF-FILLED 1CF4 BORD-REST 0CA9 BR-DELAY 0E0F BRCAST 0E40
- BREAK-PGM 05E2 BRK-INOUT 0CB4 CALBAS 0010 CALBAS-2 0081
- CALL-INP 0CBD CAT 1C58 CAT-LP 1C6E CAT-RUN 1E70
- CAT-SCRN 04A6 CAT-SYN 0486 CHAN-SPC 1034 CHECK-H 0665
- CHECK-M-2 066D CHECK-MAP 12DF CHECK-N 147F CHECK-R 148B
- CHECK-SP 0077 CHK-AG-2 18BE CHK-AGAIN 18B1 CHK-FULL 1264
- CHK-LOOP 0FF6 CHK-LP-2 18C0 CHK-M-EOF 1158 CHK-MAP-2 12DA
- CHK-NAME 131E CHK-NSECT 1C3E CHK-PRES 1813 CHK-REST 0F0E
- CHK-SCT 1C1B CHK-TEMPM 17D2 CHK-TEMPN 17DE CHK-W-MAP 1E2F
- CHKEND 015D CHKEND-L 0169 CHKEVEN 0165 CHKLOOP 18B3
- CHKNAM-END 133E CHKS-ALL 1349 CHKS-BUFF 1346 CHKS-HD-R 1341
- CHKS1 0DC5 CHKS2 0DD4 CHKS3 0E27 CHKS4 0E87
- CHKSYNTAX 0018 CL-CHAN 14A4 CL-CHK-N 14B8 CL-M-CN 176D
- CL-N-CH 175E CL-RS-CH 1751 CL-WORK 01AA CLAIMED 0F21
- CLOSE 1718 CLOSE-CH 1708 CLOSE-M 12A6 CLOSE-M2 12A9
- CLOSE-NET 1A24 CLR#-SYN 057F CLR-BUFF 1AE0 CLR-ERR 1987
- CLS#-SYN 0559 CODE 0789 CONS-IN 19D9 CONS-OUT 19EC
- CONV-1 1E98 COPYCHADD 00FB CP-NAME 121F CRT-NEW 09F3
- CRT-VARS 01F7 DATA 07D2 DEC-SECT 1312 DEFAULT 0224
- DEFLT-0 079A DEL-B-CT 1A81 DEL-D-1 0FCA DEL-M-BUF 10C4
- DEL-S-1 1867 DELAY-BC 1BFA DELAY-BC1 18FB DELAY-SC 0F5D
- DISP-CH 1EA9 DISP-HEX 1E87 DISP-HEX2 1E9E DISP-NIB 1E90
- DL-LOOP 0E12 DR-READY 18D2 E-READ-N 0F4D EACH-ST 0152
- EACH-VAR 0252 END-CODE 07B8 END-DATA 081C END-EXPT 0750
- END-INPUT 0CF7 END-LD-PR 0A0F END-PR-MS 02AC END-RS-IN 0C36
- END-S-DEL 0F8F END-SA-DR 1579 END-SET 0AE4 END1 05C1
- ENDC 1E84 ENDHERE 06CC ENTRY 12E2 ENTRY-2 12E8
- ERASE 1D6E ERASE-1 1D7F ERASE-2 1DB8 ERASE-LP 1D9C
- ERASE-MK 1DF8 ERASE-MK2 1DFB ERASE-RUN 1E66 ERASE-SYN 0531
- ERR-6 01F0 ERR-RS 12BE ERR-V 01EC EX-CHANS 17C2
- EX-D-STR 059F EX-DSTR2 14C7 EXISTING 07F2 EXP-SPEC2 05F5
- EXPT-EXP1 06B9 EXPT-EXPR 06A3 EXPT-NAME 062F EXPT-NUM 061E
- EXPT-PRMS 0701 EXPT-SPEC 05F2 EXPT-STR 05E7 EXPT-STRM 064E
- F-ERROR 168A F-HD-2 1591 F-HD-3 1599 F-M-HEAD 1580
- F-N-SCT 1CEE F-REC1 1666 F-REC2 166C FAILED 127D
- FETCH-ERR 026E FILL-B-F 1BBD FILL-B-F2 1BC1 FILL-MAP 1094
- FOR-B-T 04CD FOR-M 04E7 FOR-RUN 1E75 FORMAT 1B6E
- FORMAT-1 1B86 FR-S-LPB 1D46 FR-S-RES 1D4A FR-SC-LP 1D42
- FREESECT 1D38 FRTM-SYN 04B4 G-HD-RC 11A5 G-RDES 1E53
- G-REC-ERR 11D6 G-TYPE 07F6 GET-M-BLK 18AD GET-M-BUF 18A9
- GET-M-HD 18A3 GET-M-HD2 12C4 GET-N-BUF 0D3F GET-NBLK 0E18
- GET-NBUFF 0E65 GET-PACK 1A31 GET-R-2 117D GET-R-LP 1184
- GET-RECD 1177 GETNB-END 0E62 GETNBF-END 0EA1 GP-ERROR 1A46
- HD-LOOP 0854 HEX-LINE 1ECE HEX-LINE2 1ED3 HOOK-31 19A8
- HOOK-32 19A4 HOOK-CODE 1981 I-AGAIN 141A IN-AGAIN 0CDB
- IN-CHK 1E3E IN-M-BLK 18DE IN-NAME 1C85 INC-BLKN 0DFD
- INCREC 1A14 INK$-END 0D01 INKEY$ 0CFB INPAK 0F92
- INPAK-2 0F9D INPAK-L 0F9E INPUT-END 0CE1 INS-NAME 1CD4
- INT-SERV 0038 KBD-TEST 1A01 LCHAN 139D LD-BLK-2 0932
- LD-BLK-3 0941 LD-BLK-4 0952 LD-BLK-5 0959 LD-BLOCK 0919
- LD-DATA 080E LD-HD-NET 08E0 LD-HD-RS 08E7 LD-HDR-2 08EC
- LD-HEADER 08D8 LD-NO-PGM 0962 LD-PR-AR 09A3 LD-PROG 09B5
- LD-VE-M 1648 LD-VF-MR 08AF LINE 073E LINE-LEN 0144
- LOAD-RUN 0A95 LOAD-SYN 0894 LOOK-MAP 15F9 LP-B-MAP 1DE9
- LP-P-MAP 1DE5 LP-SCOUT 0F58 LPEND 13C1 LV-ANY 0A5C
- LV-B 0A79 LV-BN 0A6A LV-BN-E 0A7E LV-MCH 15A9
- LV-N 0A72 LVBN-END 0A8F M-AGAIN 1414 M-INPUT 1122
- MAIN-ROM 0000 MAKE-PERM 1B0D MAKESURE 0F15 MARK-FREE 1C46
- MCHAN-IN 112C MCHAN-OUT 11D8 MERGE-BLK 0967 MERGE-END 09A0
- MISSING-D 0494 MK-BLK 1C53 MOVE 13F1 MOVE-EOF 142E
- MOVE-NA 1CD8 MOVE-OUT 1423 MOVE-RUN 1E6B MOVE-SYN 053D
- MRG-SYN 08A8 N-ACTIVE 0F94 N-INPUT 0D0C NCHAN-IN 0D12
- NCHAN-OUT 0D6C NET-STATE 0F03 NEW-BUFF 1162 NEW-NAME 14FC
- NEWVARS 0030 NEXT-CHAN 102A NEXTNUM 01A5 NMINT-SRV 0066
- NO-AUTO 0A4E NO-AUTOST 0973 NO-FOR-M 04BF NO-GOOD 1A51
- NO-M-ARR 07DA NO-NAME 0716 NO-PRT 128F NO-READ 0CEA
- NOEMP 12B6 NOFULL 121B NOINC-C 1DED NONAMES 1D1C
- NONS-BSC 07F4 NONSENSE 0584 NOPRES 1820 NOREAD 11E6
- NOT-CR 0C57 NOT-FOR-B 04D3 NOT-GRAPH 0C4C NOT-NET 0722
- NOT-OP-B 051F NOT-OP-M 0500 NOT-PROT 1884 NOT-TOKEN 0C46
- NOTRIGHT 1377 NREPORT-0 00E7 NREPORT-1 0139 NREPORT-2 0663
- NREPORT-3 062D NREPORT-4 064C NREPORT-5 0681 NREPORT-8 06A1
- NREPORT-9 0683 NREPORT-C 052F NREPORT-H 0902 NREPORT-L 0930
- NUM-ARR 0819 NXT-1 01A3 NXT-B-MAP 126C NXT-BYTE 134C
- NXT-ENTRY 0AD0 NXT-MOTOR 185C NXT-SCT 119E NXT-STRM 1365
- NXTCHAN 110A OFF-MOTOR 184B OP-CHAM 1466 OP-F-1 1B3A
- OP-F-2 1B57 OP-F-3 1B5C OP-F-4 1B5F OP-F-5 1B6C
- OP-M-C 0529 OP-M-STRM 1AF0 OP-PERN-N 0EB5 OP-RS-CH 0813
- OP-RSCHAN 0B47 OP-RUN 1E7A OP-STREAM 0B4A OP-STRM 1455
- OP-TEMP-M 1B29 OP-TEMP-N 0EA9 OPEN-N-ST 0EA3 OPEN-RS 051C
- OPEN-SYN 04ED ORD-NAM 1CBB OREP-1-2 073C OREPORT-1 04B2
- OREPORT-8 0CE5 OT-NAMS 1D17 OUT-BLK-N 0D93 OUT-CODE 19EF
- OUT-M-BLK 187C OUT-M-BUF 1878 OUT-M-BYT 1895 OUT-M-HD 1872
- OUTPAK 0FC5 OUTPAK-L 0FCC PAR-1 079F PAR-2 07B2
- PR-REP-LP 029F PRCHAR 1D66 PRNAME 1D50 PRNM-LP 1D53
- PROC 0753 PROG-LINE 0130 PRT-OUT 19FC PT-N-CHAN 17ED
- RCL-T-CH 17B9 RCLM-CH 177F RCLM-MAP 1114 RCLM-NUM 0182
- RCLM-OLD 09E8 RD-NEXT 1A86 RD-RANDOM 1A17 RD-SECTOR 1A4B
- RE-MAP 162D RE-MAP-LP 163D READ-RS 0BB1 READ-SEQ 1A09
- REC-BYTE 0B8E REC-PROC 0B9A REP-MSG 0258 REPTEST 1811
- RES-B-MAP 12FE RES-VARS 024D REST-MAP 1391 REST-N-AD 1691
- REST-STRM 135F RETAD-RUN 05DD RETAD-SYN 05E0 RMERR-2 0040
- ROMERR 0028 ROTATE 12F8 RS-SH 1AC5 RS-SH2 11A3
- RUNTIME 011B RWF-ERR 1132 S-BLK-END 087D S-PACK-1 0DAB
- S-SC-DEL 0F7D S-STAT 016F SA-B-END 0891 SA-BLK-LP 0872
- SA-BLOCK 086E SA-BYTE 0880 SA-DRI-2 1530 SA-DRI-3 1538
- SA-DRI-4 155E SA-DRI-WR 1552 SA-DRIVE 14DA SA-HEADER 084F
- SA-MAP 1613 SA-MAP-LP 1620 SA-NET 088E SAVE-M 0849
- SAVE-RUN 1E7F SAVE-SYN 082F SC-L-LOOP 0133 SCOUT-END 0F56
- SCREEN$ 0771 SE-NAME 1C9A SEL-DRIVE 17F7 SEND-BLK 1275
- SEND-NEOF 0EF5 SEND-PACK 0DB2 SEND-RESP 0FBE SEND-SC 0F61
- SENDSCOUT 0DDA SEPARATOR 05B1 SER-IN-2 0C1D SER-OUT-L 0C88
- SERIAL-IN 0BD8 SET-BAUD 0AC9 SET-PROG 0A15 SET-T-MCH 0FE8
- SH-ERR 0020 SKIP-NUN 014E SP-DL-1 0DF6 SP-N-END 0E05
- ST-BF-LEN 0D88 ST-END 05B7 ST-ERROR 0068 ST-MAP-AD 108A
- ST-SHADOW 0008 START-2 009A START-3 00A5 START-4 00BC
- START-BIT 0BD1 START-SA 14E8 STCHK 1354 STO-DISP 137E
- STORE-DSP 1B23 STORE-LEN 0E93 SW-MOTOR 182A T-CH-NAME 1061
- T-FURTHER 0BF9 T-INPUT 0B6F T-LD-NET 09DE T-M-CODE 0911
- T-NA-1 1CA4 T-NA-2 1CAF T-OTHER 1E26 TCHAN-IN 0B7B
- TCHAN-OUT 0C3C TEST-BAUD 06B0 TEST-BLKN 0E45 TEST-BUFF 0D1E
- TEST-CODE 00E9 TEST-DTR 0C74 TEST-ERR 18E9 TEST-LOW 013B
- TEST-M-BF 1134 TEST-MAP 106F TEST-MCHL 10F5 TEST-MNAM 0685
- TEST-NEXT 060C TEST-OUT 0D7A TEST-PMAP 1306 TEST-RET 05BF
- TEST-SAVE 07A7 TEST-SCT 1C0A TEST-SP 003A TEST-STAT 068F
- TEST-TYPE 08F2 TIME-OUT 0D5F TON-DELAY 1809 TRY-AGAIN 0D45
- TS-L-NET 08CD TS-L-RS 08D3 TST-AGAIN 0BC5 TST-MERGE 0904
- TST-MR-M 0988 TST-MR-N 0994 TST-N-EOF 0D38 TST-NUM 1DDA
- TST-PLACE 16AC TST-SPACE 09BE TST-TYPE 09C7 TURN-ON 1802
- UNKN-1 1902 UNKN-2 191C UNKN-3 1929 UNKN-4 1952
- UNKN-5 1959 UNKN-6 1961 UNKN-7 1968 UNKN-8 196C
- UNKN-9 1976 UNPAGE 0700 UNT-MARK 0FD2 UNTIL-MK 0FAE
- UNTILFIVE 1673 UPD-NXT-S 17A4 UPD-POINT 1384 UPD-STRM 1789
- USE-C-RC 1A63 USE-R 1495 USE-REC 15DF VAR-EXIST 0235
- VE-FAIL 1664 VE-M-E 1658 VERIF-SYN 089E VR-BN 0A8A
- VR-DATA 0803 WAIT-1 0BF0 WAIT-2 0BF1 WR-F-TEST 1BD6
- WR-RECD 11FF WR-S-1 1AAD WR-S-2 1ABF WR-S-3 1AC7
- WR-SECTOR 1A91 WRITE-PRC 120D WT-SCOUT 0F1E WT-SYNC 0F35
- WTKEY 19DE
- APPENDIX 3
- 'Shadow' system variables
- Notes Address Name Contents
- X1 23734 5CB6 FLAGS3 Various flags:
- bit 0 - set during execution of 'new' commands.
- bit 1 - set during execution of CLEAR# command.
- On entry to the shadow ROM, it is set
- at the first 'paging' operation.
- bit 2 - set if the main ROM error handler is to
- be used. (Normally it is always reset).
- bit 3 - set if using the network.
- bit 4 - set during execution of LOAD and MOVE.
- bit 5 - set during execution of SAVE conwsand.
- bit 6 - set during execution of MERGE conmiand.
- bit 7 - set during execution of VERIFY cormnand.
- FLAGS3 may be addressed with (IY+124).
- X2 23735 5CB7 VECTOR Normally points to +01F0 (ERR-6). You may modify this
- address to point to a RAM routine.
- X10 23737 5CB9 SBRT ROM paging subroutine as follows:
- 5CB9 LD HL,nnnnn
- 5CBC CALL nnnnn
- 5CBF LD (H-L),HL
- 5CC2 RET
- H-L EQU +5CBA
- Used to save the value of HL while calling 'main'
- ROM routines.
- 2 23747 5CC3 BAUD Timing constant used during RS232 i/o.
- May be obtained with:
- (3500000/(26*baud rate))-2
- 1 23749 5CC5 NTSTAT Network own station number 1..64.
- 1 23759 5CC6 IOBORD Border colour used during I/O; normally 0 (black)
- N2 23751 5CC7 SER-FL Low byte may be 00 or 01; high byte holds a received
- byte if low byte is 01.
- N2 23753 5CC9 SECTOR Counter of sectors examined during Microdrive
- operations.
- N2 23755 5CCB CHADD- Temporary store for CH-ADD.
- 1 23757 5CCD NTRESP Store for network response code +01.
- 1 23758 5CCE NTDEST Start of network buffer; destination station number
- for the current packet (0..64).
- 1 23759 5CCF NTSRCE Station number of 'sending' Spectrum for the current
- packet.
- X2 23768 5CD0 NTNUMB Current packet block number (0..65535).
- N1 23762 5CD2 NTTYPE Packet type (00 for normal packets, 01 for EOF).
- X1 23763 5CD3 NTLEN Length of the data block being received, 1..255.
- N1 23764 5CD4 NTDCS Current data block checksum.
- N1 23765 5CD5 NTCHS Current header block checksum.
- N2 23766 5CD6 D-STR1 Start of first 8-byte file specifier; drive number
- 1..8, destination station number 0..64
- or baud rate 75..19200.
- N1 23768 5CD8 S-STR1 Stream number 0..15.
- N1 23769 5CD9 L-STR1 Device specifier "m", "n", "t" or "b".
- N2 23770 5CDA N-STR1 Filename length
- N2 23772 5CDC Filename start address.
- N2 23774 5CDE D-STR2 Start of 2nd 8-byte file specifier, used by MOVE
- and LOAD commands.
- N1 23776 5CE0 S-STR2 See S-STR1.
- N1 23777 5CE1 L-STR2 See L-STR1.
- N2 23778 5CE2 N-STR2 See N-STR1.
- N2 23788 5CE4
- N1 23782 5CE6 HD-00 Start of workspace used by LOAD, SAVE, VERIFY and
- MERGE commands. File type, may be:
- 00 - program 01 - numeric array
- 02 - string array 03 - bytes
- N2 23783 5CE7 HD-0B Data blocklength.
- N2 23785 5CE9 HD-0D Data block start address.
- N2 23787 5CEB HD-0F Program length (without variables), or array name.
- N2 23789 5CED HD-11 Autostart line number (+FFFF if no autostart), or
- address of the routine called by using 'hook code'
- +32.
- 1 23791 5CEF COPIES Number of copies made by SAVE. Reset to +01 after
- the SAVE.
- APPENDIX 4
- Channels
- 1. MICRODRIVE CHANNEL
- This area is used to communicate with the Microdrive device; it is created in the CHANS area. The start address is \
- pointed by the IX index register in the shadow ROM program.
- 0 +0008 Main ROM 'output' routine.
- 2 +0008 Main ROM 'input' routine.
- 4 'M' Channel specifier ('M'+80H denotes a 'temporary' channel,
- used by SAVE, MOVE, etc.).
- 5 +11D8 Shadow ROM 'output' routine.
- 7 +1122 Shadow ROM 'input' routine.
- 9 +0253 Channel length.
- 11 CHBYTE Position of the next byte to be received or stored in the
- buffer (0..512).
- 13 CHREC Record number 0..255. Also used as temporary store of sector
- number.
- 14 CHNAME 10-byte filename with trailing spaces.
- 24 CHFLAG Bit 0 set indicates a 'write' channel.
- Bit 0 reset indicates a 'read' channel.
- 25 CHDRIV Drive number 1..8.
- 26 CHMAP Address of microdrive map.
- 28 - 12 bytes of header preamble (ten zeros and two +FF). Used to
- mark the start of the header block.
- 40 HDFLAG Bit 0 set indicates that the received block is a header.
- 41 HDNUMB Sector number from which the header comes.
- 42 - Unused
- 44 HDNAME 10-byte cartridge name with trailing spaces.
- 54 HDCHK Checksum from HDFLAG to HDCHK-1.
- 55 - 12 bytes of data preamble, as for the header; used to mark the
- start of the record descriptor.
- 67 RECFLG Bit 0 reset indicates that the received block is a record
- descriptor.
- Bit 1 is set if the record is the EOF one.
- Bit 2 is reset if the record is part of a PRINT-type file.
- 68 RECNUM Record number 0..255.
- 69 RECLEN Number of bytes in the record (0..512).
- 71 RECNAM 10-byte record name with trailing spaces.
- 81 DESCHK Checksum from RECFLG to DESCHK-l.
- 82 CHDATA Start of 512-byte buffer.
- 594 DCHK Buffer checksum.
- Bytes 0..27 are used as 'channel descriptor' and are never transmitted; bytes 28..54 are the 'header block'; bytes \
- 55..594 are the 'data block'.
- Bytes 55..91 may be collected (or written) as 'record descriptor', without affecting the data buffer starting from \
- CHDATA.
- 2. NETWORK CHANNEL
- As with the Microdrive channel, this area is addressed by using the IX index
- register it is used to communicate through the Local Area Network.
- 0 +0008 Main ROM 'Output' routine,
- 2 +0008 Main ROM 'Input' routine.
- 4 'N' Channel specifier ('N'+80H denotes a 'temporary' channel).
- 5 +0D6C Shadow ROM 'Output' routine.
- 7 +0D9C Shadow ROM 'Input' routine.
- 9 +0114 Length of the channel.
- 11 NCIRIS Destination station number 0..64.
- 12 NCSELF Own station number 1..64.
- 13 NCNUMB Current block bumber 0..65535.
- 15 NCTYPE Packet type: 00 normal packet, 01 'end of file' packet.
- 16 NCOBL Number of bytes held in the buffer during 'output' (holds 0 if
- the channel is used for reading).
- 17 NCDCS Checksum of the 255-byte buffer.
- 18 NCHCS Checksum of block NCIRIS...NCDCS.
- 19 NCCUR Position of the currently received byte (in the buffer).
- 20 NCIBL Number of bytes in the buffer during 'output' (holds zero if
- the channel is used for writing).
- 21 NCB 255-byte data buffer.
- While 'sending', the bytes 11.18 form the 'header block' (to be stored into the system variables NTDEST...NTCHS of the \
- receiving Spectrum). Bytes 21..275 form the 'data block'.
- 3. RS232 "T" CHANNEL
- This channel is created only when the RS232 link is to be attached to a stream. 'Temporary' RS232 channels are never \
- created, because the RS232 I/O does not require a buffer to store the data to be sent or received (the only \
- 'workspace' is made by the SER-FL system variable).
- 0 +0008 Main ROM 'output' routine.
- 2 +0008 Main ROM 'input' routine.
- 4 'T' Channel specifier.
- 5 +0C3C Shadow ROM 'output' routine.
- 7 +0B6F Shadow ROM 'input' routine.
- 9 +000B Channel length.
- 4. RS232 "B" CIANNEL
- 0 +0008 Main ROM 'output' routine.
- 2 +0008 Main ROM 'input' routine.
- 4 'B' Channel specifier.
- 5 +0C5A Shadow ROM 'output' routine.
- 7 +0B75 Shadow ROM 'input' routine.
- 9 +000B Channel length.
- APPENDIX 5
- Bibliography
- S. Vickers, ZX SPECTRUM BASIC PROGRAMMING (Sinclair Research Ltd.)
- MICRODRIVE AND INTERFACE I MANUAL (Sinclair Research Ltd.)
- I. Logan, F. O'Hara, THE COMPLETE SPECTRUM ROM DISASSEMBLY (Melbourne House)
- I. Logan, SPECTRUM MICRODRIVE BOOK (Melbourne House)
- R. Zaks, PROGRAMMING THE Z80 (Sybex)
- APPENDIX 6
- Index to routines
- (For edition 1 Shadow ROM)
- 0000 Return to main ROM
- 0008 Start
- 0010 Call a main ROM routine
- 0018 Test if syntax is being checked
- 0020 Shadow error
- 0028 Main ROM error restart
- 0030 Create new system variables restart
- 0038 Maskable interrupt
- 003A TEST-SP
- 0040 Main ROM error routine
- 0066 Non-maskable interrupt
- 0068 ST-ERROR
- 0077 CHECK-SP
- 0081 CALBAS-2
- 009A Control routine
- 01F7 Create new system variables routine
- 023A System variables default values
- 024D Reset new system variables
- 0258 Shadow report printing
- 0287 Shadow report messages
- 0486 CAT command syntax routine
- 04B4 FORMAT command syntax routine
- 04ED OPEN command syntax routine
- 0531 ERASE command syntax routine
- 053D MOVE command syntax routine
- 0559 CLS# command routine
- 057F CLEAR# command routine
- 059F Exchange file specifiers
- 05B1 SEPARATOR
- 05B7 End of statement
- 05Cl Return to the main interpreter
- 05E7 Evaluate string expression
- 05F2 Evaluate channel expression
- 061E Evaluate numeric expression
- 062F Evaluate filename
- 064E Evaluate stream number
- 0665 Check "m" parameters
- 0685 Check "m" parameters and filename
- 068F Check station number
- 06A3 Evaluate "x";n;"name"
- 06B0 Check baud rate
- 06B9 Evaluate stream or expression
- 0700 UNPAGE
- 0701 Evaluate parameters
- 082F SAVE command syntax routine
- 0880 Save a byte to network or RS232 link
- 0894 LOAD command syntax routine
- 089E VERIFY command syntax routine
- 08A8 MERGE command syntax routine
- 08AF LOAD-VERIFY-MERGE commands routine
- 0A5C LOAD or VERIFY
- 0A95 Load "run" program
- 0AC9 Set "BAUD" system variable
- 0AEF RS232 timing constants
- 0B13 Open RS232 channel in CHANS area
- 0B47 Attach channel to a stream
- 0B64 "T" channel data
- 0B6F "T" channel input
- 0B75 "B" channel input
- 0B7B "T" channel input service routine
- 0B81 "B" channel input service routine
- 0C3C "T" channel output
- 0C5A "B" channel output
- 0CA9 Border colour restore
- 0CB4 Break into I/O operation
- 0CBD CALL-INP
- 0D0C "N" channel input
- 0D12 "N" channel input service routine
- 0D6C "N" channel output
- 0D93 OUT-BLK-N
- 0DAB S-PACK-1
- 0DB2 SEND-PACK
- 0E0F BR-DELAY
- 0E18 Header and data block receiving
- 0EA3 OPEN "N" channel command routine
- 0EA9 Open temporary "n" channel
- 0EB5 Open permanent "n" channel
- 0EEA "N" channel data
- 0EF5 Send EOF block to network
- 0F03 Network state
- 0F0E Check-resting
- 0F1E Wait-scout
- 0F61 Send-scout
- 0F92 INPAK
- 0FBE Send response byte
- 0FC5 OUTPAK
- 0FE8 Set a temporary "m" channel
- 10C4 Reclaim "m" channel
- 1122 "M" channel input
- 112C "M" channel input service routine
- 1177 Get a record
- 11A5 Get header and data block
- 11D8 "M" channel output
- 11FF Write record onto Microdrive
- 1264 CHK-FULL
- 1275 SEND-BLK
- 12A6 Close file
- 12BE ERR-RS
- 12C4 Fetch header from Microdrive
- 12DA Check map bit state
- 12FF Reset bit in map area
- 1306 Check 'pseudo-map' bit state
- 1312 Decrease sector counter
- 131E CHECK-NAME
- 1341 Calculate/compare checksums
- 135F Restore stream data
- 1391 Restore map addresses
- 13CC "M" channel data
- 13E5 Preamble data
- 13F1 MOVE command
- 1455 Use stream or temporary channel
- 14A4 Close 'MOVE' channel
- 14C7 Exchange DSTR1 and STR2 contents
- 14DA Save data block into Mlcrodrive
- 1580 Get header information from Microdrive
- 15A9 Load or verify block from Microdrive
- 1613 Save Microdrive Map contents
- 162D Restore Microdrive Map contents
- 1648 LD-VE-M
- 1666 Fetch record from Microdrive.
- 1691 Restore address of filename
- 1708 CLOSE STREAM
- 1718 CLOSE command
- 17B9 Reclaim temporary channels
- 17F7 Select drive motor
- 1867 1 millisecond delay
- 1872 Send data block to Microdrive Head
- 18A3 Receive block from Microdrive Head
- 18E9 TEST-BRK
- 18FA DELAY-BC
- 1902 UNKN-1
- 196C UNKN-8
- 1981 HOOK-CODE
- 19A4 Hook code +32
- 19A8 Hook code +31
- 19A9 Hook code addresses
- 19D9 Console input
- 19EC Console output
- 19FC Printer output
- 1A01 Keyboard test
- 1A09 Read sequential
- 1A17 Read random
- 1A24 Close network channel
- 1A31 Get packet from network
- 1A4B Read sector
- 1A86 Read next sector
- 1A91 Write sector
- 1AE0 Clear buffer contents
- 1AF0 Open a permanent "m" channel
- 1B29 Open a temporary "m" channel
- 1B6E FORMAT "m" command
- 1C58 CAT command
- 1D38 FREESECT
- 1D59 PRNAME
- 1D66 PRCHAR
- 1D6E ERASE command
- 1E3E Signal 'free sector'
- 1E53 Obtain record descriptor
- 1E66 Calls to the command routines
- 1E87 DISP-HEX
- 1E9E DISP-HEX2
- 1EA9 DISP-CH
- 1ECE HEX-LINE
- APPENDIX 7
- Shadow ROM issue 2
- The new ZX Interface 1's with serial number greater than 87315 have been provided with a new shadow ROM, with some \
- general improvements.
- The Spectrums fitted with the 'new' interface will print '80' in response to the command 'PRINT PEEK 23729'.
- The main changes may be summed up as follows:
- The TCHAN-OUT subroutine ("t" channel output routine) has been remarkably improved; the TAB function now is supported, \
- as well as the 'comma' control code, and the 'leading space' bug has been corrected. The whole subroutine is listed \
- below.
- 0C3A TCHAN-OUT CP +A5 Jump if the code is not a token
- 0C3C JR C,0C44,NOT-TOKEN code.
- 0C3E SUB +A5 Reduce range of token.
- 0C40 RST 10,CALBAS And detokenise it by calling
- 0C41 DEFW +0C18 recursively this routine via main
- 0C43 RET ROM 'PO-TOKENS' routine.
- 0C44 NOT-TOKEN LD HL,+5C3B This is FLAGS.
- 0C47 RES 0,(HL) Reset 'leading space' flag.
- 0C49 CP +20 Is the character a space?
- 0C4B JR NZ,0C4F,NOT-LEAD Jump if it is not.
- 0C4D SET 0,(HL) Otherwise set 'leading space' flag.
- 0C4F NOT-LEAD CP +7F Jump if the character is not
- 0C51 JR C,0C55,NOT-GRAPH a 'graphic' character.
- 0C53 LD A,+3F Otherwise print a '?'
- 0C55 NOT-GRAPH CP +20 Jump with codes lower than +20.
- 0C57 JR C,0C78,CTRL-CD
- 0C59 PUSH AF Save the character code.
- 0C5A INC (IY+118) Increment current print position.
- 0C5D LD A,(5CB1) Fetch line width.
- 0C60 CP (IY+118) Jump if the position is lower than
- 0C63 JR NC,0C6C,EMIT-CH or equal to the value of WIDTH.
- 0C65 CALL 0C74,NEWLINE Send CR and LF codes when pos>width.
- 0C68 LD (IY+118),+01 Reset 'print position' to +01.
- 0C6C ENIT-CH POP AF Restore character to be printed.
- 0C6D JP 0D07,BCHAN-OUT Print it.
- 0C70 CTRL-CD CP +0D Jump if the character is not 'CR'.
- 0C72 JR NZ,0C82,NOT-CR
- 0C74 LD (IY+118),+00 Clear print position.
- 0C78 LD A,+0D Print a CR code.
- 0C7A CALL 0D07,BCHAN-OUT
- 0C7D LD A,+0A Print a LF code.
- 0C7F JP 0D07,BCHAN-OUT
- 0C82 NOT-CR CP +06 Jump if the character is not the
- 0C84 JR NZ,0CA5,NOT-CMM 'comma' control code.
- 0C86 LD BC,(5CB0) Fetch width into B, and print
- position into C.
- 0C8A LD E,+00
- 0C8C SPC-COUNT INC E Increment space counter.
- 0C8D INC C Increment print position.
- 0C8E LD A,C Jump if 'position' reaches the
- 0C8F CP B right margin.
- 0C90 JR Z,0C9A,PRINT-SPC
- 0C92 CMM-LOOP SUB +08 Tabulate every 8 columns.
- 0C94 JR Z,0C9A,PRINT-SPC Jump when reached the right column.
- 0C96 JR NC,0C92,CMMLOOP Subtract again...
- 0C98 JR 0C8C,SPC-COUNT Column not reached, jump back.
- 0C9A PRINT-SPC PUSH DE Save space counter.
- 0C9B LD A,+20 Print the required number of spaces
- 0C9D CALL 0C3A,TCHAN-OUT by calling TCHAN-OUT recursively.
- 0CA0 POP DE Restore space counter.
- 0CA1 DEC E
- 0CA2 RET Z
- 0CA3 JR 0C9A,PRINT-SPC
- 0CA5 NOT-CNN CP +16 Jump with AT control code.
- 0CA7 JR Z,0CB5,TAB-PROC
- 0CA9 CP +17 Jump with TAB control code.
- 0CAB JR Z,0C5B,TAB-PROC
- 0CAD CP +19 Return with codes lower than 16d
- 0CAF RET C
- 0CB0 LD DE,+0CD0 Service routine for INK, PAPER
- 0CB3 JR 0CB8,STORE-COD ...control codes.
- 0CB5 TAB-PROC LD DE,+0CC8 Service routine for AT and TAB
- 0CB8 STORE-COD LD (TVDATA-lo),A Store first operand.
- 0CBB ALTER-OUT LD HL,(CURCHL) Fetch current channel address.
- 0CBE PUSH DE
- 0CBF LD DE,+0005 Point to 'output address' pointer.
- 0CC2 ADD HL,DE
- 0CC3 POP DE
- 0CC4 LD (HL),E Store new 'output' address.
- 0CC5 INC HL
- 0CC6 LD (HL),D
- 0CC? RET
- 0CC8 TAB-SERV LD DE,+0CD0 The new 'output' address.
- 0CCB LD (TVDATA-hi),A Store second operand.
- 0CCE JR 0CBB,ALTER-OUT Jump to change the 'output' address.
- 0CD0 LD DE,+0C3A Restore the normal 'output' address.
- 0CD3 CALL 0CBB,ALTER-OUT
- 0CD6 LD D,A Pass 'second operand' to D.
- 0CD7 LD A,(TVDATA-lo) Fetch first operand (code type).
- 0CDA CP +16 Jump with AT.
- 0CDC JR Z,0CE6,TST-WIDTH
- 0CDE CP +17 Return unless the code is TAB.
- 0CE0 CCF
- 0CE1 RET NZ
- 0CE2 LD A,(TVDATA-hi) Fetch TAB column.
- 0CE5 LD D,A Move it into D.
- 0CE6 TST-WIDTH LD A,(5CB1) Fetch line width.
- 0CE9 CP D
- 0CEA JR Z,0CEE,TAB-MOD Jump if TAB is at last column.
- 0CFC JR NC,0CF4,TABZERO Jump if TAB is within range.
- 0CEE TAB-MOD LD B,A Fetch column width.
- 0CEF LD A,D Fetch TAB column.
- 0CF0 SUB B A=TAB-WIDTH
- 0CF1 LD D,A The new position.
- 0CF2 JR 0CE6,TST-WIDTH Take (TAB pos.) MOD (width).
- 0CF4 TABZERO LD A,D Fetch TAB column.
- 0CF5 OR A New line with TAB 0.
- 0CF6 JP Z,0C74,NEWLINE
- 0CF9 TABLOOP LD A,(5CB0) Fetch current print position.
- 0CFC CP D Return if already at the..
- 0CFD RET Z ..TAB position.
- 0CFE PUSH DE
- 0CFF LD A,+20 Print the TAB spaces.
- 0D01 CALL 0C3A,TCHAN-OUT
- 0D04 POP DE
- 0D05 JR 0CF9,TABLOOP
- You should note that variable line width is allowed by POKEing the required value into the location 23729; the default \
- value is 80.
- Other important alterations concern with Microdrive reading operations (i.e. channel opening, CAT command); the number \
- of sectors examined is not fixed to 255, but is given by 'maximum sector number + 3'; this prevents the routine from \
- reading 'nonexistent' sectors, and reduces the time required in the command execution.
- The checking operation done by the FORMAT command routine is now made directly with OUT instructions, without using \
- the Microdrive channel to send/receive the blocks containing 'test data'.
- Other minor changes are:
- - The OP-RS-CH routine stores the "B" specifier into (IX+4) when opening a RS232 "b" channel.
- - Most of the tests done to the BREAK key have been replaced by calls to the TEST-BRK subroutine at +163E.
- - The carry flag is preserved when calling the BORD-REST subroutine at +0D4D; thus, the 'hook code' +2F works correctly.
- - When a "m" or "n" channel is created in the CHANS area (OP-PERM-N and SET-T-MCH), a check is made to see if there is \
- sufficient memory to insert the new space.
- - The GET-M-HD subroutine, returns (with bit 0 of HDFLAG or RECFLG inverted) when 'time-out' occurs during the reading \
- operation.
- - An instruction 'SET 7,(HL)' has been inserted at location +1741 (i.e. the middle of the CLOSE routine), to correct \
- the bug present in the 'old' shadow ROM (see comment to the CLOSE routine).
- - No CR code is sent when a RS232 'b" channel is closed.
- - The 'hook code' +2B calls the SET-T-MCH subroutine.
- - Two new 'hook codes', +33 and +34, are now available. Hook code +33 may be used to fetch a 'record descriptor' from \
- the next sector; the microdrive motor must be turned on before calling the routine. The record descriptor is stored \
- into the current microdrive channel (whose start address must be held into the IX index register), and the carry flag \
- is returned set if any error occurs, or if the 'record descriptor' holds a filename starting wIth CHR$ 0. Hook code \
- +34 opens a RS232 "b" channel by calling the OP-RS-CH subroutine. The channel base address is returned into the DE \
- register pair.
- APPENDIX 8
- How to tell which edition Interface 1 you have
- There are two different versions of the ZX Interface, each having a slightly different program in its ROM. It is \
- important that you know which version of the ROM you have, and you can find this out in the fo5lowing manner:
- Run the following line of BASIC:
- CLOSE # 0: PRINT PEEK 23729
- If this prints out a '0', then you have an edition 1 Interface 1. if it prints out '80', you have an edition 2 \
- Interface 1.
- There is the possibility that Sinclair Research may release a third edition of the Shadow ROM, with a few more \
- changes. If you should get one of these, the extended BASIC commands may not work properly with it. The 'PRINT PEEK \
- 23729'
- test probably wont distinguish between the edition 2 and edition 3 Shadow ROMs, You can, however, upload the Shadow \
- ROM into a higher area of RAM, disassemble it there, and compare the code to the listings given in this book. The \
- following
- program will load the Shadow ROM into RAM from 32768 to 48968:
- ORG 34000
- LD HL,LABEL
- LD (23789),HL
- RST 08
- DEFB 32H
- LABEL POP HL
- POP HL
- LD HL,0
- LD DE,32768
- LD BC,8192
- LDIR
- RST 0
- RET
- To do the same thing from BASIC, use the following program:
- 10 CLEAR 26000
- 20 FOR X=54000 TO 54022
- 30 READ Y
- 40 POKE X,Y
- 50 NEXT X
- 60 RAND USR 54000
- 70 DATA 33,248,210,34,237,92,207,50,225,225
- 80 DATA 33,0,0,17,0,128,1,0,32,237,176,199,201
- For information on how to make the extended BASIC commands work with edition 3 or later Shadow ROMs, refer to Appendix \
- 11, page 165.
- APPENDIX 9
- Basic loader program
- for edition 2 Shadow ROM
- (For owners of Interface 1s equipped with the edition 2 Shadow ROM.)
- Here is the new BASIC loader program, changed to run with the new shadow ROM. To enter the new BASIC commands into \
- your Spectrum without using an assembler, enter the following BASIC loader program.
- 1 CLEAR 63743
- 10 FOR A=63744 TO 65951 STEP 12
- 20 PRINT "ADDRESS:";A'
- 30 LET C=0
- 40 FOR B=1 TO 12
- 50 LET Z=A+B-1: IF Z<=65051 THEN INPUT X: PRINT X: POKE Z,X: LET C=C+X
- 60 NEXT B
- 70 PRINT '"CHECKSUM=";C
- 80 INPUT "THIS IS WRONG ? (Y/N) "; LINE Y$: IF CODE Y$=80 OR CODE Y$=121 THEN PRINT "Retype from address ";A: PAUSE \
- 100: CLS : GO TO 20
- 90 IF CODE Y$<>78 AND CODE Y$<>110 THEN GO TO 80
- 100 CLS: NEXT A
- 110 PRINT "Saving the program"
- 120 SAVE *"M";l;"SHADP" CODE 63744,1308
- When you have finished typing this program into your Spectrum, you should 'RUN' it. You should then type from the \
- listing on the next page, the 12 bytes from the address shown on the screen. When you have typed the first 12 bytes, a \
- 'checksum' should be displayed on the screen; if it matches the one printed on the listing, at the right hand side of \
- the line, then you have made no mistakes in typing the numbers, and you may enter 'N' or 'n' to continue with the next \
- line. If the checksums do not match, you must enter 'Y' or 'y', and then retype the whole line.
- When all numbers have been entered, the program will automatically be saved on Microdrive cartridge (there must be a \
- cartridge with at least 2K free in Microdrive 1). If you wish to save the program on tape, line 120 of the listing \
- should be modified appropriately. When at some 1ater time you wish to use the routines, you have simply to place the \
- cartridge in Microdrive 1, and then to enter the following direct commands:
- CLEAR 63743: LOAD *"M";1;"SHADP" CODE: RANDOMIZE USR 63744
- and the new comnands should be available. Note that if you use the NEW command, you should then give the direct \
- command 'RANDOMISE USR 63744' to reinitialise the VECTOR system variable.
- Here is the data for the new Shadow ROM:
- 63744: 207 49 33 9 249 34 183 92 201 215 24 0 1296
- 63756: 254 244 202 45 249 254 42 202 114 249 254 215 2384
- 63768: 202 11 250 254 227 202 188 251 254 229 202 12 2282
- 63780: 252 254 224 202 175 252 195 240 1 215 32 0 2042
- 63792: 254 42 194 75 249 215 121 28 205 183 5 215 1786
- 63804: 153 30 197 215 153 30 197 225 193 113 35 112 1653
- 63816: 195 193 5 215 130 28 254 44 194 240 1 215 1714
- 63828: 32 0 215 140 28 205 183 5 215 241 43 197 1504
- 63840: 213 215 153 30 80 89 223 193 120 177 202 193 1890
- 63852: 5 237 176 195 193 5 215 32 0 254 207 202 1721
- 63864: 102 250 246 32 254 108 194 197 249 215 32 0 1879
- 63876: 215 130 28 205 183 5 215 153 30 96 105 124 1489
- 63888: 205 214 20 125 205 214 20 62 32 205 248 20 1570
- 63900: 229 6 6 197 126 205 237 20 35 16 249 193 1519
- 63912: 225 126 230 127 254 32 56 6 254 128 48 2 1488
- 63924: 24 2 62 32 205 248 20 35 16 235 62 13 954
- 63936: 205 248 20 24 202 254 101 194 240 1 215 32 1736
- 63948: 0 215 130 28 205 183 5 215 153 30 253 203 1620
- 63960: 12 126 202 240 1 120 230 192 194 240 1 237 1795
- 63972: 67 73 92 237 123 61 92 33 7 250 229 42 1306
- 63984: 61 92 229 33 127 16 229 237 115 61 92 253 1545
- 63996: 54 0 255 215 169 15 33 56 15 229 199 225 1465
- 64008: 195 180 18 215 32 0 254 42 194 240 1 215 1586
- 64020: 121 28 254 44 194 240 1 215 121 28 205 183 1634
- 64032: 5 215 148 30 245 215 148 30 167 40 54 79 1376
- 64044: 6 0 197 215 148 30 167 40 44 79 6 0 932
- 64056: 197 215 153 30 197 205 0 7 225 209 193 241 1872
- 64068: 229 245 197 229 213 205 181 3 209 225 193 241 2370
- 64080: 167 237 66 48 240 61 225 32 235 33 193 5 1542
- 64092: 34 237 92 207 50 253 54 0 0 239 215 32 1413
- 64104: 0 205 30 6 205 183 5 205 109 6 62 2 1018
- 64116: 215 1 22 205 165 16 221 126 25 205 50 21 1272
- 64128: 205 169 19 33 9 251 17 24 0 205 5 251 1188
- 64140: 205 38 20 32 239 33 9 251 203 70 32 232 1364
- 64152: 58 9 251 33 12 251 182 230 2 194 169 250 1641
- 64164: 205 227 19 24 215 58 13 251 183 40 209 58 1502
- 64176: 10 251 183 32 203 221 126 41 221 190 13 40 1531
- 64188: 22 205 33 251 205 0 251 221 126 13 183 194 1704
- 64200: 128 250 221 126 41 221 119 13 195 128 250 221 1913
- 64212: 229 175 205 50 21 205 0 251 221 229 225 17 1828
- 64224: 44 0 25 205 178 251 205 0 251 205 67 29 1460
- 64236: 123 203 63 215 40 45 215 227 45 205 0 251 1632
- 64248: 221 225 205 159 17 195 193 5 62 13 195 113 1603
- 64260: 29 229 195 242 21 0 0 0 0 0 0 0 716
- 64272: 0 0 0 0 0 0 0 0 0 0 0 0 0
- 64284: 0 0 0 0 0 33 140 92 54 255 33 13 620
- 64296: 251 205 178 251 62 32 205 113 29 58 9 251 1644
- 64308: 203 87 194 62 251 62 245 195 113 29 33 24 1498
- 64320: 251 126 183 202 99 251 254 3 202 157 251 61 2040
- 64332: 245 62 228 205 113 29 58 29 251 230 31 198 1679
- 64344: 96 205 113 29 241 200 62 36 195 113 29 33 1352
- 64356: 32 251 126 230 192 192 43 62 202 205 113 29 1677
- 64368: 94 35 86 235 17 16 39 205 143 251 17 232 1370
- 64380: 3 205 143 251 17 100 0 205 143 251 17 10 1345
- 64392: 0 205 143 251 17 1 0 62 255 60 183 237 1414
- 64404: 82 48 250 25 246 48 195 113 29 62 175 205 1478
- 64416: 113 29 35 229 35 35 205 112 251 62 44 205 1355
- 64428: 113 29 225 195 112 251 6 10 126 205 113 29 1414
- 64440: 35 16 249 201 215 32 8 254 35 194 240 1 1472
- 64452: 215 121 28 205 183 5 215 148 30 245 215 148 1758
- 64464: 30 254 16 210 99 6 215 1 22 221 42 81 1197
- 64476: 92 221 126 4 254 77 194 45 6 221 203 24 1467
- 64488: 70 194 13 18 241 221 119 13 221 126 25 205 1466
- 64500: 50 21 33 255 0 34 201 92 205 95 18 175 1179
- 64512: 221 119 11 221 119 12 205 50 21 195 193 5 1372
- 64524: 215 32 0 215 130 28 205 183 5 215 148 30 1406
- 64536: 254 16 210 99 6 215 1 22 221 42 81 92 1259
- 64548: 221 126 4 254 77 194 45 6 221 203 24 70 1445
- 64560: 194 6 9 221 126 25 205 50 21 33 255 0 1145
- 64572: 34 201 92 205 128 18 56 19 40 14 221 203 1231
- 64584: 67 78 40 11 221 126 41 221 119 13 24 3 964
- 64596: 205 227 19 205 247 19 32 227 219 239 230 1 1870
- 64608: 202 185 31 205 63 31 218 126 18 221 110 69 1479
- 64620: 221 102 70 221 117 11 221 116 12 221 203 24 1539
- 64632: 198 205 73 30 205 169 19 221 126 13 221 190 1670
- 64644: 41 32 245 62 230 211 239 1 104 1 205 82 1453
- 64656: 22 221 229 225 17 55 0 25 205 179 21 62 1261
- 64668: 238 211 239 205 227 19 221 126 68 221 119 13 1907
- 64680: 175 205 50 21 195 193 5 215 32 0 254 33 1378
- 64692: 40 11 254 47 40 33 254 63 40 54 195 240 1271
- 64704: 1 215 121 28 205 183 5 215 148 30 167 202 1520
- 64716: 250 253 50 21 254 215 148 30 61 50 20 254 1606
- 64728: 195 193 5 215 121 28 205 183 5 215 148 30 1543
- 64740: 50 22 254 215 148 30 50 23 254 175 50 27 1298
- 64752: 254 195 193 5 215 32 0 215 130 28 205 183 1655
- 64764: 5 215 148 30 254 1 40 12 62 3 253 203 1226
- 64776: 124 142 205 24 23 195 193 5 62 3 215 39 1230
- 64788: 23 33 17 0 167 237 66 218 47 5 205 23 1041
- 64800: 11 213 33 5 0 25 17 53 253 115 35 114 874
- 64812: 62 3 50 216 92 209 195 81 11 254 165 211 1548
- 64824: 62 12 253 203 1 134 254 32 56 91 32 4 1134
- 64836: 253 203 1 198 245 62 1 50 24 254 241 254 1786
- 64848: 127 56 2 62 63 205 7 13 58 20 254 71 938
- 64860: 58 19 254 184 48 5 60 50 19 254 201 205 1357
- 64872: 111 253 175 50 24 254 201 62 1 50 24 254 1459
- 64884: 61 50 19 254 58 25 254 167 196 7 13 58 1162
- 64896: 26 254 167 196 7 13 58 23 254 71 58 27 1154
- 64908: 254 60 184 32 0 58 22 254 167 196 7 13 1255
- 64920: 175 50 27 254 201 254 13 32 12 58 24 254 1354
- 64932: 167 62 1 50 24 254 200 24 194 254 6 32 1268
- 64944: 33 42 19 254 58 21 254 71 14 0 12 44 822
- 64956: 125 188 48 167 144 40 4 48 251 24 243 197 1479
- 64968: 62 32 205 53 253 193 13 32 246 201 254 23 1567
- 64980: 192 17 226 253 42 81 92 6 5 9 115 35 1073
- 64992: 114 201 50 15 92 17 234 253 24 238 17 53 1308
- 65004: 253 205 216 253 58 15 92 71 58 20 254 184 1679
- 65016: 48 5 253 54 0 10 239 58 19 254 144 200 1284
- 65028: 48 5 237 68 79 24 188 197 205 111 253 193 1608
- 65040: 72 24 180 0 80 20 12 60 1 13 10 0 472
- APPENDIX 10
- Extended BASIC commands from assembler for edition 2 Shadow ROM
- (For owners of Interface 1s equipped with the edition 2 Shadow ROM.)
- To add the extended BASIC commands to your Spectrum, if you own an edition 2 Shadow ROM and an assembler, first enter \
- the assembly program on pages 12 to 32 into your Spectrum. Do not enter the table of EQU statements that follows on \
- page 33. These labels all refer to the edition 1 Shadow ROM, and are not relevant to edition 2. Instead, for each \
- label given on page 33, enter the value given in the alphabetical list of Shadow ROM 2 labels which follow. When you \
- have entered this program and assembled it, save it onto Microdrive or tape. To use the new BASIC commands, load the \
- machine code file you have made into your Spectrum at 63744 (F900 Hex), and give the direct command 'RANDOMISE USR \
- 63744'. The new commands should then be available.
- Below is an alphabetical list of the labels related to the edition 2 shadow ROM.
- ACC-CODE 0D8A ALL-BITS 102F ALL-BYTES 05A7 ALL-CHARS 1407
- ALL-MOTRS 1570 ALL-STRMS 058E ALLCHR-2 1418 ALTER-OUT 0CBB
- B-INPUT 0B7C BCHAN-IN 0B88 BCHAN-OUT 0D07 BD-DEL-1 0D1C
- BD-DEL-2 0D32 BD-DEL-3 0D48 BD-DELAY 0BD8 BD-DELAY2 0C1D
- BF-FILLED 1CFF BORD-REST 0D4D BR-DELAY 0EAC BRCAST 0EDD
- BREAK-PGM 05E2 CALBAS 0010 CALBAS-2 0081 CALL-INP 0D5A
- CAT 1C52 CAT-LP 1C68 CAT-LP-E 1C77 CAT-RUN 1AB5
- CAT-SCRN 04A6 CAT-SYN 0486 CHAN-SPC 10F1 CHECK-M 0665
- CHECK-M-2 066D CHECK-MAP 13C4 CHECK-N 1883 CHECK-R 188F
- CHECK-SP 0077 CHK-AG-2 1608 CHK-AGAIN 15F6 CHK-FULL 1349
- CHK-LOOP 10B3 CHK-LP-2 160F CHK-M-EOF 1233 CHK-MAP-2 13BF
- CHK-NAME 1403 CHK-NSECT 1C1E CHK-PRES 154E CHK-REST 0FC7
- CHK-SCT 1BF6 CHK-SCT2 1C05 CHK-TEMPM 17D0 CHK-TEMPN 17DC
- CHK-W-MAP 1E3A CHKEND 015D CHKEND-L 0169 CHKEVEN 0165
- CHKLOOP 15FD CHKS-ALL 142E CHKS-BUFF 142B CHKS-HD-R 1426
- CHKS1 0E62 CHKS2 0E71 CHKS3 0EC4 CHKS4 0F24
- CHKSYNTAX 0018 CKNAM-END 1423 CL-CHAN 18A8 CL-CHK-N 18BC
- CL-M-CH 176B CL-N-CH 175C CL-WORK 01AA CLAIMED 0FD9
- CLOSE 1718 CLOSE-CH 1708 CLOSE-M 138B CLOSE-M2 138E
- CLOSE-NET 1F18 CLR#-SYN 057F CLR-BUFF 1FD4 CLR-ERR 1E77
- CLS#-SYN 0559 CMM-LOOP 0C92 CODE 0789 CONS-IN 1ECD
- CONS-OUT 1EE0 CONV-1 14E7 COPYCHADD 00FB CP-NAME 1300
- CRT-NEW 09F7 CRT-VARS 01F7 CTRL-CD 0C70 DATA 07D2
- DEC-SECT 13F7 DEFAULT 0224 DEFLT-0 079A DEL-B-CT 1F75
- DEL-M-BUF 119F DEL-O-1 1087 DEL-S-1 15A2 DELAY-BC 1652
- DELAY-BC1 1653 DELAY-SC 101A DISP-CH 14F8 DISP-HEX 14D6
- DISP-HEX2 14ED DISP-NIB 14DF DL-LOOP 0EAF DR-READY 1620
- E-READ-N 100A EACH-ST 0152 EACH-VAR 025A EMIT-CH 0C6C
- END-CODE 07B8 END-DATA 081C END-EXPT 0750 END-INPUT 0D94
- END-LD-PR 0A13 END-PR-MS 02B4 END-RS-IN 0C34 END-S-DEL 104C
- END-SA-DR 196A END-SET 0AE8 END1 05C1 ENDC 1AC9
- ENDHERE 06CC ENDRD 16AD ENTRY 13C7 ENTRY-2 17C0
- ERASE 1D79 ERASE-1 1D8A ERASE-2 1DC3 ERASE-LP 1DA7
- ERASE-MK 1E03 ERASE-MK2 1E06 ERASE-RUN 1AAB ERASE-SYN 0531
- ERR-6 01F0 ERR-RS 13A3 ERR-V 01EC EX-CHANS 17C0
- EX-D-STR 059F EXISTING 07F2 EXPT-EXP1 06B9 EXPT-EXPR 06A3
- EXPT-NAME 062F EXPT-NUM 061E EXPT-PRMS 0701 EXPT-SPEC 05F2
- EXPT-STR 05E7 EXPT-STRM 064E F-ERROR 1A7B F-HD-2 1982
- F-HD-3 198A F-M-HEAD 1971 F-N-SCT 1CF4 F-REC1 1A57
- F-REC2 1A5D FAILED 1362 FETCH-ERR 0276 FILL-MAP 1163
- FOR-B-T 04CD FOR-M 04E7 FOR-RUN 1ABA FORMAT 185D
- FORMAT-1 1B75 FR-S-LPB 1D51 FR-S-RES 1D55 FR-SC-LP 1D4D
- FREESECT 1D43 FRMT-SYN 04B4 G-HD-RC 1280 G-RDES 1E5E
- G-REC-ERR 12B1 G-TYPE 07F6 GET-DESC 1FE4 GET-M-BLK 15F2
- GET-M-BUF 15EB GET-M-HD 15E2 GET-M-HD2 13A9 GET-N-BUF 0DDC
- GET-NBLK 0EB5 GET-NBUFF 0F02 GET-PACK 1F25 GET-R-2 1258
- GET-R-LP 125F GET-RECD 1252 GETBF-END 0F3E GETNB-END 0EFF
- GP-ERROR 1F3A HD-LOOP 0854 HEX-LINE 151D HEX-LINE2 1522
- HOOK-31 1E98 HOOK-32 1E94 HOOK-CODE 1E71 I-AGAIN 181E
- IN-AGAIN 0D78 IN-CHK 1E49 IN-M-BLK 1633 IN-NAME 1C8B
- INC-BLKN 0E9A INCREC 1F08 INKEY$ 0D98 INPAK 104F
- INPAK-2 105A INPAK-L 105B INS-NAME 1CDA INT-SERV 0038
- KBD-TEST 1EF5 LCHAN 1482 LD-BLK-2 0936 LD-BLK-3 0945
- LD-BLK-4 0956 LD-BLK-5 095D LD-BLOCK 091D LD-DATA 080E
- LD-HD-NET 08E4 LD-HD-RS 08EB LD-HDR-2 08F0 LD-HEADER 08DC
- LD-NO-PGM 0966 LD-PR-AR 09A7 LD-PROG 09B9 LD-VE-M 1A39
- LD-VF-MR 08B3 LINE 073E LINE-LEN 0144 LOAD-RUN 0A99
- LOAD-SYN 0898 LOOK-MAP 19EA LP-B-MAP 1DF4 LP-P-MAP 1DF0
- LP-SCOUT 1015 LPEND 14A6 LV-ANY 0A60 LV-B 0A7D
- LV-BN 0A6E LV-BN-E 0A82 LV-MCH 199A LV-N 0A76
- LVBN-END 0A93 M-AGAIN 1818 M-INPUT 11FD MAIN-ROM 0000
- MAKE-PERM 1AE9 MAKESURE 0FCA MARK-FREE 1C40 MCHAN-IN 1207
- MCHAN-OUT 12B3 MERGE-BLK 096B MERGE-END 09A4 MISSING-D 0494
- MK-BLK 1C4D MOVE 17F5 MOVE-EOF 1832 MOVE-NA 1CDE
- MOVE-OUT 1827 MOVE-RUN 1AB0 MOVE-SYN 053D MRG-SYN 08AC
- N-ACTIVE 1051 N-INPUT 0DA9 NCHAN-IN 0DAF NCHAN-OUT 0E09
- NET-STATE 0FBC NEW-BUFF 123D NEW-NAME 18ED NEWVARS 0030
- NEXT-CHAN 10E7 NEXTNUM 01A5 NMINT-SRV 0660 NO-AUTO 0A52
- NO-AUTOST 0977 NO-FOR-M 04BF NO-GOOD 1F45 NO-M-ARR 07DA
- NO-NAME 0716 NO-PRT 1374 NO-READ 0D87 NOEMP 139B
- NOFULL 12FC NOINC-C 1DF8 NONAMES 1D27 NONS-BSC 07F4
- NONSENSE 0584 NOPRES 155B NOREAD 12C1 NOT-CMM 0CA5
- NOT-CR 0C82 NOT-FOR-B 04D3 NOT-GRAPH 0C55 NOT-LEAD 0C4F
- NOT-NET 0722 NOT-OP-B 051F NOT-OP-M 0500 NOT-PROT 15BF
- NOT-RECV 1FF1 NOT-TOKEN 0C44 NOTRIGHT 145C NREPORT-1 0139
- NREPORT-2 0663 NREPORT-3 062D NREPORT-4 064C NREPORT-5 0681
- NREPORT-8 06A1 NREPORT-9 0683 NREPORT-L 0934 NREPORT-N 0906
- NUM-ARR 0819 NXT-1 01A3 NXT-B-MAP 1351 NXT-BYTE 1431
- NXT-ENTRY 0AD4 NXT-MOTOR 1597 NXT-SCT 1279 NXT-STRM 144A
- NXTCHAN 11E5 OFF-MOTOR 1586 OP-B-CHAN 1FF6 OP-CHAN 186A
- OP-F-1 1B16 OP-F-2 1B41 OP-F-3 1B46 OP-F-4 1B49
- OP-F-5 1B5B OP-F-X 1B26 OP-M-C 0529 OP-M-STRM 1ACC
- OP-PERM-N 0F52 OP-RS-CH 0B17 OP-RSCHAN 0B4E OP-RUN 1ABF
- OP-STREAM 0B51 OP-STRM 1859 OP-TEMP-M 1B05 OP-TEMP-N 0F46
- OPEN-N-ST 0F40 OPEN-RS 051C OPEN-SYN 04ED ORD-NAM 1CC1
- OREP-1-2 073C OREPORT-1 04B2 OREPORT-8 0D82 OT-NAMS 1D22
- OUT-BLK-N 0E30 OUT-CODE 1EE3 OUT-M-BLK 15B7 OUT-M-BUF 15B3
- OUT-M-BYT 15D0 OUT-M-HD 15AD OUTMEM 0F9E OUTMEM2 119A
- OUTPAK 1082 OUTPAK-L 1089 PAR-1 079F PAR-2 07B2
- PR-REP-LP 02A7 PRCHAR 1D71 PREP-MARK 1C35 PRINT-SPC 0C9A
- PRNAME 1D5B PRNM-LP 1D5E PROG 0753 PROG-LINE 0130
- PRT-OUT 1EF0 PT-N-CHAN 17EB RCL-T-CH 17B7 RCLM-CH 177D
- RCLM-MAP 11EF RCLM-NUM 0182 RCLM-OLD 09EC RD-BYT-1 1696
- RD-BYT-2 169D RD-BYT-3 16A5 RD-NEXT 1F7A RD-RANDOM 1F0B
- RD-SECTOR 1F3F RDLOOP1 165C RDLOOP2 165E RDLOOP3 1669
- RDLOOP4 166B RE-MAP 1A1E RE-MAP-LP 1A2E READ-BLK 165A
- READ-RS 0BAF READ-SEQ 1EFD READY-R2 1686 READY-RE 162A
- REC-BYTE 0B95 REC-PROC 0B98 REP-MSG 0260 REPTEST 154C
- RES-B-MAP 13E3 RES-VARS 0255 REST-MAP 1476 REST-N-AD 1A82
- REST-STRM 1444 RETAD-RUN 05DD RETAD-SYN 05E0 RMERR-2 0040
- ROMERR 0028 ROTATE 13DD RS-SH 1AC5 RS-SH2 11A3
- RUNTIME 011B RWF-ERR 1132 S-BLK-END 0881 S-PACK-1 0E48
- S-SC-DEL 103A S-STAT 016F SA-B-END 0895 SA-BLK-LP 0872
- SA-BLOCK 086E SA-BYTE 0884 SA-DRI-2 1921 SA-DRI-3 1929
- SA-DRI-4 194F SA-DRI-WR 1943 SA-DRIVE 18CB SA-HEADER 084F
- SA-MAP 1A04 SA-MAP-LP 1A11 SA-NET 0892 SAVE-M 0849
- SAVE-RUN 1AC4 SAVE-SYN 082F SC-L-LOOP 0133 SCOUT-END 1013
- SCREEN$ 0771 SE-NAME 1CA0 SEL-DRIVE 1532 SEND-BLK 135A
- SEND-NEOF 0FAE SEND-PACK 0E4F SEND-RESP 107B SEND-SC 101E
- SENDSCOUT 0E77 SEPARATOR 05B1 SER-IN2 0C1B SER-OUT-L 0D2C
- SERIAL-IN 0BD6 SET-BAUD 0ACD SET-PROG 0A19 SET-T-MCH 10A5
- SH-ERR 0020 SIGN-ERR 15DE SKIP-NUM 014E SP-DL-1 0E93
- SP-N-END 0EA2 SPC-COUNT 0C8C ST-BF-LEN 0E25 ST-END 05B7
- ST-ERROR 0068 ST-MAP-AD 1168 ST-SHADOW 0008 START-2 009A
- START-3 00A5 START-4 00BC START-BIT 0BCF STAR-SA 18D9
- STCHK 1439 STO-DISP 1463 STORE-COD 0CB8 STORE-DSP 1AFF
- STORE-LEN 0F30 SW-MOTOR 1565 SYNC-RD 167C T-CH-NAME 1135
- T-FURTHER 0BF7 T-INPUT 0B76 T-LD-NET 09E2 T-M-COOE 0915
- T-NA-1 1CAA T-NA-2 1CB5 T-OTHER 1E31 TAB-MOD 0CEE
- TAB-PROC 0CB5 TAB-SERV 0CC8 TABLOOP 0CF9 TABZERO 0CF4
- TCHAN-IN 0B82 TCHAN-OUT 0C3A TEST-BAUD 06B0 TEST-BLKN 0EE2
- TEST-BRK 163E TEST-BUFF 0DBB TEST-CODE 00E9 TEST-DTR 0D21
- TEST-LOW 013B TEST-N-BF 120F TEST-MAP 1143 TEST-MCHL 11D0
- TEST-MNAM 0685 TEST-NEXT 060C TEST-OUT 0E17 TEST-PMAP 13E8
- TEST-RET 05BF TEST-SAVE 07A7 TEST-SCT 1BDF TEST-SP 003A
- TEST-STAT 068F TEST-TYPE 08F6 TIME-OUT 0DFC TON-DELAY 1344
- TRY-AGAIN 0DE2 TS-L-NET 08D1 TS-L-RS 08D7 TST-AGAIN 0BC3
- TST-MERGE 0908 TST-MR-M 098C TST-MR-N 0998 TST-N-EOF 0DD5
- TST-NUM 1DE5 TST-PLACE 1A9D TST-SPACE 09C2 TST-TYPE 09CB
- TST-WIDTH 0CE6 TURN-ON 153D UNPAGE 0700 UNT-MARK 108F
- UNTIL-MK 106B UNTILFIVE 1A64 UPD-NXT-S 17A2 UPD-POINT 1469
- UPD-STRM 1787 USE-C-RC 1F57 USE-R 1899 USE-REC 19D0
- VAR~EXIST 023D VE-FAIL 1A55 VE-M-E 1A49 VERIFSYN 08A2
- VR-BN 0A8E VR-DATA 0803 WAIT-1 0BEE WAIT-2 0BEF
- WR-BLK 16AF WR-BYT-1 16C4 WR-BYT-2 16C8 WR-BYT-3 16CD
- WR-F-TEST 1BAB WR-RECD 12DA WR-S-1 1FA1 WR-S-2 1FB3
- WR-S-3 1FBB WR-SECTOR 1F85 WRITE-PRC 12EE WT-SC-E 0FD3
- WT-SCOUT 0FD6 WT-SYNC 0FED WTKEY 1ED2
- APPENDIX 11
- What to do if you have an unknown ROM
- If you should find that your Interface 1 contains a ROM which differs from both the edition 1 and the edition 2 Shadow \
- ROM, then the code to implement the extended BASIC commands that is given in this book will not work. This is because \
- the code that we have given contains a number of calls to routines in the Shadow ROM, which perform a number of useful \
- tasks, such as selecting Microdrives, reading a sector of tape, displaying hexadecimal numbers on the screen, etc. \
- Many of these routines are at different locations in the first two editions of the ROM, and presumably they would be \
- different again in any future ROMs.
- This does not, however mean that it is not possible for you to add the expanded BASIC commands to your machine. The \
- code that we have given is still quite correct, but the calls it makes to the ROM are no longer accurate. The \
- solution, then is to add to the extended BASIC commands routines of your own which have the same names as the ROM \
- routines, and will perform the same functions. This doesn't mean that you'll have to write all these routines - all \
- the code you need is contained in the Shadow ROM disassembly given earlier in this book. Simply find the routine you \
- need in the Shadow ROM disassembly, and copy it into your program. Consider the following example:
- The extended BASIC command '*L n' includes the following code:
- LD H,B ;move it into HL
- LD L,C
- AGAIN LD A,H ;display high byte of address in hex
- CALL DISP-HEX
- LD A,L ;display low byte
- This wont work as it stands, as it includes a call to the Shadow ROM routine DISP-HEX, and the address given for \
- DISP-HEX in the table of EQU statements will not be correct. What you should do to make this work is to remove the \
- entry for DISP-HEX from the EQU table, and then look up the entry for DISP-HEX in the alphabetical list of labels \
- (Appendix 2.). According to this, the DISP-HEX routine is at 1E87H. Look this up in the disassembly, and add the \
- routine you find (shown below) to the end of your program.
- DISP-HEX PUSH AF
- RRA
- RRA
- RRA
- RRA
- CALL DISP-NIB
- POP AF
- DISP-NIB AND 0FH
- CP 0AH
- JR C,CONV-1
- ADD A,7
- CONV-1 ADD A,30H
- CALL DISP-CH
- RET
- Note, however, that this routine makes its own call to another Shadow ROM routine, DISP-CH, which you will also have \
- to add to your code. DISP-CH is located at 1EA9 in the disassembly, and is as follows:
- DISP-CH PUSH HL
- PUSH DE
- PUSH BC
- PUSH AF
- EXX
- PUSH HL
- PUSH DE
- PUSH BC
- PUSH AF
- LD HL,(CURCHL)
- PUSH HL
- PUSH AF
- LD A,2
- RST CALBAS
- DEFW 1601H
- POP AF
- RST CALBAS
- DEFW 10H
- POP HL
- LD (CURCHL),A
- POP AF
- POP BC
- POP DE
- POP HL
- EXX
- POP AF
- POP BC
- POP DE
- POP HL
- RET
- Doing the same thing with all the other Shadow ROM calls should make it possible for you to run all the extended BASIC \
- commands. Note that the program, as it stands, fits into the very highest part of memory, with no room above it to \
- spare. The code you will be adding will make the extended commands somewhat longer. Because of this, you will have to \
- ORG your program to an earlier location, in order for it to fit into memory. Remember that when you initialise the new \
- commands from BASIC, you should no longer use
- RANDOMISE USR 63744
- but instead use
- RANDOMISE USR x
- where x is the location at which your assembler program is ORGed.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement